contentoh-components-library 21.6.45 → 21.6.48

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.
@@ -7,10 +7,10 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports.PropagateChangesModal = void 0;
9
9
 
10
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/toConsumableArray"));
11
-
12
10
  var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectSpread2"));
13
11
 
12
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/toConsumableArray"));
13
+
14
14
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/slicedToArray"));
15
15
 
16
16
  var _react = require("react");
@@ -49,6 +49,10 @@ var PropagateChangesModal = function PropagateChangesModal(_ref) {
49
49
  changedAttributes = _ref$changedAttribute === void 0 ? [] : _ref$changedAttribute,
50
50
  _ref$variants = _ref.variants,
51
51
  variants = _ref$variants === void 0 ? [] : _ref$variants,
52
+ _ref$groupMembers = _ref.groupMembers,
53
+ groupMembers = _ref$groupMembers === void 0 ? [] : _ref$groupMembers,
54
+ _ref$groupCode = _ref.groupCode,
55
+ groupCode = _ref$groupCode === void 0 ? null : _ref$groupCode,
52
56
  onCancel = _ref.onCancel,
53
57
  onConfirm = _ref.onConfirm,
54
58
  _ref$saving = _ref.saving,
@@ -58,18 +62,57 @@ var PropagateChangesModal = function PropagateChangesModal(_ref) {
58
62
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
59
63
  chosenAttributes = _useState2[0],
60
64
  setChosenAttributes = _useState2[1];
65
+ /*
66
+ DOS DESTINOS INDEPENDIENTES, y esa independencia es el punto.
67
+ hijos cuelgan de este producto y heredan de él. Hay jerarquía.
68
+ variantes comparten un código de grupo. No hay jerarquía; son el mismo
69
+ producto en otra presentación.
70
+ Elegir variantes NO debe alcanzar a los hijos ni al revés, así que cada uno
71
+ lleva su propio alcance y su propia selección. Un solo control con tres
72
+ opciones —hijos / variantes / ambos— no bastaría: el usuario también tiene
73
+ que poder decir "a estas dos variantes y a ese hijo".
74
+ Arrancan en "none" los dos: propagar sobrescribe, así que ningún destino se
75
+ da por elegido sin que alguien lo pida.
76
+ */
77
+
61
78
 
62
- var _useState3 = (0, _react.useState)("all"),
79
+ var _useState3 = (0, _react.useState)("none"),
63
80
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
64
- scope = _useState4[0],
65
- setScope = _useState4[1];
81
+ scopeChildren = _useState4[0],
82
+ setScopeChildren = _useState4[1];
66
83
 
67
84
  var _useState5 = (0, _react.useState)([]),
68
85
  _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
69
86
  chosenChildren = _useState6[0],
70
87
  setChosenChildren = _useState6[1];
71
88
 
72
- var destinatarios = scope === "all" ? variants.length : chosenChildren.length;
89
+ var _useState7 = (0, _react.useState)("none"),
90
+ _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
91
+ scopeVariants = _useState8[0],
92
+ setScopeVariants = _useState8[1];
93
+
94
+ var _useState9 = (0, _react.useState)([]),
95
+ _useState10 = (0, _slicedToArray2.default)(_useState9, 2),
96
+ chosenVariants = _useState10[0],
97
+ setChosenVariants = _useState10[1];
98
+
99
+ var seleccion = function seleccion(scope, todos, elegidos) {
100
+ if (scope === "none") return [];
101
+ if (scope === "all") return todos;
102
+ return todos.filter(function (item) {
103
+ return elegidos.includes(item.articleId);
104
+ });
105
+ };
106
+
107
+ var hijosDestino = seleccion(scopeChildren, variants, chosenChildren);
108
+ var variantesDestino = seleccion(scopeVariants, groupMembers, chosenVariants); // Un producto puede ser hijo Y estar en el grupo: se cuenta una sola vez.
109
+
110
+ var idsDestino = new Set([].concat((0, _toConsumableArray2.default)(hijosDestino.map(function (x) {
111
+ return x.articleId;
112
+ })), (0, _toConsumableArray2.default)(variantesDestino.map(function (x) {
113
+ return x.articleId;
114
+ }))));
115
+ var destinatarios = idsDestino.size;
73
116
  var puedePropagar = chosenAttributes.length > 0 && destinatarios > 0;
74
117
  var enSegundoPlano = destinatarios > UMBRAL_SEGUNDO_PLANO;
75
118
  /*
@@ -83,8 +126,10 @@ var PropagateChangesModal = function PropagateChangesModal(_ref) {
83
126
  salida que el aviso debería estar ofreciendo.
84
127
  */
85
128
 
86
- var destinos = scope === "all" ? variants : variants.filter(function (item) {
87
- return chosenChildren.includes(item.articleId);
129
+ var destinos = [].concat((0, _toConsumableArray2.default)(hijosDestino), (0, _toConsumableArray2.default)(variantesDestino)).filter(function (item, i, lista) {
130
+ return lista.findIndex(function (x) {
131
+ return x.articleId === item.articleId;
132
+ }) === i;
88
133
  });
89
134
  var conValorPropio = destinos.map(function (hijo) {
90
135
  var _hijo$overriddenAttri;
@@ -106,18 +151,32 @@ var PropagateChangesModal = function PropagateChangesModal(_ref) {
106
151
  });
107
152
  };
108
153
 
109
- var toggleChild = function toggleChild(id) {
110
- setChosenChildren(function (current) {
111
- return current.includes(id) ? current.filter(function (item) {
112
- return item !== id;
113
- }) : [].concat((0, _toConsumableArray2.default)(current), [id]);
114
- });
154
+ var toggleEn = function toggleEn(setter) {
155
+ return function (id) {
156
+ setter(function (current) {
157
+ return current.includes(id) ? current.filter(function (item) {
158
+ return item !== id;
159
+ }) : [].concat((0, _toConsumableArray2.default)(current), [id]);
160
+ });
161
+ };
115
162
  };
116
163
 
164
+ var toggleChild = toggleEn(setChosenChildren);
165
+ var toggleVariant = toggleEn(setChosenVariants);
166
+
117
167
  var confirmar = function confirmar() {
168
+ // Se manda "none" explícito y no una lista vacía para que el servidor no
169
+ // tenga que adivinar si "sin ids" quiere decir "a ninguno" o "no me lo
170
+ // preguntaron". Cada destino viaja por su cuenta.
171
+ var comoLista = function comoLista(scope, elegidos) {
172
+ if (scope === "none") return "none";
173
+ return scope === "all" ? "all" : elegidos;
174
+ };
175
+
118
176
  onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm({
119
177
  attributes: chosenAttributes,
120
- targetChildren: scope === "all" ? "all" : chosenChildren
178
+ targetChildren: comoLista(scopeChildren, chosenChildren),
179
+ targetVariants: comoLista(scopeVariants, chosenVariants)
121
180
  });
122
181
  };
123
182
 
@@ -128,13 +187,13 @@ var PropagateChangesModal = function PropagateChangesModal(_ref) {
128
187
  },
129
188
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Header, {
130
189
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("h2", {
131
- children: ["Este producto tiene ", variants.length, " hijo", variants.length === 1 ? "" : "s"]
190
+ children: [[variants.length ? "".concat(variants.length, " hijo").concat(variants.length === 1 ? "" : "s") : null, groupMembers.length ? "".concat(groupMembers.length, " variante").concat(groupMembers.length === 1 ? "" : "s") : null].filter(Boolean).join(" y "), " pueden recibir este cambio"]
132
191
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("p", {
133
- children: ["Cambiaste ", changedAttributes.length, " atributo", changedAttributes.length === 1 ? "" : "s", ". Elige cu\xE1les bajan a los hijos; el resto se guarda solo en este producto."]
192
+ children: ["Cambiaste ", changedAttributes.length, " atributo", changedAttributes.length === 1 ? "" : "s", ". Elige cu\xE1les se copian y a qui\xE9nes; el resto se guarda solo en este producto."]
134
193
  })]
135
194
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Body, {
136
195
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("h3", {
137
- children: "\xBFQu\xE9 se baja a los hijos?"
196
+ children: "\xBFQu\xE9 se copia?"
138
197
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_styles.List, {
139
198
  children: changedAttributes.map(function (attribute) {
140
199
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
@@ -155,54 +214,122 @@ var PropagateChangesModal = function PropagateChangesModal(_ref) {
155
214
  })
156
215
  }, attribute.id);
157
216
  })
158
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("h3", {
159
- children: "\xBFA cu\xE1les?"
160
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Choices, {
161
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
162
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
163
- type: "radio",
164
- name: "propagation-scope",
165
- checked: scope === "all",
166
- onChange: function onChange() {
167
- return setScope("all");
168
- }
169
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
170
- children: ["A todos", /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
171
- className: "hint",
172
- children: [variants.length, " hijo", variants.length === 1 ? "" : "s", " activo", variants.length === 1 ? "" : "s", "."]
217
+ }), variants.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
218
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("h3", {
219
+ children: ["\xBFA cu\xE1les de los ", variants.length, " hijo", variants.length === 1 ? "" : "s", "?"]
220
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Choices, {
221
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
222
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
223
+ type: "radio",
224
+ name: "scope-children",
225
+ checked: scopeChildren === "none",
226
+ onChange: function onChange() {
227
+ return setScopeChildren("none");
228
+ }
229
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
230
+ children: "A ninguno"
231
+ })]
232
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
233
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
234
+ type: "radio",
235
+ name: "scope-children",
236
+ checked: scopeChildren === "all",
237
+ onChange: function onChange() {
238
+ return setScopeChildren("all");
239
+ }
240
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
241
+ children: "A todos"
242
+ })]
243
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
244
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
245
+ type: "radio",
246
+ name: "scope-children",
247
+ checked: scopeChildren === "some",
248
+ onChange: function onChange() {
249
+ return setScopeChildren("some");
250
+ }
251
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
252
+ children: "Elegir cu\xE1les"
173
253
  })]
174
254
  })]
175
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
176
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
177
- type: "radio",
178
- name: "propagation-scope",
179
- checked: scope === "some",
180
- onChange: function onChange() {
181
- return setScope("some");
182
- }
183
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
184
- children: "Elegir cu\xE1les"
185
- })]
255
+ }), scopeChildren === "some" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_styles.List, {
256
+ children: variants.map(function (variant) {
257
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
258
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
259
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
260
+ type: "checkbox",
261
+ checked: chosenChildren.includes(variant.articleId),
262
+ onChange: function onChange() {
263
+ return toggleChild(variant.articleId);
264
+ }
265
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
266
+ children: [variant.name, /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
267
+ className: "meta",
268
+ children: ["UPC ", variant.upc || "—"]
269
+ })]
270
+ })]
271
+ })
272
+ }, variant.articleId);
273
+ })
186
274
  })]
187
- }), scope === "some" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_styles.List, {
188
- children: variants.map(function (variant) {
189
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
190
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
191
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
192
- type: "checkbox",
193
- checked: chosenChildren.includes(variant.articleId),
194
- onChange: function onChange() {
195
- return toggleChild(variant.articleId);
196
- }
197
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
198
- children: [variant.name, /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
199
- className: "meta",
200
- children: ["UPC ", variant.upc || "—"]
275
+ }), groupMembers.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
276
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("h3", {
277
+ children: ["\xBFA cu\xE1les de las ", groupMembers.length, " variante", groupMembers.length === 1 ? "" : "s", groupCode ? " del grupo ".concat(groupCode) : "", "?"]
278
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Choices, {
279
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
280
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
281
+ type: "radio",
282
+ name: "scope-variants",
283
+ checked: scopeVariants === "none",
284
+ onChange: function onChange() {
285
+ return setScopeVariants("none");
286
+ }
287
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
288
+ children: "A ninguna"
289
+ })]
290
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
291
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
292
+ type: "radio",
293
+ name: "scope-variants",
294
+ checked: scopeVariants === "all",
295
+ onChange: function onChange() {
296
+ return setScopeVariants("all");
297
+ }
298
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
299
+ children: "A todas"
300
+ })]
301
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
302
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
303
+ type: "radio",
304
+ name: "scope-variants",
305
+ checked: scopeVariants === "some",
306
+ onChange: function onChange() {
307
+ return setScopeVariants("some");
308
+ }
309
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
310
+ children: "Elegir cu\xE1les"
311
+ })]
312
+ })]
313
+ }), scopeVariants === "some" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_styles.List, {
314
+ children: groupMembers.map(function (miembro) {
315
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
316
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("label", {
317
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
318
+ type: "checkbox",
319
+ checked: chosenVariants.includes(miembro.articleId),
320
+ onChange: function onChange() {
321
+ return toggleVariant(miembro.articleId);
322
+ }
323
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
324
+ children: [miembro.name, /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
325
+ className: "meta",
326
+ children: ["UPC ", miembro.upc || "—"]
327
+ })]
201
328
  })]
202
- })]
203
- })
204
- }, variant.articleId);
205
- })
329
+ })
330
+ }, miembro.articleId);
331
+ })
332
+ })]
206
333
  }), conValorPropio.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Note, {
207
334
  className: "accent",
208
335
  children: [conValorPropio.length === 1 ? "Un hijo tiene un valor propio en lo que elegiste y se va a reemplazar: " : "".concat(conValorPropio.length, " hijos tienen valores propios en lo que elegiste y se van a reemplazar: "), conValorPropio.map(function (hijo) {
@@ -215,7 +342,7 @@ var PropagateChangesModal = function PropagateChangesModal(_ref) {
215
342
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Footer, {
216
343
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
217
344
  className: "resumen",
218
- children: puedePropagar ? "".concat(chosenAttributes.length, " atributo(s) a ").concat(destinatarios, " hijo(s).") : "No se bajará nada a los hijos."
345
+ children: puedePropagar ? "".concat(chosenAttributes.length, " atributo(s) a ").concat(destinatarios, " producto(s).") : "No se copiará nada: elige al menos un atributo y un destino."
219
346
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
220
347
  type: "button",
221
348
  className: "secondary",
@@ -283,7 +283,6 @@ var VariantGroupModal = function VariantGroupModal(_ref) {
283
283
  }
284
284
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
285
285
  type: "submit",
286
- className: "secondary",
287
286
  disabled: loading,
288
287
  children: loading ? "Buscando…" : "Buscar"
289
288
  })]
@@ -22,19 +22,19 @@ var Overlay = _styledComponents.default.div(_templateObject || (_templateObject
22
22
 
23
23
  exports.Overlay = Overlay;
24
24
 
25
- var Panel = _styledComponents.default.div(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2.default)(["\n display: flex;\n flex-direction: column;\n width: min(520px, 94vw);\n max-height: 88vh;\n border-radius: 10px;\n background-color: ", ";\n font-family: ", ";\n overflow: hidden;\n"])), _variables.GlobalColors.white, _variables.FontFamily.Raleway);
25
+ var Panel = _styledComponents.default.div(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2.default)(["\n display: flex;\n flex-direction: column;\n width: min(560px, 92vw);\n max-height: 86vh;\n border-radius: 10px;\n background-color: ", ";\n font-family: ", ";\n overflow: hidden;\n"])), _variables.GlobalColors.white, _variables.FontFamily.Raleway);
26
26
 
27
27
  exports.Panel = Panel;
28
28
 
29
- var Header = _styledComponents.default.div(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2.default)(["\n padding: 18px 22px 12px;\n\n h2 {\n margin: 0;\n font-family: ", ";\n font-size: 16px;\n color: ", ";\n }\n\n p {\n margin: 6px 0 0;\n font-size: 13px;\n line-height: 1.4;\n color: ", ";\n }\n"])), _variables.FontFamily.Raleway_600, _variables.GlobalColors.deep_gray, _variables.GlobalColors.gray);
29
+ var Header = _styledComponents.default.div(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2.default)(["\n padding: 20px 24px 12px;\n\n h2 {\n margin: 0;\n font-family: ", ";\n font-size: 17px;\n color: ", ";\n }\n\n p {\n margin: 4px 0 0;\n font-size: 13px;\n line-height: 1.4;\n color: ", ";\n }\n"])), _variables.FontFamily.Raleway_700, _variables.GlobalColors.deep_gray, _variables.GlobalColors.gray);
30
30
 
31
31
  exports.Header = Header;
32
32
 
33
- var Body = _styledComponents.default.div(_templateObject4 || (_templateObject4 = (0, _taggedTemplateLiteral2.default)(["\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 4px 22px 8px;\n"])));
33
+ var Body = _styledComponents.default.div(_templateObject4 || (_templateObject4 = (0, _taggedTemplateLiteral2.default)(["\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 4px 24px 12px;\n"])));
34
34
 
35
35
  exports.Body = Body;
36
36
 
37
- var SearchRow = _styledComponents.default.form(_templateObject5 || (_templateObject5 = (0, _taggedTemplateLiteral2.default)(["\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n\n input {\n flex: 1;\n min-width: 0;\n height: 38px;\n padding: 0 12px;\n border: 1px solid ", ";\n border-radius: 6px;\n font-family: inherit;\n font-size: 13px;\n color: ", ";\n }\n\n input:focus {\n outline: none;\n border-color: ", ";\n }\n"])), _variables.GlobalColors.s2, _variables.GlobalColors.deep_gray, PINK);
37
+ var SearchRow = _styledComponents.default.form(_templateObject5 || (_templateObject5 = (0, _taggedTemplateLiteral2.default)(["\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n\n input {\n flex: 1;\n min-width: 0;\n height: 36px;\n padding: 0 12px;\n border: 1px solid ", ";\n border-radius: 6px;\n font-family: ", ";\n font-size: 13px;\n color: ", ";\n }\n\n input:focus {\n outline: none;\n border-color: ", ";\n }\n\n /*\n Estas reglas faltaban y el bot\xF3n se sal\xEDa del panel.\n\n Llevaba className=\"secondary\", pero esa clase solo est\xE1 definida dentro de\n Footer, as\xED que aqu\xED no aplicaba nada: sal\xEDa como un bot\xF3n crudo del\n navegador, sin altura ni ancho acotados. El flex-shrink es para que el texto\n no se parta cuando el campo de b\xFAsqueda se lleva el espacio.\n */\n button {\n flex-shrink: 0;\n height: 36px;\n padding: 0 18px;\n border: none;\n border-radius: 6px;\n background-color: ", ";\n color: ", ";\n font-family: ", ";\n font-size: 13px;\n cursor: pointer;\n }\n\n button:disabled {\n opacity: 0.5;\n cursor: default;\n }\n"])), _variables.GlobalColors.s2, _variables.FontFamily.Raleway, _variables.GlobalColors.deep_gray, PINK, PINK, _variables.GlobalColors.white, _variables.FontFamily.Raleway_600);
38
38
 
39
39
  exports.SearchRow = SearchRow;
40
40
 
@@ -42,7 +42,7 @@ var List = _styledComponents.default.ul(_templateObject6 || (_templateObject6 =
42
42
 
43
43
  exports.List = List;
44
44
 
45
- var NewGroup = _styledComponents.default.div(_templateObject7 || (_templateObject7 = (0, _taggedTemplateLiteral2.default)(["\n padding: 12px;\n border: 1px dashed rgba(", ", 0.5);\n border-radius: 6px;\n background-color: rgba(", ", 0.04);\n\n label {\n display: block;\n margin-bottom: 6px;\n font-family: ", ";\n font-size: 12px;\n color: ", ";\n }\n\n input {\n width: 100%;\n height: 38px;\n padding: 0 12px;\n border: 1px solid ", ";\n border-radius: 6px;\n font-family: inherit;\n font-size: 13px;\n text-transform: uppercase;\n color: ", ";\n }\n\n input:focus {\n outline: none;\n border-color: ", ";\n }\n\n .ayuda {\n display: block;\n margin-top: 6px;\n font-size: 11px;\n line-height: 1.4;\n color: ", ";\n }\n"])), PINK_RGB, PINK_RGB, _variables.FontFamily.Raleway_600, _variables.GlobalColors.deep_gray, _variables.GlobalColors.s2, _variables.GlobalColors.deep_gray, PINK, _variables.GlobalColors.gray);
45
+ var NewGroup = _styledComponents.default.div(_templateObject7 || (_templateObject7 = (0, _taggedTemplateLiteral2.default)(["\n padding: 12px;\n border: 1px dashed rgba(", ", 0.5);\n border-radius: 6px;\n background-color: rgba(", ", 0.04);\n\n label {\n display: block;\n margin-bottom: 6px;\n font-family: ", ";\n font-size: 12px;\n color: ", ";\n }\n\n input {\n width: 100%;\n height: 36px;\n padding: 0 12px;\n border: 1px solid ", ";\n border-radius: 6px;\n font-family: inherit;\n font-size: 13px;\n text-transform: uppercase;\n color: ", ";\n }\n\n input:focus {\n outline: none;\n border-color: ", ";\n }\n\n .ayuda {\n display: block;\n margin-top: 6px;\n font-size: 11px;\n line-height: 1.4;\n color: ", ";\n }\n"])), PINK_RGB, PINK_RGB, _variables.FontFamily.Raleway_600, _variables.GlobalColors.deep_gray, _variables.GlobalColors.s2, _variables.GlobalColors.deep_gray, PINK, _variables.GlobalColors.gray);
46
46
 
47
47
  exports.NewGroup = NewGroup;
48
48
 
@@ -50,6 +50,6 @@ var Message = _styledComponents.default.p(_templateObject8 || (_templateObject8
50
50
 
51
51
  exports.Message = Message;
52
52
 
53
- var Footer = _styledComponents.default.div(_templateObject9 || (_templateObject9 = (0, _taggedTemplateLiteral2.default)(["\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 14px 22px 18px;\n border-top: 1px solid ", ";\n\n .resumen {\n font-size: 12px;\n color: ", ";\n }\n\n .acciones {\n display: flex;\n gap: 10px;\n }\n\n button {\n height: 38px;\n padding: 0 16px;\n border-radius: 6px;\n cursor: pointer;\n font-family: ", ";\n font-size: 13px;\n }\n\n button:disabled {\n opacity: 0.5;\n cursor: default;\n }\n\n .secondary {\n border: 1px solid ", ";\n background: none;\n color: ", ";\n }\n\n .primary {\n border: 1px solid ", ";\n background-color: ", ";\n color: ", ";\n }\n"])), _variables.GlobalColors.s2, _variables.GlobalColors.gray, _variables.FontFamily.Raleway_600, _variables.GlobalColors.s2, _variables.GlobalColors.deep_gray, PINK, PINK, _variables.GlobalColors.white);
53
+ var Footer = _styledComponents.default.div(_templateObject9 || (_templateObject9 = (0, _taggedTemplateLiteral2.default)(["\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 16px 24px;\n border-top: 1px solid ", ";\n\n .resumen {\n font-size: 12px;\n color: ", ";\n }\n\n .acciones {\n display: flex;\n gap: 10px;\n }\n\n button {\n height: 38px;\n padding: 0 16px;\n border-radius: 6px;\n cursor: pointer;\n font-family: ", ";\n font-size: 13px;\n }\n\n button:disabled {\n opacity: 0.5;\n cursor: default;\n }\n\n .secondary {\n border: 1px solid ", ";\n background: none;\n color: ", ";\n }\n\n .primary {\n border: 1px solid ", ";\n background-color: ", ";\n color: ", ";\n }\n"])), _variables.GlobalColors.s2, _variables.GlobalColors.gray, _variables.FontFamily.Raleway_600, _variables.GlobalColors.s2, _variables.GlobalColors.deep_gray, PINK, PINK, _variables.GlobalColors.white);
54
54
 
55
55
  exports.Footer = Footer;
@@ -94,7 +94,7 @@ var _AiProductEdition = require("../../../contexts/AiProductEdition");
94
94
  var _jsxRuntime = require("react/jsx-runtime");
95
95
 
96
96
  var ProviderProductEditionView = function ProviderProductEditionView(_ref) {
97
- var _location$state4, _state$product2, _state$product3, _state$product4, _state$product5, _state$product6, _state$product7, _state$product15, _family$variants2, _state$product20, _state$product21, _state$product22, _state$active_retaile4, _state$product23, _state$product24, _state$product25, _variantGroup$group, _location$state5, _location$state6, _state$active_retaile5, _state$active_retaile6, _state$images_values$2, _state$images_values10, _state$images_values11, _state$active_retaile7, _state$product26, _state$product27, _state$product28, _state$product29, _family$variants3, _family$variants4, _family$variants5, _variantGroup$members, _variantGroup$members2, _state$active_percent, _state$active_percent2, _state$active_retaile8, _state$active_retaile9, _state$active_retaile10, _state$product35, _state$descriptions_i, _state$services2, _state$services2$data, _state$product36, _state$product37, _state$datasheets_inp, _state$datasheets_inp2, _state$datasheets_inp3, _state$product38, _state$images_values12;
97
+ var _location$state4, _state$product2, _state$product3, _state$product4, _state$product5, _state$product6, _state$product7, _state$product15, _family$variants2, _variantGroup$members2, _variantGroup$group, _state$product20, _state$product21, _state$product22, _state$active_retaile4, _state$product23, _state$product24, _state$product25, _variantGroup$group2, _location$state5, _location$state6, _state$active_retaile5, _state$active_retaile6, _state$images_values$2, _state$images_values10, _state$images_values11, _state$active_retaile7, _state$product26, _state$product27, _state$product28, _state$product29, _family$variants3, _family$variants4, _family$variants5, _variantGroup$members3, _variantGroup$members4, _state$active_percent, _state$active_percent2, _state$active_retaile8, _state$active_retaile9, _state$active_retaile10, _state$product35, _state$descriptions_i, _state$services2, _state$services2$data, _state$product36, _state$product37, _state$datasheets_inp, _state$datasheets_inp2, _state$datasheets_inp3, _state$product38, _state$images_values12;
98
98
 
99
99
  var tabsSections = _ref.tabsSections,
100
100
  _ref$productSelected = _ref.productSelected,
@@ -882,15 +882,24 @@ var ProviderProductEditionView = function ProviderProductEditionView(_ref) {
882
882
 
883
883
  case "Ficha técnica":
884
884
  {
885
- var _state$product10;
885
+ var _variantGroup$members, _state$product10;
886
886
 
887
887
  // Guardar un padre con hijos abre la decisión de propagar. Sin este
888
888
  // paso el cambio se queda solo en el padre y los hijos se van
889
889
  // separando de él sin que nadie lo note.
890
- var esPadre = ((_state$product10 = state.product) === null || _state$product10 === void 0 ? void 0 : _state$product10.variantsCount) > 0;
890
+
891
+ /*
892
+ El diálogo se abre si hay ALGÚN destino posible, no solo hijos: un
893
+ producto puede no tener hijos y aun así pertenecer a un grupo de
894
+ variantes, y ese cambio también se le puede copiar a sus compañeras.
895
+ */
896
+ var companeras = ((_variantGroup$members = variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.members) !== null && _variantGroup$members !== void 0 ? _variantGroup$members : []).filter(function (m) {
897
+ return !m.isCurrent;
898
+ });
899
+ var hayDestinos = ((_state$product10 = state.product) === null || _state$product10 === void 0 ? void 0 : _state$product10.variantsCount) > 0 || companeras.length > 0;
891
900
  var cambios = cambiosDeFichaTecnica();
892
901
 
893
- if (esPadre && cambios.length > 0) {
902
+ if (hayDestinos && cambios.length > 0) {
894
903
  // Se espera a tener la familia antes de abrir: si no, el diálogo
895
904
  // aparece diciendo "0 hijos" hasta que llega la respuesta, que es
896
905
  // justo lo contrario de lo que va a preguntar.
@@ -2116,6 +2125,10 @@ var ProviderProductEditionView = function ProviderProductEditionView(_ref) {
2116
2125
  variants: ((_family$variants2 = family === null || family === void 0 ? void 0 : family.variants) !== null && _family$variants2 !== void 0 ? _family$variants2 : []).filter(function (v) {
2117
2126
  return !v.isCurrent;
2118
2127
  }),
2128
+ groupMembers: ((_variantGroup$members2 = variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.members) !== null && _variantGroup$members2 !== void 0 ? _variantGroup$members2 : []).filter(function (m) {
2129
+ return !m.isCurrent;
2130
+ }),
2131
+ groupCode: (_variantGroup$group = variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.group) !== null && _variantGroup$group !== void 0 ? _variantGroup$group : null,
2119
2132
  saving: state.saving,
2120
2133
  onCancel: function onCancel() {
2121
2134
  return setPendingPropagation(null);
@@ -2138,7 +2151,7 @@ var ProviderProductEditionView = function ProviderProductEditionView(_ref) {
2138
2151
  articleId: (_state$product23 = state.product) === null || _state$product23 === void 0 ? void 0 : _state$product23.id_article,
2139
2152
  articleName: (_state$product24 = state.product) === null || _state$product24 === void 0 ? void 0 : _state$product24.name,
2140
2153
  articleUpc: (_state$product25 = state.product) === null || _state$product25 === void 0 ? void 0 : _state$product25.upc,
2141
- currentGroup: (_variantGroup$group = variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.group) !== null && _variantGroup$group !== void 0 ? _variantGroup$group : null,
2154
+ currentGroup: (_variantGroup$group2 = variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.group) !== null && _variantGroup$group2 !== void 0 ? _variantGroup$group2 : null,
2142
2155
  token: token,
2143
2156
  onClose: function onClose() {
2144
2157
  return setShowGroupModal(false);
@@ -2469,7 +2482,7 @@ var ProviderProductEditionView = function ProviderProductEditionView(_ref) {
2469
2482
  })]
2470
2483
  }), showGroup && (variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.group) && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
2471
2484
  className: "variants-family",
2472
- children: [((_variantGroup$members = variantGroup.members) !== null && _variantGroup$members !== void 0 ? _variantGroup$members : []).filter(function (miembro) {
2485
+ children: [((_variantGroup$members3 = variantGroup.members) !== null && _variantGroup$members3 !== void 0 ? _variantGroup$members3 : []).filter(function (miembro) {
2473
2486
  return !miembro.isCurrent;
2474
2487
  }).map(function (miembro) {
2475
2488
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
@@ -2493,7 +2506,7 @@ var ProviderProductEditionView = function ProviderProductEditionView(_ref) {
2493
2506
  })]
2494
2507
  })
2495
2508
  }, miembro.articleId);
2496
- }), ((_variantGroup$members2 = variantGroup.members) !== null && _variantGroup$members2 !== void 0 ? _variantGroup$members2 : []).filter(function (m) {
2509
+ }), ((_variantGroup$members4 = variantGroup.members) !== null && _variantGroup$members4 !== void 0 ? _variantGroup$members4 : []).filter(function (m) {
2497
2510
  return !m.isCurrent;
2498
2511
  }).length === 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)("p", {
2499
2512
  className: "loading",
@@ -109,7 +109,7 @@ var _material = require("@mui/material");
109
109
 
110
110
  var _jsxRuntime = require("react/jsx-runtime");
111
111
 
112
- var allowedAccountsToViewChangeStatus = ["mperez@contentoh.com", "gmorales@contentoh.com", "rvega@contentoh.com", "amora@contentoh.com", //PRODUCT DEV ACCOUNTS
112
+ var allowedAccountsToViewChangeStatus = ["mperez@contentoh.com", "gmorales@contentoh.com", "rvega@contentoh.com", "amora@contentoh.com", "maltamirano@contentoh.com", //PRODUCT DEV ACCOUNTS
113
113
  "oparra@contentoh.com", "zsegura@contentoh.com", "oserna@contentoh.com", "jalvarado@contentoh.com", //DEV ACCOUNTS
114
114
  "kikije1467@mtlcz.com", //IMÁGENES
115
115
  "karafe3218@mom2kid.com", //TEXTOS
@@ -238,7 +238,7 @@ function _regenerateVideoThumbnails() {
238
238
  }
239
239
 
240
240
  var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
241
- var _state$product10, _family$variants, _state$product11, _state$product15, _state$errors, _family$variants2, _state$product19, _state$product20, _state$product21, _state$active_retaile6, _state$product22, _state$product23, _state$product24, _variantGroup$group, _location$state, _location$state2, _state$active_retaile7, _state$active_retaile8, _state$images_values$2, _state$images_values10, _state$images_values11, _state$product25, _state$active_retaile9, _family$variants3, _family$variants4, _variantGroup$members, _variantGroup$members2, _state$active_percent, _state$active_percent2, _state$active_percent3, _state$active_retaile10, _state$active_retaile11, _state$active_retaile12, _state$product31, _state$services2, _state$services2$data, _state$product32, _state$product33, _state$datasheets_inp, _state$datasheets_inp2, _state$product34, _state$images_values12, _state$comment;
241
+ var _state$product10, _family$variants, _state$product11, _state$product15, _state$errors, _family$variants2, _variantGroup$members2, _variantGroup$group, _state$product19, _state$product20, _state$product21, _state$active_retaile6, _state$product22, _state$product23, _state$product24, _variantGroup$group2, _location$state, _location$state2, _state$active_retaile7, _state$active_retaile8, _state$images_values$2, _state$images_values10, _state$images_values11, _state$product25, _state$active_retaile9, _family$variants3, _family$variants4, _variantGroup$members3, _variantGroup$members4, _state$active_percent, _state$active_percent2, _state$active_percent3, _state$active_retaile10, _state$active_retaile11, _state$active_retaile12, _state$product31, _state$services2, _state$services2$data, _state$product32, _state$product33, _state$datasheets_inp, _state$datasheets_inp2, _state$product34, _state$images_values12, _state$comment;
242
242
 
243
243
  var tabsSections = _ref.tabsSections,
244
244
  _ref$productSelected = _ref.productSelected,
@@ -1811,7 +1811,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1811
1811
 
1812
1812
  var handleOnClickSave = /*#__PURE__*/function () {
1813
1813
  var _ref16 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee11() {
1814
- var _familia$variants, cambios, familia, hijos;
1814
+ var _familia$variants, _variantGroup$members, cambios, familia, hijos, companeras;
1815
1815
 
1816
1816
  return _regenerator.default.wrap(function _callee11$(_context11) {
1817
1817
  while (1) {
@@ -1826,7 +1826,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1826
1826
 
1827
1827
  case 2:
1828
1828
  _context11.t0 = state.active_tab;
1829
- _context11.next = _context11.t0 === "Descripción" ? 5 : _context11.t0 === "Ficha técnica" ? 8 : _context11.t0 === "Imágenes" ? 32 : 35;
1829
+ _context11.next = _context11.t0 === "Descripción" ? 5 : _context11.t0 === "Ficha técnica" ? 8 : _context11.t0 === "Imágenes" ? 33 : 36;
1830
1830
  break;
1831
1831
 
1832
1832
  case 5:
@@ -1834,7 +1834,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1834
1834
  return saveDescriptions(token);
1835
1835
 
1836
1836
  case 7:
1837
- return _context11.abrupt("break", 36);
1837
+ return _context11.abrupt("break", 37);
1838
1838
 
1839
1839
  case 8:
1840
1840
  cambios = cambiosDeFichaTecnica();
@@ -1848,7 +1848,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1848
1848
  return saveDatasheets(token);
1849
1849
 
1850
1850
  case 12:
1851
- return _context11.abrupt("break", 36);
1851
+ return _context11.abrupt("break", 37);
1852
1852
 
1853
1853
  case 13:
1854
1854
  /*
@@ -1924,9 +1924,18 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1924
1924
  hijos = ((_familia$variants = familia.variants) !== null && _familia$variants !== void 0 ? _familia$variants : []).filter(function (v) {
1925
1925
  return !v.isCurrent;
1926
1926
  });
1927
+ /*
1928
+ También cuentan las compañeras de grupo: un producto puede no tener
1929
+ hijos y aun así pertenecer a un grupo de variantes, y el cambio se les
1930
+ puede copiar igual. Si no se miraran, guardar no ofrecería nada.
1931
+ */
1932
+
1933
+ companeras = ((_variantGroup$members = variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.members) !== null && _variantGroup$members !== void 0 ? _variantGroup$members : []).filter(function (m) {
1934
+ return !m.isCurrent;
1935
+ });
1927
1936
 
1928
- if (!(hijos.length > 0)) {
1929
- _context11.next = 29;
1937
+ if (!(hijos.length > 0 || companeras.length > 0)) {
1938
+ _context11.next = 30;
1930
1939
  break;
1931
1940
  }
1932
1941
 
@@ -1935,28 +1944,28 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1935
1944
  });
1936
1945
  return _context11.abrupt("return");
1937
1946
 
1938
- case 29:
1939
- _context11.next = 31;
1947
+ case 30:
1948
+ _context11.next = 32;
1940
1949
  return saveDatasheets(token);
1941
1950
 
1942
- case 31:
1943
- return _context11.abrupt("break", 36);
1944
-
1945
1951
  case 32:
1946
- _context11.next = 34;
1947
- return updateImages(token);
1952
+ return _context11.abrupt("break", 37);
1948
1953
 
1949
- case 34:
1950
- return _context11.abrupt("break", 36);
1954
+ case 33:
1955
+ _context11.next = 35;
1956
+ return updateImages(token);
1951
1957
 
1952
1958
  case 35:
1953
- return _context11.abrupt("break", 36);
1959
+ return _context11.abrupt("break", 37);
1954
1960
 
1955
1961
  case 36:
1956
- _context11.next = 38;
1962
+ return _context11.abrupt("break", 37);
1963
+
1964
+ case 37:
1965
+ _context11.next = 39;
1957
1966
  return loadData(false);
1958
1967
 
1959
- case 38:
1968
+ case 39:
1960
1969
  case "end":
1961
1970
  return _context11.stop();
1962
1971
  }
@@ -2888,6 +2897,10 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
2888
2897
  variants: ((_family$variants2 = family === null || family === void 0 ? void 0 : family.variants) !== null && _family$variants2 !== void 0 ? _family$variants2 : []).filter(function (v) {
2889
2898
  return !v.isCurrent;
2890
2899
  }),
2900
+ groupMembers: ((_variantGroup$members2 = variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.members) !== null && _variantGroup$members2 !== void 0 ? _variantGroup$members2 : []).filter(function (m) {
2901
+ return !m.isCurrent;
2902
+ }),
2903
+ groupCode: (_variantGroup$group = variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.group) !== null && _variantGroup$group !== void 0 ? _variantGroup$group : null,
2891
2904
  saving: state.saving,
2892
2905
  onCancel: function onCancel() {
2893
2906
  return setPendingPropagation(null);
@@ -2910,7 +2923,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
2910
2923
  articleId: (_state$product22 = state.product) === null || _state$product22 === void 0 ? void 0 : _state$product22.id_article,
2911
2924
  articleName: (_state$product23 = state.product) === null || _state$product23 === void 0 ? void 0 : _state$product23.name,
2912
2925
  articleUpc: (_state$product24 = state.product) === null || _state$product24 === void 0 ? void 0 : _state$product24.upc,
2913
- currentGroup: (_variantGroup$group = variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.group) !== null && _variantGroup$group !== void 0 ? _variantGroup$group : null,
2926
+ currentGroup: (_variantGroup$group2 = variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.group) !== null && _variantGroup$group2 !== void 0 ? _variantGroup$group2 : null,
2914
2927
  token: token,
2915
2928
  onClose: function onClose() {
2916
2929
  return setShowGroupModal(false);
@@ -3251,7 +3264,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
3251
3264
  })]
3252
3265
  }), showGroup && (variantGroup === null || variantGroup === void 0 ? void 0 : variantGroup.group) && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
3253
3266
  className: "variants-family",
3254
- children: [((_variantGroup$members = variantGroup.members) !== null && _variantGroup$members !== void 0 ? _variantGroup$members : []).filter(function (miembro) {
3267
+ children: [((_variantGroup$members3 = variantGroup.members) !== null && _variantGroup$members3 !== void 0 ? _variantGroup$members3 : []).filter(function (miembro) {
3255
3268
  return !miembro.isCurrent;
3256
3269
  }).map(function (miembro) {
3257
3270
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
@@ -3275,7 +3288,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
3275
3288
  })]
3276
3289
  })
3277
3290
  }, miembro.articleId);
3278
- }), ((_variantGroup$members2 = variantGroup.members) !== null && _variantGroup$members2 !== void 0 ? _variantGroup$members2 : []).filter(function (m) {
3291
+ }), ((_variantGroup$members4 = variantGroup.members) !== null && _variantGroup$members4 !== void 0 ? _variantGroup$members4 : []).filter(function (m) {
3279
3292
  return !m.isCurrent;
3280
3293
  }).length === 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)("p", {
3281
3294
  className: "loading",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contentoh-components-library",
3
- "version": "21.6.45",
3
+ "version": "21.6.48",
4
4
  "dependencies": {
5
5
  "@aws-amplify/auth": "^4.5.3",
6
6
  "@aws-amplify/datastore": "^3.11.0",
@@ -40,15 +40,50 @@ const UMBRAL_SEGUNDO_PLANO = 20;
40
40
  export const PropagateChangesModal = ({
41
41
  changedAttributes = [],
42
42
  variants = [],
43
+ groupMembers = [],
44
+ groupCode = null,
43
45
  onCancel,
44
46
  onConfirm,
45
47
  saving = false,
46
48
  }) => {
47
49
  const [chosenAttributes, setChosenAttributes] = useState([]);
48
- const [scope, setScope] = useState("all");
50
+
51
+ /*
52
+ DOS DESTINOS INDEPENDIENTES, y esa independencia es el punto.
53
+
54
+ hijos cuelgan de este producto y heredan de él. Hay jerarquía.
55
+ variantes comparten un código de grupo. No hay jerarquía; son el mismo
56
+ producto en otra presentación.
57
+
58
+ Elegir variantes NO debe alcanzar a los hijos ni al revés, así que cada uno
59
+ lleva su propio alcance y su propia selección. Un solo control con tres
60
+ opciones —hijos / variantes / ambos— no bastaría: el usuario también tiene
61
+ que poder decir "a estas dos variantes y a ese hijo".
62
+
63
+ Arrancan en "none" los dos: propagar sobrescribe, así que ningún destino se
64
+ da por elegido sin que alguien lo pida.
65
+ */
66
+ const [scopeChildren, setScopeChildren] = useState("none");
49
67
  const [chosenChildren, setChosenChildren] = useState([]);
68
+ const [scopeVariants, setScopeVariants] = useState("none");
69
+ const [chosenVariants, setChosenVariants] = useState([]);
50
70
 
51
- const destinatarios = scope === "all" ? variants.length : chosenChildren.length;
71
+ const seleccion = (scope, todos, elegidos) => {
72
+ if (scope === "none") return [];
73
+ if (scope === "all") return todos;
74
+ return todos.filter((item) => elegidos.includes(item.articleId));
75
+ };
76
+
77
+ const hijosDestino = seleccion(scopeChildren, variants, chosenChildren);
78
+ const variantesDestino = seleccion(scopeVariants, groupMembers, chosenVariants);
79
+
80
+ // Un producto puede ser hijo Y estar en el grupo: se cuenta una sola vez.
81
+ const idsDestino = new Set([
82
+ ...hijosDestino.map((x) => x.articleId),
83
+ ...variantesDestino.map((x) => x.articleId),
84
+ ]);
85
+
86
+ const destinatarios = idsDestino.size;
52
87
  const puedePropagar = chosenAttributes.length > 0 && destinatarios > 0;
53
88
  const enSegundoPlano = destinatarios > UMBRAL_SEGUNDO_PLANO;
54
89
 
@@ -64,9 +99,9 @@ export const PropagateChangesModal = ({
64
99
  desmarca el atributo conflictivo, el aviso desaparece — que es justo la
65
100
  salida que el aviso debería estar ofreciendo.
66
101
  */
67
- const destinos = scope === "all"
68
- ? variants
69
- : variants.filter((item) => chosenChildren.includes(item.articleId));
102
+ const destinos = [...hijosDestino, ...variantesDestino].filter(
103
+ (item, i, lista) => lista.findIndex((x) => x.articleId === item.articleId) === i
104
+ );
70
105
 
71
106
  const conValorPropio = destinos
72
107
  .map((hijo) => ({
@@ -85,18 +120,30 @@ export const PropagateChangesModal = ({
85
120
  );
86
121
  };
87
122
 
88
- const toggleChild = (id) => {
89
- setChosenChildren((current) =>
123
+ const toggleEn = (setter) => (id) => {
124
+ setter((current) =>
90
125
  current.includes(id)
91
126
  ? current.filter((item) => item !== id)
92
127
  : [...current, id]
93
128
  );
94
129
  };
95
130
 
131
+ const toggleChild = toggleEn(setChosenChildren);
132
+ const toggleVariant = toggleEn(setChosenVariants);
133
+
96
134
  const confirmar = () => {
135
+ // Se manda "none" explícito y no una lista vacía para que el servidor no
136
+ // tenga que adivinar si "sin ids" quiere decir "a ninguno" o "no me lo
137
+ // preguntaron". Cada destino viaja por su cuenta.
138
+ const comoLista = (scope, elegidos) => {
139
+ if (scope === "none") return "none";
140
+ return scope === "all" ? "all" : elegidos;
141
+ };
142
+
97
143
  onConfirm?.({
98
144
  attributes: chosenAttributes,
99
- targetChildren: scope === "all" ? "all" : chosenChildren,
145
+ targetChildren: comoLista(scopeChildren, chosenChildren),
146
+ targetVariants: comoLista(scopeVariants, chosenVariants),
100
147
  });
101
148
  };
102
149
 
@@ -105,18 +152,29 @@ export const PropagateChangesModal = ({
105
152
  <Panel onClick={(event) => event.stopPropagation()}>
106
153
  <Header>
107
154
  <h2>
108
- Este producto tiene {variants.length} hijo
109
- {variants.length === 1 ? "" : "s"}
155
+ {[
156
+ variants.length
157
+ ? `${variants.length} hijo${variants.length === 1 ? "" : "s"}`
158
+ : null,
159
+ groupMembers.length
160
+ ? `${groupMembers.length} variante${
161
+ groupMembers.length === 1 ? "" : "s"
162
+ }`
163
+ : null,
164
+ ]
165
+ .filter(Boolean)
166
+ .join(" y ")}
167
+ {" pueden recibir este cambio"}
110
168
  </h2>
111
169
  <p>
112
170
  Cambiaste {changedAttributes.length} atributo
113
- {changedAttributes.length === 1 ? "" : "s"}. Elige cuáles bajan a los
114
- hijos; el resto se guarda solo en este producto.
171
+ {changedAttributes.length === 1 ? "" : "s"}. Elige cuáles se copian y
172
+ a quiénes; el resto se guarda solo en este producto.
115
173
  </p>
116
174
  </Header>
117
175
 
118
176
  <Body>
119
- <h3>¿Qué se baja a los hijos?</h3>
177
+ <h3>¿Qué se copia?</h3>
120
178
  <List>
121
179
  {changedAttributes.map((attribute) => (
122
180
  <li key={attribute.id}>
@@ -135,52 +193,124 @@ export const PropagateChangesModal = ({
135
193
  ))}
136
194
  </List>
137
195
 
138
- <h3>¿A cuáles?</h3>
139
- <Choices>
140
- <label>
141
- <input
142
- type="radio"
143
- name="propagation-scope"
144
- checked={scope === "all"}
145
- onChange={() => setScope("all")}
146
- />
147
- <span>
148
- A todos
149
- <span className="hint">
150
- {variants.length} hijo{variants.length === 1 ? "" : "s"} activo
151
- {variants.length === 1 ? "" : "s"}.
152
- </span>
153
- </span>
154
- </label>
155
- <label>
156
- <input
157
- type="radio"
158
- name="propagation-scope"
159
- checked={scope === "some"}
160
- onChange={() => setScope("some")}
161
- />
162
- <span>Elegir cuáles</span>
163
- </label>
164
- </Choices>
165
-
166
- {scope === "some" && (
167
- <List>
168
- {variants.map((variant) => (
169
- <li key={variant.articleId}>
170
- <label>
171
- <input
172
- type="checkbox"
173
- checked={chosenChildren.includes(variant.articleId)}
174
- onChange={() => toggleChild(variant.articleId)}
175
- />
176
- <span>
177
- {variant.name}
178
- <span className="meta">UPC {variant.upc || "—"}</span>
179
- </span>
180
- </label>
181
- </li>
182
- ))}
183
- </List>
196
+ {/* Cada destino con su propio alcance. Van separados porque
197
+ propagar a las variantes NO debe alcanzar a los hijos: si fuera
198
+ un solo control, elegir "todos" mandaría a los dos lados. */}
199
+ {variants.length > 0 && (
200
+ <>
201
+ <h3>
202
+ ¿A cuáles de los {variants.length} hijo
203
+ {variants.length === 1 ? "" : "s"}?
204
+ </h3>
205
+ <Choices>
206
+ <label>
207
+ <input
208
+ type="radio"
209
+ name="scope-children"
210
+ checked={scopeChildren === "none"}
211
+ onChange={() => setScopeChildren("none")}
212
+ />
213
+ <span>A ninguno</span>
214
+ </label>
215
+ <label>
216
+ <input
217
+ type="radio"
218
+ name="scope-children"
219
+ checked={scopeChildren === "all"}
220
+ onChange={() => setScopeChildren("all")}
221
+ />
222
+ <span>A todos</span>
223
+ </label>
224
+ <label>
225
+ <input
226
+ type="radio"
227
+ name="scope-children"
228
+ checked={scopeChildren === "some"}
229
+ onChange={() => setScopeChildren("some")}
230
+ />
231
+ <span>Elegir cuáles</span>
232
+ </label>
233
+ </Choices>
234
+
235
+ {scopeChildren === "some" && (
236
+ <List>
237
+ {variants.map((variant) => (
238
+ <li key={variant.articleId}>
239
+ <label>
240
+ <input
241
+ type="checkbox"
242
+ checked={chosenChildren.includes(variant.articleId)}
243
+ onChange={() => toggleChild(variant.articleId)}
244
+ />
245
+ <span>
246
+ {variant.name}
247
+ <span className="meta">UPC {variant.upc || "—"}</span>
248
+ </span>
249
+ </label>
250
+ </li>
251
+ ))}
252
+ </List>
253
+ )}
254
+ </>
255
+ )}
256
+
257
+ {groupMembers.length > 0 && (
258
+ <>
259
+ <h3>
260
+ ¿A cuáles de las {groupMembers.length} variante
261
+ {groupMembers.length === 1 ? "" : "s"}
262
+ {groupCode ? ` del grupo ${groupCode}` : ""}?
263
+ </h3>
264
+ <Choices>
265
+ <label>
266
+ <input
267
+ type="radio"
268
+ name="scope-variants"
269
+ checked={scopeVariants === "none"}
270
+ onChange={() => setScopeVariants("none")}
271
+ />
272
+ <span>A ninguna</span>
273
+ </label>
274
+ <label>
275
+ <input
276
+ type="radio"
277
+ name="scope-variants"
278
+ checked={scopeVariants === "all"}
279
+ onChange={() => setScopeVariants("all")}
280
+ />
281
+ <span>A todas</span>
282
+ </label>
283
+ <label>
284
+ <input
285
+ type="radio"
286
+ name="scope-variants"
287
+ checked={scopeVariants === "some"}
288
+ onChange={() => setScopeVariants("some")}
289
+ />
290
+ <span>Elegir cuáles</span>
291
+ </label>
292
+ </Choices>
293
+
294
+ {scopeVariants === "some" && (
295
+ <List>
296
+ {groupMembers.map((miembro) => (
297
+ <li key={miembro.articleId}>
298
+ <label>
299
+ <input
300
+ type="checkbox"
301
+ checked={chosenVariants.includes(miembro.articleId)}
302
+ onChange={() => toggleVariant(miembro.articleId)}
303
+ />
304
+ <span>
305
+ {miembro.name}
306
+ <span className="meta">UPC {miembro.upc || "—"}</span>
307
+ </span>
308
+ </label>
309
+ </li>
310
+ ))}
311
+ </List>
312
+ )}
313
+ </>
184
314
  )}
185
315
 
186
316
  {/* Lo que sorprende si no se dice: aquí se pisa lo que el hijo
@@ -209,9 +339,11 @@ export const PropagateChangesModal = ({
209
339
 
210
340
  <Footer>
211
341
  <span className="resumen">
342
+ {/* Se cuentan los destinos DISTINTOS: un producto que es hijo y
343
+ además comparte grupo recibe el valor una sola vez. */}
212
344
  {puedePropagar
213
- ? `${chosenAttributes.length} atributo(s) a ${destinatarios} hijo(s).`
214
- : "No se bajará nada a los hijos."}
345
+ ? `${chosenAttributes.length} atributo(s) a ${destinatarios} producto(s).`
346
+ : "No se copiará nada: elige al menos un atributo y un destino."}
215
347
  </span>
216
348
  <button
217
349
  type="button"
@@ -163,7 +163,7 @@ export const VariantGroupModal = ({
163
163
  placeholder="Busca un grupo por su código"
164
164
  onChange={(event) => setQuery(event.target.value)}
165
165
  />
166
- <button type="submit" className="secondary" disabled={loading}>
166
+ <button type="submit" disabled={loading}>
167
167
  {loading ? "Buscando…" : "Buscar"}
168
168
  </button>
169
169
  </SearchRow>
@@ -18,8 +18,8 @@ export const Overlay = styled.div`
18
18
  export const Panel = styled.div`
19
19
  display: flex;
20
20
  flex-direction: column;
21
- width: min(520px, 94vw);
22
- max-height: 88vh;
21
+ width: min(560px, 92vw);
22
+ max-height: 86vh;
23
23
  border-radius: 10px;
24
24
  background-color: ${GlobalColors.white};
25
25
  font-family: ${FontFamily.Raleway};
@@ -27,17 +27,17 @@ export const Panel = styled.div`
27
27
  `;
28
28
 
29
29
  export const Header = styled.div`
30
- padding: 18px 22px 12px;
30
+ padding: 20px 24px 12px;
31
31
 
32
32
  h2 {
33
33
  margin: 0;
34
- font-family: ${FontFamily.Raleway_600};
35
- font-size: 16px;
34
+ font-family: ${FontFamily.Raleway_700};
35
+ font-size: 17px;
36
36
  color: ${GlobalColors.deep_gray};
37
37
  }
38
38
 
39
39
  p {
40
- margin: 6px 0 0;
40
+ margin: 4px 0 0;
41
41
  font-size: 13px;
42
42
  line-height: 1.4;
43
43
  color: ${GlobalColors.gray};
@@ -48,7 +48,7 @@ export const Body = styled.div`
48
48
  flex: 1;
49
49
  min-height: 0;
50
50
  overflow-y: auto;
51
- padding: 4px 22px 8px;
51
+ padding: 4px 24px 12px;
52
52
  `;
53
53
 
54
54
  export const SearchRow = styled.form`
@@ -59,11 +59,11 @@ export const SearchRow = styled.form`
59
59
  input {
60
60
  flex: 1;
61
61
  min-width: 0;
62
- height: 38px;
62
+ height: 36px;
63
63
  padding: 0 12px;
64
64
  border: 1px solid ${GlobalColors.s2};
65
65
  border-radius: 6px;
66
- font-family: inherit;
66
+ font-family: ${FontFamily.Raleway};
67
67
  font-size: 13px;
68
68
  color: ${GlobalColors.deep_gray};
69
69
  }
@@ -72,6 +72,32 @@ export const SearchRow = styled.form`
72
72
  outline: none;
73
73
  border-color: ${PINK};
74
74
  }
75
+
76
+ /*
77
+ Estas reglas faltaban y el botón se salía del panel.
78
+
79
+ Llevaba className="secondary", pero esa clase solo está definida dentro de
80
+ Footer, así que aquí no aplicaba nada: salía como un botón crudo del
81
+ navegador, sin altura ni ancho acotados. El flex-shrink es para que el texto
82
+ no se parta cuando el campo de búsqueda se lleva el espacio.
83
+ */
84
+ button {
85
+ flex-shrink: 0;
86
+ height: 36px;
87
+ padding: 0 18px;
88
+ border: none;
89
+ border-radius: 6px;
90
+ background-color: ${PINK};
91
+ color: ${GlobalColors.white};
92
+ font-family: ${FontFamily.Raleway_600};
93
+ font-size: 13px;
94
+ cursor: pointer;
95
+ }
96
+
97
+ button:disabled {
98
+ opacity: 0.5;
99
+ cursor: default;
100
+ }
75
101
  `;
76
102
 
77
103
  export const List = styled.ul`
@@ -143,7 +169,7 @@ export const NewGroup = styled.div`
143
169
 
144
170
  input {
145
171
  width: 100%;
146
- height: 38px;
172
+ height: 36px;
147
173
  padding: 0 12px;
148
174
  border: 1px solid ${GlobalColors.s2};
149
175
  border-radius: 6px;
@@ -187,7 +213,7 @@ export const Footer = styled.div`
187
213
  align-items: center;
188
214
  justify-content: space-between;
189
215
  gap: 12px;
190
- padding: 14px 22px 18px;
216
+ padding: 16px 24px;
191
217
  border-top: 1px solid ${GlobalColors.s2};
192
218
 
193
219
  .resumen {
@@ -734,10 +734,19 @@ const ProviderProductEditionView = ({
734
734
  // Guardar un padre con hijos abre la decisión de propagar. Sin este
735
735
  // paso el cambio se queda solo en el padre y los hijos se van
736
736
  // separando de él sin que nadie lo note.
737
- const esPadre = state.product?.variantsCount > 0;
737
+ /*
738
+ El diálogo se abre si hay ALGÚN destino posible, no solo hijos: un
739
+ producto puede no tener hijos y aun así pertenecer a un grupo de
740
+ variantes, y ese cambio también se le puede copiar a sus compañeras.
741
+ */
742
+ const companeras = (variantGroup?.members ?? []).filter(
743
+ (m) => !m.isCurrent
744
+ );
745
+ const hayDestinos =
746
+ state.product?.variantsCount > 0 || companeras.length > 0;
738
747
  const cambios = cambiosDeFichaTecnica();
739
748
 
740
- if (esPadre && cambios.length > 0) {
749
+ if (hayDestinos && cambios.length > 0) {
741
750
  // Se espera a tener la familia antes de abrir: si no, el diálogo
742
751
  // aparece diciendo "0 hijos" hasta que llega la respuesta, que es
743
752
  // justo lo contrario de lo que va a preguntar.
@@ -1642,6 +1651,10 @@ const ProviderProductEditionView = ({
1642
1651
  <PropagateChangesModal
1643
1652
  changedAttributes={pendingPropagation.cambios}
1644
1653
  variants={(family?.variants ?? []).filter((v) => !v.isCurrent)}
1654
+ groupMembers={(variantGroup?.members ?? []).filter(
1655
+ (m) => !m.isCurrent
1656
+ )}
1657
+ groupCode={variantGroup?.group ?? null}
1645
1658
  saving={state.saving}
1646
1659
  onCancel={() => setPendingPropagation(null)}
1647
1660
  onConfirm={(propagation) => {
@@ -77,6 +77,7 @@ const allowedAccountsToViewChangeStatus = [
77
77
  "gmorales@contentoh.com",
78
78
  "rvega@contentoh.com",
79
79
  "amora@contentoh.com",
80
+ "maltamirano@contentoh.com",
80
81
  //PRODUCT DEV ACCOUNTS
81
82
  "oparra@contentoh.com",
82
83
  "zsegura@contentoh.com",
@@ -1318,7 +1319,16 @@ const RetailerProductEditionView = ({
1318
1319
 
1319
1320
  const hijos = (familia.variants ?? []).filter((v) => !v.isCurrent);
1320
1321
 
1321
- if (hijos.length > 0) {
1322
+ /*
1323
+ También cuentan las compañeras de grupo: un producto puede no tener
1324
+ hijos y aun así pertenecer a un grupo de variantes, y el cambio se les
1325
+ puede copiar igual. Si no se miraran, guardar no ofrecería nada.
1326
+ */
1327
+ const companeras = (variantGroup?.members ?? []).filter(
1328
+ (m) => !m.isCurrent
1329
+ );
1330
+
1331
+ if (hijos.length > 0 || companeras.length > 0) {
1322
1332
  setPendingPropagation({ cambios });
1323
1333
  return;
1324
1334
  }
@@ -2083,6 +2093,10 @@ const RetailerProductEditionView = ({
2083
2093
  <PropagateChangesModal
2084
2094
  changedAttributes={pendingPropagation.cambios}
2085
2095
  variants={(family?.variants ?? []).filter((v) => !v.isCurrent)}
2096
+ groupMembers={(variantGroup?.members ?? []).filter(
2097
+ (m) => !m.isCurrent
2098
+ )}
2099
+ groupCode={variantGroup?.group ?? null}
2086
2100
  saving={state.saving}
2087
2101
  onCancel={() => setPendingPropagation(null)}
2088
2102
  onConfirm={(propagation) => {