contentoh-components-library 21.6.35 → 21.6.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51,6 +51,7 @@ import { ProductImageModal } from "../../organisms/ProductImageModal";
51
51
  import { VersionSelector } from "../../organisms/VersionSelector";
52
52
  import { Modal } from "../../organisms/Modal";
53
53
  import { LinkVariantsModal } from "../../organisms/LinkVariantsModal";
54
+ import { UnlinkVariantModal } from "../../organisms/UnlinkVariantModal";
54
55
  import { PropagateChangesModal } from "../../organisms/PropagateChangesModal";
55
56
  import { readPayload } from "../../organisms/LinkVariantsModal/api";
56
57
 
@@ -186,6 +187,9 @@ const RetailerProductEditionView = ({
186
187
  const [family, setFamily] = useState(null);
187
188
  const [showFamily, setShowFamily] = useState(false);
188
189
  const [loadingVariant, setLoadingVariant] = useState(null);
190
+ // Qué vínculo se está por romper, o null si no hay diálogo abierto. Guarda al
191
+ // HIJO, que es quien lleva la relación y lo que pide la acción `unlink`.
192
+ const [porDesvincular, setPorDesvincular] = useState(null);
189
193
  // Por qué un salto no se pudo hacer. Vive aparte de `family.error` porque no
190
194
  // es un fallo al leer la familia, sino al abrir uno de sus miembros.
191
195
  const [avisoFamilia, setAvisoFamilia] = useState(null);
@@ -858,6 +862,69 @@ const RetailerProductEditionView = ({
858
862
  En ese caso no hay nada que abrir aquí, y se dice en vez de navegar a una
859
863
  pantalla que mostraría el producto equivocado.
860
864
  */
865
+ /*
866
+ Después de desvincular, esta ficha cambia de forma: si se soltó de su padre
867
+ vuelve a poder ligar, y si soltó a un hijo pierde uno de la cuenta. En esta
868
+ pantalla el bloque de parentesco se decide con `family`, así que hay que
869
+ repreguntarla —vaciarla lo haría desaparecer, que es el error que ya se
870
+ cometió una vez aquí—.
871
+ */
872
+ const handleOnUnlinked = (result) => {
873
+ if (!result) return;
874
+
875
+ const updatedProduct =
876
+ result.mode === "self"
877
+ ? { ...state.product, parentArticleId: null, variantsCount: 0 }
878
+ : {
879
+ ...state.product,
880
+ variantsCount: Math.max((state.product?.variantsCount ?? 1) - 1, 0),
881
+ };
882
+
883
+ dispatch({ type: "SET_PRODUCT", payload: updatedProduct });
884
+
885
+ // Se PARCHEA lo guardado: ahí vive el producto con la forma del listado
886
+ // —`article` anidado, servicios, cadenas— y escribir encima la versión
887
+ // aplanada de esta pantalla lo dejaría mutilado en el siguiente F5.
888
+ try {
889
+ const guardado = JSON.parse(
890
+ sessionStorage.getItem("productSelected") ?? "null"
891
+ );
892
+
893
+ if (guardado) {
894
+ sessionStorage.setItem(
895
+ "productSelected",
896
+ JSON.stringify({
897
+ ...guardado,
898
+ variantsCount: updatedProduct.variantsCount,
899
+ parentArticleId: updatedProduct.parentArticleId ?? null,
900
+ })
901
+ );
902
+ }
903
+ } catch (error) {
904
+ console.error("unlinkVariant/sessionStorage: ", error);
905
+ }
906
+
907
+ /*
908
+ Si ya no queda familia, se cierra el desplegable: su botón desaparece con
909
+ el vínculo, y dejarlo abierto pinta una caja que dice «no tiene hijos» y
910
+ que nadie puede cerrar.
911
+ */
912
+ if (
913
+ !updatedProduct.parentArticleId &&
914
+ (updatedProduct.variantsCount ?? 0) === 0
915
+ ) {
916
+ setShowFamily(false);
917
+ }
918
+
919
+ loadFamily(true);
920
+
921
+ // Al desvincular el servidor pone `is_overridden = 0` en todas las
922
+ // versiones, así que los chips de herencia tienen que dejar de dibujarse.
923
+ // Sin `enableLoading` para no parpadear el esqueleto encima de una pantalla
924
+ // que ya está pintada.
925
+ loadData(false);
926
+ };
927
+
861
928
  const openFamilyMember = async (articleId) => {
862
929
  setLoadingVariant(articleId);
863
930
  setAvisoFamilia(null);
@@ -1857,6 +1924,14 @@ const RetailerProductEditionView = ({
1857
1924
  onLinked={handleOnLinkedVariants}
1858
1925
  />
1859
1926
  )}
1927
+ {porDesvincular && (
1928
+ <UnlinkVariantModal
1929
+ {...porDesvincular}
1930
+ token={token}
1931
+ onClose={() => setPorDesvincular(null)}
1932
+ onUnlinked={handleOnUnlinked}
1933
+ />
1934
+ )}
1860
1935
  {showRejectModal && (
1861
1936
  <Modal
1862
1937
  title={
@@ -2117,43 +2192,90 @@ const RetailerProductEditionView = ({
2117
2192
  </p>
2118
2193
  )}
2119
2194
 
2195
+ {/* Desvincular se ofrece donde se ve el vínculo, y solo en la
2196
+ dirección que corresponde a esta ficha: desde un hijo, sobre
2197
+ su padre; desde un padre, sobre cada hijo. A un hermano no:
2198
+ para eso se abre su ficha. */}
2120
2199
  {family?.parent && (
2121
- <button
2122
- type="button"
2123
- className="family-row parent"
2124
- disabled={loadingVariant !== null}
2125
- onClick={() => openFamilyMember(family.parent.articleId)}
2126
- >
2127
- <span className="role">
2128
- {loadingVariant === family.parent.articleId
2129
- ? "Abriendo…"
2130
- : "Producto padre"}
2131
- </span>
2132
- <span className="name">{family.parent.name}</span>
2133
- <span className="upc">{family.parent.upc}</span>
2134
- </button>
2200
+ <div className="family-item">
2201
+ <button
2202
+ type="button"
2203
+ className="family-row parent"
2204
+ disabled={loadingVariant !== null}
2205
+ onClick={() => openFamilyMember(family.parent.articleId)}
2206
+ >
2207
+ <span className="role">
2208
+ {loadingVariant === family.parent.articleId
2209
+ ? "Abriendo…"
2210
+ : "Producto padre"}
2211
+ </span>
2212
+ <span className="name">{family.parent.name}</span>
2213
+ <span className="upc">{family.parent.upc}</span>
2214
+ </button>
2215
+
2216
+ <button
2217
+ type="button"
2218
+ className="desvincular"
2219
+ title="Dejar de ser hijo de este producto"
2220
+ onClick={() =>
2221
+ setPorDesvincular({
2222
+ mode: "self",
2223
+ childArticleId: state.product?.id_article,
2224
+ childName: state.product?.name,
2225
+ childUpc: state.product?.upc,
2226
+ parentName: family.parent.name,
2227
+ parentUpc: family.parent.upc,
2228
+ })
2229
+ }
2230
+ >
2231
+ Desvincular
2232
+ </button>
2233
+ </div>
2135
2234
  )}
2136
2235
 
2137
2236
  {family?.variants?.map((variant) => (
2138
- <button
2139
- key={variant.articleId}
2140
- type="button"
2141
- className={`family-row${
2142
- variant.isCurrent ? " current" : ""
2143
- }`}
2144
- disabled={variant.isCurrent || loadingVariant !== null}
2145
- onClick={() => openFamilyMember(variant.articleId)}
2146
- >
2147
- <span className="role">
2148
- {loadingVariant === variant.articleId
2149
- ? "Abriendo…"
2150
- : variant.isCurrent
2151
- ? "Estás aquí"
2152
- : "Hijo"}
2153
- </span>
2154
- <span className="name">{variant.name}</span>
2155
- <span className="upc">{variant.upc}</span>
2156
- </button>
2237
+ <div className="family-item" key={variant.articleId}>
2238
+ <button
2239
+ type="button"
2240
+ className={`family-row${
2241
+ variant.isCurrent ? " current" : ""
2242
+ }`}
2243
+ disabled={variant.isCurrent || loadingVariant !== null}
2244
+ onClick={() => openFamilyMember(variant.articleId)}
2245
+ >
2246
+ <span className="role">
2247
+ {loadingVariant === variant.articleId
2248
+ ? "Abriendo…"
2249
+ : variant.isCurrent
2250
+ ? "Estás aquí"
2251
+ : "Hijo"}
2252
+ </span>
2253
+ <span className="name">{variant.name}</span>
2254
+ <span className="upc">{variant.upc}</span>
2255
+ </button>
2256
+
2257
+ {/* Solo cuando esta ficha ES el padre: si hay `parent`, lo
2258
+ que se lista son hermanos. */}
2259
+ {!family.parent && !variant.isCurrent && (
2260
+ <button
2261
+ type="button"
2262
+ className="desvincular"
2263
+ title="Desvincular este hijo"
2264
+ onClick={() =>
2265
+ setPorDesvincular({
2266
+ mode: "child",
2267
+ childArticleId: variant.articleId,
2268
+ childName: variant.name,
2269
+ childUpc: variant.upc,
2270
+ parentName: state.product?.name,
2271
+ parentUpc: state.product?.upc,
2272
+ })
2273
+ }
2274
+ >
2275
+ Desvincular
2276
+ </button>
2277
+ )}
2278
+ </div>
2157
2279
  ))}
2158
2280
 
2159
2281
  {family && !family.error && !family.variants?.length && (
@@ -215,6 +215,36 @@ export const Container = styled.div`
215
215
  color: ${GlobalColors.gray};
216
216
  }
217
217
 
218
+ /* La fila es un botón que navega; desvincular tiene que quedar FUERA de
219
+ él —un botón dentro de otro no es HTML válido y el clic se confunde—. */
220
+ .family-item {
221
+ display: flex;
222
+ align-items: center;
223
+ gap: 4px;
224
+ }
225
+
226
+ .family-item .family-row {
227
+ flex: 1;
228
+ min-width: 0;
229
+ }
230
+
231
+ .desvincular {
232
+ flex-shrink: 0;
233
+ border: none;
234
+ background: none;
235
+ padding: 4px 6px;
236
+ cursor: pointer;
237
+ font-family: ${FontFamily.Raleway_500};
238
+ font-size: 10px;
239
+ color: ${GlobalColors.gray};
240
+ text-decoration: underline;
241
+ white-space: nowrap;
242
+ }
243
+
244
+ .desvincular:hover {
245
+ color: ${PINK};
246
+ }
247
+
218
248
  .family-row {
219
249
  display: flex;
220
250
  align-items: baseline;
package/src/index.js CHANGED
@@ -89,6 +89,7 @@ export * from "./components/organisms/ImagesGroup/index";
89
89
  export * from "./components/organisms/InputGroup/index";
90
90
  export * from "./components/organisms/LinkVariantsModal/index";
91
91
  export * from "./components/organisms/PropagateChangesModal/index";
92
+ export * from "./components/organisms/UnlinkVariantModal/index";
92
93
  export * from "./components/organisms/ProductImageModal/index";
93
94
  export * from "./components/organisms/Chat/index";
94
95
  export * from "./components/organisms/Modal/index";