contentoh-components-library 21.6.51 → 21.6.53
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.
- package/dist/components/organisms/PropagateChangesModal/index.js +6 -1
- package/dist/components/pages/ProviderProductEdition/context/provider-product-edition.context.js +10 -8
- package/dist/components/pages/ProviderProductEdition/index.js +154 -62
- package/dist/components/pages/RetailerProductEdition/context/provider-product-edition.context.js +11 -9
- package/dist/components/pages/RetailerProductEdition/index.js +160 -54
- package/package.json +1 -1
- package/src/components/organisms/PropagateChangesModal/index.js +10 -3
- package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx +2 -1
- package/src/components/pages/ProviderProductEdition/index.js +75 -3
- package/src/components/pages/RetailerProductEdition/context/provider-product-edition.context.jsx +2 -1
- package/src/components/pages/RetailerProductEdition/index.js +79 -3
|
@@ -742,14 +742,64 @@ const ProviderProductEditionView = ({
|
|
|
742
742
|
return soloPropagables(cambios);
|
|
743
743
|
};
|
|
744
744
|
|
|
745
|
+
/*
|
|
746
|
+
Lo que se acaba de editar en la pestaña de descripciones.
|
|
747
|
+
|
|
748
|
+
Va aparte de `cambiosDeFichaTecnica` porque son tablas distintas y el
|
|
749
|
+
endpoint recibe una lista o la otra. Aquí NO se filtran UPC ni SKU: esos son
|
|
750
|
+
atributos de ficha técnica y no aparecen en esta pestaña.
|
|
751
|
+
*/
|
|
752
|
+
const cambiosDeDescripciones = () => {
|
|
753
|
+
const retailerId = state.active_retailer?.id_retailer;
|
|
754
|
+
const inputs = state.services?.descriptions?.inputs ?? {};
|
|
755
|
+
|
|
756
|
+
return (state.updated_descriptions_inputs ?? []).map((item) => {
|
|
757
|
+
const input = inputs[`${item.attributeId}_${retailerId}`];
|
|
758
|
+
return {
|
|
759
|
+
id: Number(item.attributeId),
|
|
760
|
+
name: input?.name ?? `Descripción ${item.attributeId}`,
|
|
761
|
+
value: item.value,
|
|
762
|
+
};
|
|
763
|
+
});
|
|
764
|
+
};
|
|
765
|
+
|
|
766
|
+
/*
|
|
767
|
+
Destinos posibles para lo que se guarde en este producto: sus hijos y sus
|
|
768
|
+
compañeras de grupo. Un hijo no propaga a nadie.
|
|
769
|
+
*/
|
|
770
|
+
const destinosPosibles = () => {
|
|
771
|
+
if (state.product?.parentArticleId) return 0;
|
|
772
|
+
const companeras = (variantGroup?.members ?? []).filter((m) => !m.isCurrent);
|
|
773
|
+
return (state.product?.variantsCount ?? 0) + companeras.length;
|
|
774
|
+
};
|
|
775
|
+
|
|
745
776
|
const handleOnClickSave = () => {
|
|
746
777
|
// `preparandoPropagacion` cubre la ventana entre el clic y la apertura del
|
|
747
778
|
// diálogo: sin esto, dos clics seguidos lanzan dos consultas de familia.
|
|
748
779
|
if (state.saving || preparandoPropagacion) return;
|
|
749
780
|
switch (state.active_tab) {
|
|
750
|
-
case "Descripción":
|
|
781
|
+
case "Descripción": {
|
|
782
|
+
/*
|
|
783
|
+
Guardar una descripción en un padre también abre la decisión de
|
|
784
|
+
propagar. Sin esto, el hijo heredaba la descripción al ligarse y se
|
|
785
|
+
quedaba con la versión vieja en cuanto el padre la corregía, sin que
|
|
786
|
+
nadie lo notara.
|
|
787
|
+
*/
|
|
788
|
+
const cambiosDesc = cambiosDeDescripciones();
|
|
789
|
+
|
|
790
|
+
if (destinosPosibles() > 0 && cambiosDesc.length > 0) {
|
|
791
|
+
setPreparandoPropagacion(true);
|
|
792
|
+
loadFamily()
|
|
793
|
+
.then(() =>
|
|
794
|
+
setPendingPropagation({ cambios: cambiosDesc, kind: "description" })
|
|
795
|
+
)
|
|
796
|
+
.finally(() => setPreparandoPropagacion(false));
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
|
|
751
800
|
saveDescriptions(token);
|
|
752
801
|
break;
|
|
802
|
+
}
|
|
753
803
|
case "Ficha técnica": {
|
|
754
804
|
// Guardar un padre con hijos abre la decisión de propagar. Sin este
|
|
755
805
|
// paso el cambio se queda solo en el padre y los hijos se van
|
|
@@ -788,7 +838,7 @@ const ProviderProductEditionView = ({
|
|
|
788
838
|
// justo lo contrario de lo que va a preguntar.
|
|
789
839
|
setPreparandoPropagacion(true);
|
|
790
840
|
loadFamily()
|
|
791
|
-
.then(() => setPendingPropagation({ cambios }))
|
|
841
|
+
.then(() => setPendingPropagation({ cambios, kind: "datasheet" }))
|
|
792
842
|
.finally(() => setPreparandoPropagacion(false));
|
|
793
843
|
return;
|
|
794
844
|
}
|
|
@@ -1686,6 +1736,7 @@ const ProviderProductEditionView = ({
|
|
|
1686
1736
|
{pendingPropagation && (
|
|
1687
1737
|
<PropagateChangesModal
|
|
1688
1738
|
changedAttributes={pendingPropagation.cambios}
|
|
1739
|
+
kind={pendingPropagation.kind ?? "datasheet"}
|
|
1689
1740
|
variants={
|
|
1690
1741
|
state.product?.parentArticleId
|
|
1691
1742
|
? []
|
|
@@ -1698,8 +1749,29 @@ const ProviderProductEditionView = ({
|
|
|
1698
1749
|
saving={state.saving}
|
|
1699
1750
|
onCancel={() => setPendingPropagation(null)}
|
|
1700
1751
|
onConfirm={(propagation) => {
|
|
1752
|
+
const esDescripcion = pendingPropagation.kind === "description";
|
|
1701
1753
|
setPendingPropagation(null);
|
|
1702
|
-
|
|
1754
|
+
|
|
1755
|
+
if (!propagation) {
|
|
1756
|
+
// Guardar sin propagar: el producto se guarda solo.
|
|
1757
|
+
if (esDescripcion) saveDescriptions(token);
|
|
1758
|
+
else saveDatasheets(token);
|
|
1759
|
+
return;
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
/*
|
|
1763
|
+
El diálogo habla de «atributos» porque es el mismo componente
|
|
1764
|
+
para las dos pestañas. Al guardar hay que ponerlo en la lista
|
|
1765
|
+
que corresponde: el servidor recibe `attributes` o
|
|
1766
|
+
`descriptions`, nunca una por la otra.
|
|
1767
|
+
*/
|
|
1768
|
+
const { attributes, ...destinos } = propagation;
|
|
1769
|
+
|
|
1770
|
+
if (esDescripcion) {
|
|
1771
|
+
saveDescriptions(token, { ...destinos, descriptions: attributes });
|
|
1772
|
+
} else {
|
|
1773
|
+
saveDatasheets(token, propagation);
|
|
1774
|
+
}
|
|
1703
1775
|
}}
|
|
1704
1776
|
/>
|
|
1705
1777
|
)}
|
package/src/components/pages/RetailerProductEdition/context/provider-product-edition.context.jsx
CHANGED
|
@@ -34,7 +34,7 @@ const ProductEditionContext = createContext();
|
|
|
34
34
|
export const ProviderProductEditionProvider = ({ children }) => {
|
|
35
35
|
const [state, dispatch] = useReducer(productEditionReducer, initialState);
|
|
36
36
|
|
|
37
|
-
const saveDescriptions = async (token) => {
|
|
37
|
+
const saveDescriptions = async (token, propagation) => {
|
|
38
38
|
if (state.updated_descriptions_inputs.length === 0) return;
|
|
39
39
|
|
|
40
40
|
dispatch({ type: "SET_SAVING", payload: true });
|
|
@@ -42,6 +42,7 @@ export const ProviderProductEditionProvider = ({ children }) => {
|
|
|
42
42
|
const dataObject = {
|
|
43
43
|
articleId: state.product?.id_article,
|
|
44
44
|
articleData: state.updated_descriptions_inputs,
|
|
45
|
+
...(propagation ? { propagation } : {}),
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
// console.log({dataObject});
|
|
@@ -1270,13 +1270,68 @@ const RetailerProductEditionView = ({
|
|
|
1270
1270
|
return soloPropagables(cambios);
|
|
1271
1271
|
};
|
|
1272
1272
|
|
|
1273
|
+
/*
|
|
1274
|
+
Lo que se acaba de editar en la pestaña de descripciones.
|
|
1275
|
+
|
|
1276
|
+
Va aparte de `cambiosDeFichaTecnica` porque son tablas distintas y el
|
|
1277
|
+
endpoint recibe una lista o la otra. Aquí NO se filtran UPC ni SKU: esos son
|
|
1278
|
+
atributos de ficha técnica y no aparecen en esta pestaña.
|
|
1279
|
+
*/
|
|
1280
|
+
const cambiosDeDescripciones = () => {
|
|
1281
|
+
const retailerId = state.active_retailer?.id_retailer;
|
|
1282
|
+
const inputs = state.services?.descriptions?.inputs ?? {};
|
|
1283
|
+
|
|
1284
|
+
return (state.updated_descriptions_inputs ?? []).map((item) => {
|
|
1285
|
+
const input = inputs[`${item.attributeId}_${retailerId}`];
|
|
1286
|
+
return {
|
|
1287
|
+
id: Number(item.attributeId),
|
|
1288
|
+
name: input?.name ?? `Descripción ${item.attributeId}`,
|
|
1289
|
+
value: item.value,
|
|
1290
|
+
};
|
|
1291
|
+
});
|
|
1292
|
+
};
|
|
1293
|
+
|
|
1273
1294
|
const handleOnClickSave = async () => {
|
|
1274
1295
|
if (state.saving || preparandoPropagacion) return;
|
|
1275
1296
|
|
|
1276
1297
|
switch (state.active_tab) {
|
|
1277
|
-
case "Descripción":
|
|
1298
|
+
case "Descripción": {
|
|
1299
|
+
/*
|
|
1300
|
+
Guardar una descripción en un padre también abre la decisión de
|
|
1301
|
+
propagar. Sin esto, el hijo heredaba la descripción al ligarse y se
|
|
1302
|
+
quedaba con la versión vieja en cuanto el padre la corregía, sin que
|
|
1303
|
+
nadie lo notara.
|
|
1304
|
+
*/
|
|
1305
|
+
const cambiosDesc = cambiosDeDescripciones();
|
|
1306
|
+
const companerasDesc = (variantGroup?.members ?? []).filter(
|
|
1307
|
+
(m) => !m.isCurrent
|
|
1308
|
+
);
|
|
1309
|
+
|
|
1310
|
+
if (esHijoDeOtro || cambiosDesc.length === 0) {
|
|
1311
|
+
await saveDescriptions(token);
|
|
1312
|
+
break;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
setPreparandoPropagacion(true);
|
|
1316
|
+
let familiaDesc = null;
|
|
1317
|
+
try {
|
|
1318
|
+
familiaDesc = await loadFamily(true);
|
|
1319
|
+
} finally {
|
|
1320
|
+
setPreparandoPropagacion(false);
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
const hijosDesc = (familiaDesc?.variants ?? []).filter(
|
|
1324
|
+
(v) => !v.isCurrent
|
|
1325
|
+
);
|
|
1326
|
+
|
|
1327
|
+
if (hijosDesc.length > 0 || companerasDesc.length > 0) {
|
|
1328
|
+
setPendingPropagation({ cambios: cambiosDesc, kind: "description" });
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1278
1332
|
await saveDescriptions(token);
|
|
1279
1333
|
break;
|
|
1334
|
+
}
|
|
1280
1335
|
case "Ficha técnica": {
|
|
1281
1336
|
const cambios = cambiosDeFichaTecnica();
|
|
1282
1337
|
|
|
@@ -1368,7 +1423,7 @@ const RetailerProductEditionView = ({
|
|
|
1368
1423
|
// Un hijo tampoco puede estar agrupado desde 2026-09-25, así que para
|
|
1369
1424
|
// él no queda ningún destino posible.
|
|
1370
1425
|
if (!esHijo && (hijos.length > 0 || companeras.length > 0)) {
|
|
1371
|
-
setPendingPropagation({ cambios });
|
|
1426
|
+
setPendingPropagation({ cambios, kind: "datasheet" });
|
|
1372
1427
|
return;
|
|
1373
1428
|
}
|
|
1374
1429
|
|
|
@@ -2131,6 +2186,7 @@ const RetailerProductEditionView = ({
|
|
|
2131
2186
|
{pendingPropagation && (
|
|
2132
2187
|
<PropagateChangesModal
|
|
2133
2188
|
changedAttributes={pendingPropagation.cambios}
|
|
2189
|
+
kind={pendingPropagation.kind ?? "datasheet"}
|
|
2134
2190
|
variants={
|
|
2135
2191
|
esHijoDeOtro
|
|
2136
2192
|
? []
|
|
@@ -2143,8 +2199,28 @@ const RetailerProductEditionView = ({
|
|
|
2143
2199
|
saving={state.saving}
|
|
2144
2200
|
onCancel={() => setPendingPropagation(null)}
|
|
2145
2201
|
onConfirm={(propagation) => {
|
|
2202
|
+
const esDescripcion = pendingPropagation.kind === "description";
|
|
2146
2203
|
setPendingPropagation(null);
|
|
2147
|
-
|
|
2204
|
+
|
|
2205
|
+
if (!propagation) {
|
|
2206
|
+
if (esDescripcion) saveDescriptions(token);
|
|
2207
|
+
else saveDatasheets(token);
|
|
2208
|
+
return;
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
/*
|
|
2212
|
+
El diálogo habla de «atributos» porque es el mismo componente
|
|
2213
|
+
para las dos pestañas. Al guardar hay que ponerlo en la lista
|
|
2214
|
+
que corresponde: el servidor recibe `attributes` o
|
|
2215
|
+
`descriptions`, nunca una por la otra.
|
|
2216
|
+
*/
|
|
2217
|
+
const { attributes, ...destinos } = propagation;
|
|
2218
|
+
|
|
2219
|
+
if (esDescripcion) {
|
|
2220
|
+
saveDescriptions(token, { ...destinos, descriptions: attributes });
|
|
2221
|
+
} else {
|
|
2222
|
+
saveDatasheets(token, propagation);
|
|
2223
|
+
}
|
|
2148
2224
|
}}
|
|
2149
2225
|
/>
|
|
2150
2226
|
)}
|