contentoh-components-library 21.6.35 → 21.6.37

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/index.js CHANGED
@@ -1122,7 +1122,7 @@ Object.keys(_index85).forEach(function (key) {
1122
1122
  });
1123
1123
  });
1124
1124
 
1125
- var _index86 = require("./components/organisms/ProductImageModal/index");
1125
+ var _index86 = require("./components/organisms/UnlinkVariantModal/index");
1126
1126
 
1127
1127
  Object.keys(_index86).forEach(function (key) {
1128
1128
  if (key === "default" || key === "__esModule") return;
@@ -1135,7 +1135,7 @@ Object.keys(_index86).forEach(function (key) {
1135
1135
  });
1136
1136
  });
1137
1137
 
1138
- var _index87 = require("./components/organisms/Chat/index");
1138
+ var _index87 = require("./components/organisms/ProductImageModal/index");
1139
1139
 
1140
1140
  Object.keys(_index87).forEach(function (key) {
1141
1141
  if (key === "default" || key === "__esModule") return;
@@ -1148,7 +1148,7 @@ Object.keys(_index87).forEach(function (key) {
1148
1148
  });
1149
1149
  });
1150
1150
 
1151
- var _index88 = require("./components/organisms/Modal/index");
1151
+ var _index88 = require("./components/organisms/Chat/index");
1152
1152
 
1153
1153
  Object.keys(_index88).forEach(function (key) {
1154
1154
  if (key === "default" || key === "__esModule") return;
@@ -1161,7 +1161,7 @@ Object.keys(_index88).forEach(function (key) {
1161
1161
  });
1162
1162
  });
1163
1163
 
1164
- var _index89 = require("./components/organisms/OrderDetail/index");
1164
+ var _index89 = require("./components/organisms/Modal/index");
1165
1165
 
1166
1166
  Object.keys(_index89).forEach(function (key) {
1167
1167
  if (key === "default" || key === "__esModule") return;
@@ -1174,6 +1174,19 @@ Object.keys(_index89).forEach(function (key) {
1174
1174
  });
1175
1175
  });
1176
1176
 
1177
+ var _index90 = require("./components/organisms/OrderDetail/index");
1178
+
1179
+ Object.keys(_index90).forEach(function (key) {
1180
+ if (key === "default" || key === "__esModule") return;
1181
+ if (key in exports && exports[key] === _index90[key]) return;
1182
+ Object.defineProperty(exports, key, {
1183
+ enumerable: true,
1184
+ get: function get() {
1185
+ return _index90[key];
1186
+ }
1187
+ });
1188
+ });
1189
+
1177
1190
  var _RangeCalendar = require("./components/organisms/RangeCalendar");
1178
1191
 
1179
1192
  Object.keys(_RangeCalendar).forEach(function (key) {
@@ -1200,28 +1213,28 @@ Object.keys(_TableResizable).forEach(function (key) {
1200
1213
  });
1201
1214
  });
1202
1215
 
1203
- var _index90 = require("./components/organisms/SideModal/index");
1216
+ var _index91 = require("./components/organisms/SideModal/index");
1204
1217
 
1205
- Object.keys(_index90).forEach(function (key) {
1218
+ Object.keys(_index91).forEach(function (key) {
1206
1219
  if (key === "default" || key === "__esModule") return;
1207
- if (key in exports && exports[key] === _index90[key]) return;
1220
+ if (key in exports && exports[key] === _index91[key]) return;
1208
1221
  Object.defineProperty(exports, key, {
1209
1222
  enumerable: true,
1210
1223
  get: function get() {
1211
- return _index90[key];
1224
+ return _index91[key];
1212
1225
  }
1213
1226
  });
1214
1227
  });
1215
1228
 
1216
- var _index91 = require("./components/organisms/GridProducts/index");
1229
+ var _index92 = require("./components/organisms/GridProducts/index");
1217
1230
 
1218
- Object.keys(_index91).forEach(function (key) {
1231
+ Object.keys(_index92).forEach(function (key) {
1219
1232
  if (key === "default" || key === "__esModule") return;
1220
- if (key in exports && exports[key] === _index91[key]) return;
1233
+ if (key in exports && exports[key] === _index92[key]) return;
1221
1234
  Object.defineProperty(exports, key, {
1222
1235
  enumerable: true,
1223
1236
  get: function get() {
1224
- return _index91[key];
1237
+ return _index92[key];
1225
1238
  }
1226
1239
  });
1227
1240
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contentoh-components-library",
3
- "version": "21.6.35",
3
+ "version": "21.6.37",
4
4
  "dependencies": {
5
5
  "@aws-amplify/auth": "^4.5.3",
6
6
  "@aws-amplify/datastore": "^3.11.0",
@@ -7,6 +7,10 @@ import { Container } from "./styles";
7
7
  *
8
8
  * El estado "propio" es el que carga información —ese campo se separó del padre—
9
9
  * así que es el que lleva acento y el que ofrece la acción de volver a heredar.
10
+ *
11
+ * OJO: "propio" ya NO significa "a salvo de la propagación". Desde el cambio del
12
+ * 2026-09-01 la propagación sobrescribe también estos valores; el aviso de que va
13
+ * a pasar vive en el diálogo de propagación, no aquí. El tooltip lo dice así.
10
14
  * "Heredado" es el caso normal y se mantiene discreto: si gritara en cada campo,
11
15
  * la ficha entera se volvería ruido.
12
16
  *
@@ -41,14 +45,20 @@ export const InheritanceTag = ({
41
45
  className="tag-label"
42
46
  title={
43
47
  isOverridden
44
- ? "Valor propio de este producto hijo. La propagación del padre no lo modifica."
48
+ ? "Valor capturado en este producto hijo, distinto al del padre. Si el padre propaga este atributo, se reemplaza."
45
49
  : `Valor heredado${parentUpc ? ` del producto ${parentUpc}` : " del producto padre"}.`
46
50
  }
47
51
  >
48
52
  {isOverridden ? "Propio" : "Heredado"}
49
53
  </span>
50
54
 
51
- {isOverridden && onRestore && (
55
+ {/* `Boolean`, no `isOverridden` a secas.
56
+
57
+ `is_overridden` llega como NÚMERO (0/1) desde la API y el reducer. Con
58
+ `{isOverridden && ...}`, un 0 se evalúa a 0 y React IMPRIME el texto
59
+ «0» — ese era el cero que aparecía en el hueco de la acción justo
60
+ después de pulsar «Volver a heredar», que es cuando el valor pasa a 0. */}
61
+ {Boolean(isOverridden) && onRestore && (
52
62
  <button type="button" className="tag-action" onClick={onRestore}>
53
63
  {restoreLabel}
54
64
  </button>
@@ -321,7 +321,9 @@ export const TagAndInput = ({
321
321
  className={"input-container"}
322
322
  key={`generalTagInput-${inputType}`}
323
323
  >
324
- {label?.length && (
324
+ {/* `Boolean`, no `label?.length`: con la etiqueta en cadena vacía la
325
+ expresión valía 0 y React imprimía un «0» en la ficha. */}
326
+ {Boolean(label?.length) && (
325
327
  <div className="title-container">
326
328
  <div className="titles">
327
329
  <ScreenHeader
@@ -46,7 +46,9 @@ export const TagAndInputv2 = ({
46
46
  className={"input-container"}
47
47
  key={`generalTagInput-${inputType}`}
48
48
  >
49
- {label?.length && (
49
+ {/* `Boolean`, no `label?.length`: con la etiqueta en cadena vacía la
50
+ expresión valía 0 y React imprimía un «0» en la ficha. */}
51
+ {Boolean(label?.length) && (
50
52
  <div className="title-container">
51
53
  <ScreenHeaderv2
52
54
  text={label}
@@ -21,7 +21,10 @@ import {
21
21
 
22
22
  props (* requerido):
23
23
  - *changedAttributes: [{ id, name, value }] lo que se acaba de editar
24
- - *variants: [{ articleId, name, upc }] los hijos activos del padre
24
+ - *variants: [{ articleId, name, upc, overriddenAttributes }] los hijos
25
+ activos del padre. `overriddenAttributes` son los atributos que ese hijo
26
+ capturó a mano; la propagación los sobrescribe, y este diálogo es el
27
+ único lugar donde el usuario puede enterarse antes de que pase.
25
28
  - *onCancel: cerrar sin guardar nada
26
29
  - *onConfirm: (propagation | null) => void
27
30
  null → guardar solo el padre
@@ -49,6 +52,31 @@ export const PropagateChangesModal = ({
49
52
  const puedePropagar = chosenAttributes.length > 0 && destinatarios > 0;
50
53
  const enSegundoPlano = destinatarios > UMBRAL_SEGUNDO_PLANO;
51
54
 
55
+ /*
56
+ A quién se le va a pisar un valor capturado a mano.
57
+
58
+ La propagación sobrescribe: eso se decidió a propósito, porque el usuario ya
59
+ eligió atributo por atributo y hijo por hijo. Pero sobrescribir en silencio
60
+ es otra cosa, y desde que se quitaron las etiquetas de «Heredado» y «Propio»
61
+ este diálogo es el único momento en que alguien puede saberlo.
62
+
63
+ Se recalcula con lo que está marcado ahora, no al abrir: si el usuario
64
+ desmarca el atributo conflictivo, el aviso desaparece — que es justo la
65
+ salida que el aviso debería estar ofreciendo.
66
+ */
67
+ const destinos = scope === "all"
68
+ ? variants
69
+ : variants.filter((item) => chosenChildren.includes(item.articleId));
70
+
71
+ const conValorPropio = destinos
72
+ .map((hijo) => ({
73
+ ...hijo,
74
+ pisados: (hijo.overriddenAttributes ?? []).filter((id) =>
75
+ chosenAttributes.includes(Number(id))
76
+ ),
77
+ }))
78
+ .filter((hijo) => hijo.pisados.length > 0);
79
+
52
80
  const toggleAttribute = (id) => {
53
81
  setChosenAttributes((current) =>
54
82
  current.includes(id)
@@ -155,13 +183,20 @@ export const PropagateChangesModal = ({
155
183
  </List>
156
184
  )}
157
185
 
158
- {/* La diferencia con "ligar", y la que sorprende si no se dice: aquí
159
- lo que el hijo editó a mano NO se pisa. */}
160
- <Note>
161
- Un hijo que haya editado alguno de estos atributos por su cuenta
162
- conserva su valor. Para devolverlo al del padre está la acción
163
- «Volver a heredar» en la ficha de ese hijo.
164
- </Note>
186
+ {/* Lo que sorprende si no se dice: aquí se pisa lo que el hijo
187
+ hubiera capturado a mano. Se nombra a quién, no solo cuántos: con
188
+ «2 hijos» nadie sabe si le importa, con los nombres sí. */}
189
+ {conValorPropio.length > 0 && (
190
+ <Note className="accent">
191
+ {conValorPropio.length === 1
192
+ ? "Un hijo tiene un valor propio en lo que elegiste y se va a reemplazar: "
193
+ : `${conValorPropio.length} hijos tienen valores propios en lo que elegiste y se van a reemplazar: `}
194
+ {conValorPropio
195
+ .map((hijo) => `${hijo.name || `Producto ${hijo.articleId}`} (${hijo.pisados.length})`)
196
+ .join(", ")}
197
+ . Si no quieres pisarlos, desmarca ese atributo o ese hijo.
198
+ </Note>
199
+ )}
165
200
 
166
201
  {enSegundoPlano && (
167
202
  <Note className="accent">
@@ -0,0 +1,141 @@
1
+ import { useState } from "react";
2
+ import axios from "axios";
3
+
4
+ import { readPayload, ApiError } from "../LinkVariantsModal/api";
5
+ import { Overlay, Panel, Header, Body, Message, Footer } from "./styles";
6
+
7
+ /*
8
+ Confirmación para romper un vínculo padre/hijo.
9
+
10
+ El servidor ya sabía hacerlo desde el principio —POST /variants/unlink—, pero
11
+ no había forma de pedirlo desde ninguna pantalla: la única manera de deshacer
12
+ una liga era DESACTIVAR al padre, que suelta a todos los hijos de golpe y no
13
+ se puede revertir. Esto es la versión de a uno.
14
+
15
+ La acción se pide siempre con el id del HIJO, que es quien tiene el vínculo en
16
+ `article.parent_article_id`. Por eso las dos direcciones —un hijo que se suelta
17
+ y un padre que suelta a un hijo— son la misma llamada; lo único que cambia es
18
+ el texto, porque no es lo mismo lo que el usuario cree estar haciendo.
19
+
20
+ props (* requerido):
21
+ - *childArticleId: el hijo que pierde el vínculo
22
+ - childName / childUpc: para nombrarlo en el diálogo
23
+ - parentName / parentUpc: de quién se desprende
24
+ - mode: "self" (esta ficha deja de ser hija) | "child" (esta ficha suelta a un hijo)
25
+ - *token, endpoint
26
+ - *onClose, onUnlinked
27
+ */
28
+ export const UnlinkVariantModal = ({
29
+ childArticleId,
30
+ childName,
31
+ childUpc,
32
+ parentName,
33
+ parentUpc,
34
+ mode = "self",
35
+ token,
36
+ endpoint = process.env.REACT_APP_VARIANTS_ENDPOINT,
37
+ onClose,
38
+ onUnlinked,
39
+ }) => {
40
+ const [loading, setLoading] = useState(false);
41
+ const [error, setError] = useState(null);
42
+
43
+ const nombreHijo = childName || `Producto ${childArticleId}`;
44
+ const nombrePadre = parentName || "el producto padre";
45
+
46
+ const submit = async () => {
47
+ setLoading(true);
48
+ setError(null);
49
+ try {
50
+ const res = await axios.post(
51
+ `${endpoint}/unlink`,
52
+ { articleIds: [childArticleId] },
53
+ { headers: { Authorization: token } }
54
+ );
55
+
56
+ const data = readPayload(res);
57
+ onUnlinked?.({ ...data, mode, childArticleId });
58
+ onClose?.();
59
+ } catch (err) {
60
+ // El transporte siempre responde 200; el error de negocio viaja dentro.
61
+ setError(
62
+ err instanceof ApiError || err?.name === "ApiError"
63
+ ? err.message
64
+ : "No se pudo desvincular. Intenta de nuevo."
65
+ );
66
+ setLoading(false);
67
+ }
68
+ };
69
+
70
+ return (
71
+ <Overlay onClick={loading ? undefined : onClose}>
72
+ <Panel onClick={(event) => event.stopPropagation()}>
73
+ <Header>
74
+ <h2>
75
+ {mode === "self"
76
+ ? "Dejar de ser hijo de otro producto"
77
+ : "Desvincular este hijo"}
78
+ </h2>
79
+ <p>
80
+ {mode === "self" ? (
81
+ <>
82
+ «{nombreHijo}» dejará de colgar de «{nombrePadre}»
83
+ {parentUpc ? ` (UPC ${parentUpc})` : ""}.
84
+ </>
85
+ ) : (
86
+ <>
87
+ «{nombreHijo}»{childUpc ? ` (UPC ${childUpc})` : ""} dejará de
88
+ colgar de este producto.
89
+ </>
90
+ )}
91
+ </p>
92
+ </Header>
93
+
94
+ <Body>
95
+ <ul>
96
+ {/* Lo primero que la gente teme, y no pasa. */}
97
+ <li>
98
+ <strong>No se borra nada.</strong> Todo lo que heredó —atributos,
99
+ descripciones, imágenes y cadenas— se queda como información
100
+ propia del producto.
101
+ </li>
102
+ <li>
103
+ Desaparecen las marcas de «Heredado» y «Propio»: sin padre dejan de
104
+ querer decir algo.
105
+ </li>
106
+ <li>
107
+ Deja de recibir la propagación
108
+ {mode === "self" ? " de su padre" : " de este producto"}: lo que se
109
+ edite de un lado ya no baja al otro.
110
+ </li>
111
+ <li className="aviso">
112
+ Volver a ligarlos es a mano, y hay que elegir otra vez qué hereda.
113
+ Desvincular no se deshace solo.
114
+ </li>
115
+ </ul>
116
+ </Body>
117
+
118
+ {error && <Message>{error}</Message>}
119
+
120
+ <Footer>
121
+ <button
122
+ type="button"
123
+ className="secondary"
124
+ onClick={onClose}
125
+ disabled={loading}
126
+ >
127
+ Cancelar
128
+ </button>
129
+ <button
130
+ type="button"
131
+ className="primary"
132
+ onClick={submit}
133
+ disabled={loading}
134
+ >
135
+ {loading ? "Desvinculando…" : "Desvincular"}
136
+ </button>
137
+ </Footer>
138
+ </Panel>
139
+ </Overlay>
140
+ );
141
+ };
@@ -0,0 +1,106 @@
1
+ import styled from "styled-components";
2
+
3
+ import { GlobalColors, FontFamily } from "../../../global-files/variables";
4
+
5
+ const PINK = "#E13AA8";
6
+
7
+ export const Overlay = styled.div`
8
+ position: fixed;
9
+ inset: 0;
10
+ z-index: 1000;
11
+ display: flex;
12
+ align-items: center;
13
+ justify-content: center;
14
+ background-color: rgba(40, 31, 51, 0.4);
15
+ `;
16
+
17
+ export const Panel = styled.div`
18
+ width: min(460px, 92vw);
19
+ border-radius: 10px;
20
+ background-color: ${GlobalColors.white};
21
+ font-family: ${FontFamily.Raleway};
22
+ overflow: hidden;
23
+ `;
24
+
25
+ export const Header = styled.div`
26
+ padding: 18px 22px 10px;
27
+
28
+ h2 {
29
+ margin: 0;
30
+ font-family: ${FontFamily.Raleway_600};
31
+ font-size: 16px;
32
+ color: ${GlobalColors.deep_gray};
33
+ }
34
+
35
+ p {
36
+ margin: 6px 0 0;
37
+ font-size: 13px;
38
+ line-height: 1.4;
39
+ color: ${GlobalColors.gray};
40
+ }
41
+ `;
42
+
43
+ export const Body = styled.div`
44
+ padding: 4px 22px 8px;
45
+
46
+ ul {
47
+ margin: 0;
48
+ padding-left: 18px;
49
+ }
50
+
51
+ li {
52
+ margin-bottom: 6px;
53
+ font-size: 13px;
54
+ line-height: 1.4;
55
+ color: ${GlobalColors.deep_gray};
56
+ }
57
+
58
+ /* Lo único que no se puede deshacer solo va marcado: el resto son
59
+ consecuencias, esta es una advertencia. */
60
+ li.aviso {
61
+ color: ${PINK};
62
+ }
63
+ `;
64
+
65
+ export const Message = styled.p`
66
+ margin: 8px 22px 0;
67
+ padding: 10px 12px;
68
+ border-radius: 6px;
69
+ background-color: rgba(225, 58, 168, 0.1);
70
+ font-size: 13px;
71
+ line-height: 1.4;
72
+ color: ${PINK};
73
+ `;
74
+
75
+ export const Footer = styled.div`
76
+ display: flex;
77
+ justify-content: flex-end;
78
+ gap: 10px;
79
+ padding: 16px 22px 20px;
80
+
81
+ button {
82
+ height: 38px;
83
+ padding: 0 16px;
84
+ border-radius: 6px;
85
+ cursor: pointer;
86
+ font-family: ${FontFamily.Raleway_600};
87
+ font-size: 13px;
88
+ }
89
+
90
+ button:disabled {
91
+ opacity: 0.5;
92
+ cursor: default;
93
+ }
94
+
95
+ .secondary {
96
+ border: 1px solid ${GlobalColors.s2};
97
+ background: none;
98
+ color: ${GlobalColors.deep_gray};
99
+ }
100
+
101
+ .primary {
102
+ border: 1px solid ${PINK};
103
+ background-color: ${PINK};
104
+ color: ${GlobalColors.white};
105
+ }
106
+ `;