contentoh-components-library 21.6.32 → 21.6.33
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/ai/prompts/attribute.prompt.js +28 -0
- package/dist/ai/prompts/description.prompt.js +33 -0
- package/dist/ai/schemas/attribute.schema.js +35 -0
- package/dist/ai/schemas/description.schema.js +27 -0
- package/dist/components/atoms/InheritanceTag/InheritanceTag.stories.js +5 -5
- package/dist/components/atoms/InheritanceTag/index.js +6 -6
- package/dist/components/organisms/InputGroup/index.js +12 -1
- package/dist/components/organisms/LinkVariantsModal/index.js +269 -356
- package/dist/components/organisms/LinkVariantsModal/styles.js +14 -5
- package/dist/components/organisms/PropagateChangesModal/index.js +12 -13
- package/dist/components/pages/ProviderProductEdition/context/provider-product-edition.context.js +5 -5
- package/dist/components/pages/ProviderProductEdition/context/reducers/inputs.js +5 -2
- package/dist/components/pages/ProviderProductEdition/index.js +76 -33
- package/dist/components/pages/RetailerProductEdition/context/provider-product-edition.context.js +5 -5
- package/dist/components/pages/RetailerProductEdition/context/reducers/inputs.js +5 -2
- package/dist/components/pages/RetailerProductEdition/index.js +75 -35
- package/package.json +1 -1
- package/src/components/atoms/InheritanceTag/InheritanceTag.stories.js +3 -3
- package/src/components/atoms/InheritanceTag/index.js +6 -6
- package/src/components/organisms/InputGroup/index.js +12 -0
- package/src/components/organisms/LinkVariantsModal/index.js +260 -287
- package/src/components/organisms/LinkVariantsModal/styles.js +65 -32
- package/src/components/organisms/PropagateChangesModal/index.js +19 -17
- package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx +4 -4
- package/src/components/pages/ProviderProductEdition/context/reducers/inputs.js +13 -1
- package/src/components/pages/ProviderProductEdition/index.js +48 -20
- package/src/components/pages/RetailerProductEdition/context/provider-product-edition.context.jsx +4 -4
- package/src/components/pages/RetailerProductEdition/context/reducers/inputs.js +13 -1
- package/src/components/pages/RetailerProductEdition/index.js +48 -20
|
@@ -202,22 +202,6 @@ export const List = styled.ul`
|
|
|
202
202
|
min-width: 0;
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
.quitar {
|
|
206
|
-
flex-shrink: 0;
|
|
207
|
-
margin-right: 10px;
|
|
208
|
-
border: none;
|
|
209
|
-
background: none;
|
|
210
|
-
padding: 2px 6px;
|
|
211
|
-
cursor: pointer;
|
|
212
|
-
font-size: 16px;
|
|
213
|
-
line-height: 1;
|
|
214
|
-
color: ${GlobalColors.gray};
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
.quitar:hover {
|
|
218
|
-
color: ${PINK};
|
|
219
|
-
}
|
|
220
|
-
|
|
221
205
|
.count {
|
|
222
206
|
margin-left: auto;
|
|
223
207
|
font-size: 12px;
|
|
@@ -288,6 +272,13 @@ export const Message = styled.p`
|
|
|
288
272
|
background-color: rgba(${PINK_RGB}, 0.1);
|
|
289
273
|
color: ${PINK};
|
|
290
274
|
}
|
|
275
|
+
|
|
276
|
+
/* Aviso, no error: el padre ya tiene hijos y planchar les cambia el origen.
|
|
277
|
+
Se puede continuar, así que no usa el rosa de rechazo. */
|
|
278
|
+
&.aviso {
|
|
279
|
+
background-color: rgba(${PINK_RGB}, 0.06);
|
|
280
|
+
border-left: 3px solid ${PINK};
|
|
281
|
+
}
|
|
291
282
|
`;
|
|
292
283
|
|
|
293
284
|
export const Footer = styled.div`
|
|
@@ -386,29 +377,71 @@ export const ImageGrid = styled.div`
|
|
|
386
377
|
}
|
|
387
378
|
`;
|
|
388
379
|
|
|
389
|
-
|
|
380
|
+
/*
|
|
381
|
+
Padre → hijo, dibujado.
|
|
382
|
+
|
|
383
|
+
El paso de herencia escribe en una dirección sola y hasta ahora no la decía:
|
|
384
|
+
el modo se elige en la pantalla anterior y desaparece de la vista. Con dos
|
|
385
|
+
tarjetas y una flecha se lee de un golpe, sin tener que reconstruirlo del
|
|
386
|
+
texto de cada bloque.
|
|
387
|
+
*/
|
|
388
|
+
export const Direction = styled.div`
|
|
390
389
|
display: flex;
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
margin-bottom: 16px;
|
|
390
|
+
align-items: stretch;
|
|
391
|
+
gap: 10px;
|
|
392
|
+
margin-bottom: 12px;
|
|
395
393
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
394
|
+
.lado {
|
|
395
|
+
flex: 1 1 0;
|
|
396
|
+
min-width: 0;
|
|
397
|
+
padding: 10px 12px;
|
|
398
|
+
border: 1px solid ${GlobalColors.s2};
|
|
400
399
|
border-radius: 6px;
|
|
401
|
-
background:
|
|
400
|
+
background-color: ${GlobalColors.white};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/* El padre es el que manda en esta pantalla, y se marca como tal. */
|
|
404
|
+
.lado:first-of-type {
|
|
405
|
+
border-color: rgba(${PINK_RGB}, 0.45);
|
|
406
|
+
background-color: rgba(${PINK_RGB}, 0.05);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.rol {
|
|
410
|
+
display: block;
|
|
402
411
|
font-family: ${FontFamily.Raleway_600};
|
|
403
|
-
font-size:
|
|
412
|
+
font-size: 11px;
|
|
413
|
+
text-transform: uppercase;
|
|
414
|
+
letter-spacing: 0.4px;
|
|
404
415
|
color: ${PINK};
|
|
405
|
-
cursor: pointer;
|
|
406
|
-
flex-shrink: 0;
|
|
407
416
|
}
|
|
408
417
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
418
|
+
strong {
|
|
419
|
+
display: block;
|
|
420
|
+
margin-top: 2px;
|
|
421
|
+
font-family: ${FontFamily.Raleway_600};
|
|
422
|
+
font-size: 13px;
|
|
423
|
+
color: ${GlobalColors.deep_gray};
|
|
424
|
+
overflow: hidden;
|
|
425
|
+
text-overflow: ellipsis;
|
|
426
|
+
white-space: nowrap;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/* Cuál de los dos es la ficha abierta: sin esto, al relacionar un padre no se
|
|
430
|
+
sabe de qué lado está uno. */
|
|
431
|
+
.actual {
|
|
432
|
+
display: block;
|
|
433
|
+
margin-top: 2px;
|
|
434
|
+
font-size: 11px;
|
|
435
|
+
font-style: italic;
|
|
436
|
+
color: ${GlobalColors.gray};
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.flecha {
|
|
440
|
+
align-self: center;
|
|
441
|
+
flex-shrink: 0;
|
|
442
|
+
font-size: 20px;
|
|
443
|
+
line-height: 1;
|
|
444
|
+
color: ${PINK};
|
|
412
445
|
}
|
|
413
446
|
`;
|
|
414
447
|
|
|
@@ -15,14 +15,13 @@ import {
|
|
|
15
15
|
Diálogo de propagación al guardar un producto padre.
|
|
16
16
|
|
|
17
17
|
Aparece cuando se guardan cambios de ficha técnica en un producto que tiene
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
como estaban.
|
|
18
|
+
hijos. El backend NO propaga nada por su cuenta: solo baja a los hijos lo que
|
|
19
|
+
venga en `propagation`, y esa lista la arma esta pantalla. Guardar sin abrirla,
|
|
20
|
+
o cerrarla sin propagar, deja al padre modificado y a los hijos como estaban.
|
|
22
21
|
|
|
23
22
|
props (* requerido):
|
|
24
23
|
- *changedAttributes: [{ id, name, value }] lo que se acaba de editar
|
|
25
|
-
- *variants: [{ articleId, name, upc }]
|
|
24
|
+
- *variants: [{ articleId, name, upc }] los hijos activos del padre
|
|
26
25
|
- *onCancel: cerrar sin guardar nada
|
|
27
26
|
- *onConfirm: (propagation | null) => void
|
|
28
27
|
null → guardar solo el padre
|
|
@@ -77,16 +76,19 @@ export const PropagateChangesModal = ({
|
|
|
77
76
|
<Overlay>
|
|
78
77
|
<Panel onClick={(event) => event.stopPropagation()}>
|
|
79
78
|
<Header>
|
|
80
|
-
<h2>
|
|
79
|
+
<h2>
|
|
80
|
+
Este producto tiene {variants.length} hijo
|
|
81
|
+
{variants.length === 1 ? "" : "s"}
|
|
82
|
+
</h2>
|
|
81
83
|
<p>
|
|
82
84
|
Cambiaste {changedAttributes.length} atributo
|
|
83
|
-
{changedAttributes.length === 1 ? "" : "s"}. Elige cuáles bajan a
|
|
84
|
-
|
|
85
|
+
{changedAttributes.length === 1 ? "" : "s"}. Elige cuáles bajan a los
|
|
86
|
+
hijos; el resto se guarda solo en este producto.
|
|
85
87
|
</p>
|
|
86
88
|
</Header>
|
|
87
89
|
|
|
88
90
|
<Body>
|
|
89
|
-
<h3>¿Qué se baja a
|
|
91
|
+
<h3>¿Qué se baja a los hijos?</h3>
|
|
90
92
|
<List>
|
|
91
93
|
{changedAttributes.map((attribute) => (
|
|
92
94
|
<li key={attribute.id}>
|
|
@@ -115,9 +117,9 @@ export const PropagateChangesModal = ({
|
|
|
115
117
|
onChange={() => setScope("all")}
|
|
116
118
|
/>
|
|
117
119
|
<span>
|
|
118
|
-
A
|
|
120
|
+
A todos
|
|
119
121
|
<span className="hint">
|
|
120
|
-
{variants.length}
|
|
122
|
+
{variants.length} hijo{variants.length === 1 ? "" : "s"} activo
|
|
121
123
|
{variants.length === 1 ? "" : "s"}.
|
|
122
124
|
</span>
|
|
123
125
|
</span>
|
|
@@ -154,16 +156,16 @@ export const PropagateChangesModal = ({
|
|
|
154
156
|
)}
|
|
155
157
|
|
|
156
158
|
{/* La diferencia con "ligar", y la que sorprende si no se dice: aquí
|
|
157
|
-
lo que
|
|
159
|
+
lo que el hijo editó a mano NO se pisa. */}
|
|
158
160
|
<Note>
|
|
159
|
-
|
|
161
|
+
Un hijo que haya editado alguno de estos atributos por su cuenta
|
|
160
162
|
conserva su valor. Para devolverlo al del padre está la acción
|
|
161
|
-
«Volver a heredar» en la ficha de
|
|
163
|
+
«Volver a heredar» en la ficha de ese hijo.
|
|
162
164
|
</Note>
|
|
163
165
|
|
|
164
166
|
{enSegundoPlano && (
|
|
165
167
|
<Note className="accent">
|
|
166
|
-
Son más de {UMBRAL_SEGUNDO_PLANO}
|
|
168
|
+
Son más de {UMBRAL_SEGUNDO_PLANO} hijos, así que la propagación
|
|
167
169
|
corre en segundo plano: el guardado termina antes de que todas estén
|
|
168
170
|
actualizadas.
|
|
169
171
|
</Note>
|
|
@@ -173,8 +175,8 @@ export const PropagateChangesModal = ({
|
|
|
173
175
|
<Footer>
|
|
174
176
|
<span className="resumen">
|
|
175
177
|
{puedePropagar
|
|
176
|
-
? `${chosenAttributes.length} atributo(s) a ${destinatarios}
|
|
177
|
-
: "No se bajará nada a
|
|
178
|
+
? `${chosenAttributes.length} atributo(s) a ${destinatarios} hijo(s).`
|
|
179
|
+
: "No se bajará nada a los hijos."}
|
|
178
180
|
</span>
|
|
179
181
|
<button
|
|
180
182
|
type="button"
|
package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx
CHANGED
|
@@ -123,7 +123,7 @@ export const ProviderProductEditionProvider = ({ children }) => {
|
|
|
123
123
|
lo que el usuario eligió en el diálogo: { attributes: [...], targetChildren }.
|
|
124
124
|
|
|
125
125
|
Sin ese bloque el backend no propaga nada. Es deliberado: bajar un cambio a
|
|
126
|
-
|
|
126
|
+
los hijos tiene que ser una decisión, no un efecto secundario de guardar.
|
|
127
127
|
*/
|
|
128
128
|
const saveDatasheets = async (token, propagation) => {
|
|
129
129
|
if (state.updated_datasheets_inputs.length === 0) return;
|
|
@@ -167,17 +167,17 @@ export const ProviderProductEditionProvider = ({ children }) => {
|
|
|
167
167
|
type: "SET_UPDATED_DATASHEETS_INPUTS",
|
|
168
168
|
payload: [],
|
|
169
169
|
});
|
|
170
|
-
// En
|
|
170
|
+
// En un hijo, todo atributo que se toca deja de ser heredado:
|
|
171
171
|
// update-articles-data le pone is_overridden = 1 en la base. Si aquí solo
|
|
172
172
|
// se refresca el valor, el chip sigue diciendo "Heredado" hasta la
|
|
173
173
|
// siguiente carga de la ficha, y el usuario ve una marca que ya es falsa.
|
|
174
|
-
const
|
|
174
|
+
const esHijo =
|
|
175
175
|
state.services?.datasheets?.variant?.isVariant ??
|
|
176
176
|
!!state.product?.parentArticleId;
|
|
177
177
|
|
|
178
178
|
dispatch({
|
|
179
179
|
type: "UPDATE_DATASHEETS_INPUTS",
|
|
180
|
-
payload:
|
|
180
|
+
payload: esHijo
|
|
181
181
|
? state.updated_datasheets_inputs.map((item) => ({
|
|
182
182
|
...item,
|
|
183
183
|
isOverridden: 1,
|
|
@@ -52,7 +52,19 @@ export const inputsReducer = (state, action) => {
|
|
|
52
52
|
const updatedInput = action.payload.find(
|
|
53
53
|
(updated) => updated.attributeId === input.id
|
|
54
54
|
);
|
|
55
|
-
|
|
55
|
+
if (!updatedInput) return input;
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
...input,
|
|
59
|
+
value: updatedInput.value,
|
|
60
|
+
// Opcional a propósito, igual que en la ficha técnica: quien solo
|
|
61
|
+
// cambia el valor no toca la marca de herencia. La usa "Volver a
|
|
62
|
+
// heredar", que sí necesita devolverla a heredada para que el chip
|
|
63
|
+
// deje de decir "Propio".
|
|
64
|
+
...(updatedInput.isOverridden === undefined
|
|
65
|
+
? {}
|
|
66
|
+
: { isOverridden: updatedInput.isOverridden }),
|
|
67
|
+
};
|
|
56
68
|
}
|
|
57
69
|
);
|
|
58
70
|
|
|
@@ -709,15 +709,15 @@ const ProviderProductEditionView = ({
|
|
|
709
709
|
saveDescriptions(token);
|
|
710
710
|
break;
|
|
711
711
|
case "Ficha técnica": {
|
|
712
|
-
// Guardar un padre con
|
|
713
|
-
// paso el cambio se queda solo en el padre y
|
|
712
|
+
// Guardar un padre con hijos abre la decisión de propagar. Sin este
|
|
713
|
+
// paso el cambio se queda solo en el padre y los hijos se van
|
|
714
714
|
// separando de él sin que nadie lo note.
|
|
715
715
|
const esPadre = state.product?.variantsCount > 0;
|
|
716
716
|
const cambios = cambiosDeFichaTecnica();
|
|
717
717
|
|
|
718
718
|
if (esPadre && cambios.length > 0) {
|
|
719
719
|
// Se espera a tener la familia antes de abrir: si no, el diálogo
|
|
720
|
-
// aparece diciendo "0
|
|
720
|
+
// aparece diciendo "0 hijos" hasta que llega la respuesta, que es
|
|
721
721
|
// justo lo contrario de lo que va a preguntar.
|
|
722
722
|
setPreparandoPropagacion(true);
|
|
723
723
|
loadFamily()
|
|
@@ -763,7 +763,7 @@ const ProviderProductEditionView = ({
|
|
|
763
763
|
};
|
|
764
764
|
|
|
765
765
|
/*
|
|
766
|
-
Trae la familia del producto: sus
|
|
766
|
+
Trae la familia del producto: sus hijos, o sus hermanos si el abierto es
|
|
767
767
|
una de ellas.
|
|
768
768
|
|
|
769
769
|
Se pide al abrir la sección y no al montar la pantalla: la mayoría de los
|
|
@@ -786,7 +786,7 @@ const ProviderProductEditionView = ({
|
|
|
786
786
|
};
|
|
787
787
|
|
|
788
788
|
/*
|
|
789
|
-
Abre
|
|
789
|
+
Abre otro producto de la familia.
|
|
790
790
|
|
|
791
791
|
Esta pantalla no lee el producto de la URL: lo lee de sessionStorage, donde
|
|
792
792
|
lo dejó el listado al hacer clic. Así que navegar a /products/:id sin más
|
|
@@ -801,7 +801,7 @@ const ProviderProductEditionView = ({
|
|
|
801
801
|
raíz —que la ficha lea de la URL— toca todas las plataformas y no cabe aquí.
|
|
802
802
|
*/
|
|
803
803
|
/*
|
|
804
|
-
Abre la edición múltiple con
|
|
804
|
+
Abre la edición múltiple con los hijos de la familia ya cargados.
|
|
805
805
|
|
|
806
806
|
Esa pantalla lee `multipleEditionList` de sessionStorage —así la deja el
|
|
807
807
|
listado al pulsar "editar varios"— y necesita el PRODUCTO COMPLETO de cada
|
|
@@ -855,7 +855,7 @@ const ProviderProductEditionView = ({
|
|
|
855
855
|
payload: {
|
|
856
856
|
show: true,
|
|
857
857
|
title: "",
|
|
858
|
-
message: "No se pudieron cargar
|
|
858
|
+
message: "No se pudieron cargar los hijos para editarlos juntos.",
|
|
859
859
|
image: errorIcon,
|
|
860
860
|
},
|
|
861
861
|
});
|
|
@@ -918,7 +918,7 @@ const ProviderProductEditionView = ({
|
|
|
918
918
|
el usuario tenga sin guardar.
|
|
919
919
|
|
|
920
920
|
Los dos modos tienen efectos opuestos sobre este producto: ligando hijos GANA
|
|
921
|
-
|
|
921
|
+
hijos; ligándose a un padre pasa a SER uno, y entonces el botón de ligar
|
|
922
922
|
desaparece porque la jerarquía es de un solo nivel.
|
|
923
923
|
*/
|
|
924
924
|
const handleOnLinkedVariants = (result) => {
|
|
@@ -965,7 +965,7 @@ const ProviderProductEditionView = ({
|
|
|
965
965
|
/*
|
|
966
966
|
Acción "Volver a heredar del producto" de los chips de herencia.
|
|
967
967
|
|
|
968
|
-
La inicia
|
|
968
|
+
La inicia el hijo, no el padre, y descarta un valor capturado a mano: por
|
|
969
969
|
eso el endpoint exige la lista explícita de atributos y no acepta un "todos"
|
|
970
970
|
implícito.
|
|
971
971
|
|
|
@@ -973,15 +973,25 @@ const ProviderProductEditionView = ({
|
|
|
973
973
|
alternativa —recargar la ficha— se llevaría por delante lo que el usuario
|
|
974
974
|
tenga sin guardar en las otras pestañas.
|
|
975
975
|
*/
|
|
976
|
-
|
|
976
|
+
/*
|
|
977
|
+
`kind` distingue de qué pestaña salió el chip. Las descripciones viven en
|
|
978
|
+
`rel_article_description` y la ficha técnica en `article_data`: el endpoint
|
|
979
|
+
recibe una lista o la otra, y lo que devuelve se repinta en su propio
|
|
980
|
+
reducer.
|
|
981
|
+
*/
|
|
982
|
+
const handleOnRestoreInheritance = async (attributeId, kind = "attribute") => {
|
|
977
983
|
if (!attributeId || !state.product?.id_article) return;
|
|
978
984
|
|
|
985
|
+
const esDescripcion = kind === "description";
|
|
986
|
+
|
|
979
987
|
try {
|
|
980
988
|
const res = await axios.post(
|
|
981
989
|
`${process.env.REACT_APP_VARIANTS_ENDPOINT}/restore`,
|
|
982
990
|
{
|
|
983
991
|
articleId: state.product.id_article,
|
|
984
|
-
|
|
992
|
+
...(esDescripcion
|
|
993
|
+
? { descriptions: [Number(attributeId)] }
|
|
994
|
+
: { attributes: [Number(attributeId)] }),
|
|
985
995
|
},
|
|
986
996
|
{ headers: { Authorization: token } }
|
|
987
997
|
);
|
|
@@ -990,6 +1000,18 @@ const ProviderProductEditionView = ({
|
|
|
990
1000
|
// real viaja en el cuerpo y readPayload lo convierte en excepción.
|
|
991
1001
|
const data = readPayload(res);
|
|
992
1002
|
|
|
1003
|
+
if (esDescripcion) {
|
|
1004
|
+
dispatch({
|
|
1005
|
+
type: "UPDATE_DESCRIPTIONS_INPUTS",
|
|
1006
|
+
payload: (data.descriptionValues || []).map((item) => ({
|
|
1007
|
+
attributeId: item.id_description,
|
|
1008
|
+
value: item.value,
|
|
1009
|
+
isOverridden: 0,
|
|
1010
|
+
})),
|
|
1011
|
+
});
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
993
1015
|
dispatch({
|
|
994
1016
|
type: "UPDATE_DATASHEETS_INPUTS",
|
|
995
1017
|
payload: (data.values || []).map((item) => ({
|
|
@@ -1664,7 +1686,7 @@ const ProviderProductEditionView = ({
|
|
|
1664
1686
|
</div>
|
|
1665
1687
|
<div className="product-information">
|
|
1666
1688
|
<div className="product-information">
|
|
1667
|
-
{/* Solo cuando el producto NO es ya
|
|
1689
|
+
{/* Solo cuando el producto NO es ya hijo de alguien: ligarlo
|
|
1668
1690
|
otra vez devolvería VARIANT_ALREADY_LINKED sin excepción, y un
|
|
1669
1691
|
botón que siempre falla es peor que no tenerlo. Para salir de
|
|
1670
1692
|
una familia está la desvinculación, no este botón. */}
|
|
@@ -1687,7 +1709,7 @@ const ProviderProductEditionView = ({
|
|
|
1687
1709
|
loadFamily();
|
|
1688
1710
|
}}
|
|
1689
1711
|
>
|
|
1690
|
-
{state.product.variantsCount}
|
|
1712
|
+
{state.product.variantsCount} hijo
|
|
1691
1713
|
{state.product.variantsCount === 1 ? "" : "s"}
|
|
1692
1714
|
<span aria-hidden="true">{showFamily ? " ▴" : " ▾"}</span>
|
|
1693
1715
|
</button>
|
|
@@ -1695,8 +1717,8 @@ const ProviderProductEditionView = ({
|
|
|
1695
1717
|
</div>
|
|
1696
1718
|
)}
|
|
1697
1719
|
|
|
1698
|
-
{/* La ficha de
|
|
1699
|
-
aquí se salta al padre o a
|
|
1720
|
+
{/* La ficha de un hijo también necesita ver la familia: desde
|
|
1721
|
+
aquí se salta al padre o a un hermano sin pasar por el listado. */}
|
|
1700
1722
|
{state.product?.parentArticleId && (
|
|
1701
1723
|
<div className="variants-actions">
|
|
1702
1724
|
<button
|
|
@@ -1708,7 +1730,7 @@ const ProviderProductEditionView = ({
|
|
|
1708
1730
|
loadFamily();
|
|
1709
1731
|
}}
|
|
1710
1732
|
>
|
|
1711
|
-
|
|
1733
|
+
Hijo de otro producto
|
|
1712
1734
|
<span aria-hidden="true">{showFamily ? " ▴" : " ▾"}</span>
|
|
1713
1735
|
</button>
|
|
1714
1736
|
</div>
|
|
@@ -1756,7 +1778,7 @@ const ProviderProductEditionView = ({
|
|
|
1756
1778
|
? "Abriendo…"
|
|
1757
1779
|
: variant.isCurrent
|
|
1758
1780
|
? "Estás aquí"
|
|
1759
|
-
: "
|
|
1781
|
+
: "Hijo"}
|
|
1760
1782
|
</span>
|
|
1761
1783
|
<span className="name">{variant.name}</span>
|
|
1762
1784
|
<span className="upc">{variant.upc}</span>
|
|
@@ -1764,10 +1786,10 @@ const ProviderProductEditionView = ({
|
|
|
1764
1786
|
))}
|
|
1765
1787
|
|
|
1766
1788
|
{family && !family.error && !family.variants?.length && (
|
|
1767
|
-
<p className="loading">Este producto no tiene
|
|
1789
|
+
<p className="loading">Este producto no tiene hijos.</p>
|
|
1768
1790
|
)}
|
|
1769
1791
|
|
|
1770
|
-
{/*
|
|
1792
|
+
{/* Editarlos juntos evita abrir seis fichas para llenar lo
|
|
1771
1793
|
mismo seis veces, que es el caso real de una familia. */}
|
|
1772
1794
|
{family?.variants?.length > 1 && (
|
|
1773
1795
|
<button
|
|
@@ -1778,7 +1800,7 @@ const ProviderProductEditionView = ({
|
|
|
1778
1800
|
>
|
|
1779
1801
|
{preparandoEdicionMultiple
|
|
1780
1802
|
? "Abriendo…"
|
|
1781
|
-
: `Editar
|
|
1803
|
+
: `Editar los ${family.variants.length} hijos juntos`}
|
|
1782
1804
|
</button>
|
|
1783
1805
|
)}
|
|
1784
1806
|
</div>
|
|
@@ -1849,6 +1871,12 @@ const ProviderProductEditionView = ({
|
|
|
1849
1871
|
updatedDescriptions={
|
|
1850
1872
|
state.updated_descriptions_inputs
|
|
1851
1873
|
}
|
|
1874
|
+
/* El parentesco es del producto, no del servicio:
|
|
1875
|
+
los dos endpoints lo devuelven igual. Se toma de
|
|
1876
|
+
la ficha técnica para no depender de que la
|
|
1877
|
+
llamada de descripciones traiga el bloque. */
|
|
1878
|
+
variant={state.services?.datasheets?.variant}
|
|
1879
|
+
onRestoreInheritance={handleOnRestoreInheritance}
|
|
1852
1880
|
articleId={state.product?.id_article}
|
|
1853
1881
|
version={state.product.version}
|
|
1854
1882
|
isShowbox={false}
|
package/src/components/pages/RetailerProductEdition/context/provider-product-edition.context.jsx
CHANGED
|
@@ -140,7 +140,7 @@ export const ProviderProductEditionProvider = ({ children }) => {
|
|
|
140
140
|
/*
|
|
141
141
|
`propagation` es opcional y solo lo manda la ficha de un producto padre, con
|
|
142
142
|
lo que el usuario eligió en el diálogo. Sin ese bloque el backend no propaga
|
|
143
|
-
nada: bajar un cambio a
|
|
143
|
+
nada: bajar un cambio a los hijos es una decisión, no un efecto
|
|
144
144
|
secundario de guardar.
|
|
145
145
|
*/
|
|
146
146
|
const saveDatasheets = async (token, propagation) => {
|
|
@@ -181,17 +181,17 @@ export const ProviderProductEditionProvider = ({ children }) => {
|
|
|
181
181
|
type: "SET_UPDATED_DATASHEETS_INPUTS",
|
|
182
182
|
payload: [],
|
|
183
183
|
});
|
|
184
|
-
// En
|
|
184
|
+
// En un hijo, todo atributo que se toca deja de ser heredado:
|
|
185
185
|
// update-articles-data le pone is_overridden = 1 en la base. Sin
|
|
186
186
|
// reflejarlo aquí, el chip sigue diciendo "Heredado" hasta la siguiente
|
|
187
187
|
// carga de la ficha, y el usuario ve una marca que ya es falsa.
|
|
188
|
-
const
|
|
188
|
+
const esHijo =
|
|
189
189
|
state.services?.datasheets?.variant?.isVariant ??
|
|
190
190
|
!!state.product?.parentArticleId;
|
|
191
191
|
|
|
192
192
|
dispatch({
|
|
193
193
|
type: "UPDATE_DATASHEETS_INPUTS",
|
|
194
|
-
payload:
|
|
194
|
+
payload: esHijo
|
|
195
195
|
? state.updated_datasheets_inputs.map((item) => ({
|
|
196
196
|
...item,
|
|
197
197
|
isOverridden: 1,
|
|
@@ -61,7 +61,19 @@ export const inputsReducer = (state, action) => {
|
|
|
61
61
|
const updatedInput = action.payload.find(
|
|
62
62
|
(updated) => updated.attributeId === input.id
|
|
63
63
|
);
|
|
64
|
-
|
|
64
|
+
if (!updatedInput) return input;
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
...input,
|
|
68
|
+
value: updatedInput.value,
|
|
69
|
+
// Opcional a propósito, igual que en la ficha técnica: quien solo
|
|
70
|
+
// cambia el valor no toca la marca de herencia. La usa "Volver a
|
|
71
|
+
// heredar", que sí necesita devolverla a heredada para que el chip
|
|
72
|
+
// deje de decir "Propio".
|
|
73
|
+
...(updatedInput.isOverridden === undefined
|
|
74
|
+
? {}
|
|
75
|
+
: { isOverridden: updatedInput.isOverridden }),
|
|
76
|
+
};
|
|
65
77
|
}
|
|
66
78
|
);
|
|
67
79
|
|