contentoh-components-library 21.6.34 → 21.6.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/organisms/UnlinkVariantModal/index.js +178 -0
- package/dist/components/organisms/UnlinkVariantModal/styles.js +42 -0
- package/dist/components/pages/ProviderProductEdition/index.js +186 -59
- package/dist/components/pages/ProviderProductEdition/styles.js +2 -2
- package/dist/components/pages/RetailerProductEdition/index.js +468 -220
- package/dist/components/pages/RetailerProductEdition/styles.js +2 -2
- package/dist/components/pages/RetailerProductEdition/utils.js +8 -3
- package/dist/index.js +25 -12
- package/package.json +1 -1
- package/src/components/organisms/UnlinkVariantModal/index.js +141 -0
- package/src/components/organisms/UnlinkVariantModal/styles.js +106 -0
- package/src/components/pages/ProviderProductEdition/index.js +166 -37
- package/src/components/pages/ProviderProductEdition/styles.js +30 -0
- package/src/components/pages/RetailerProductEdition/index.js +251 -25
- package/src/components/pages/RetailerProductEdition/styles.js +41 -0
- package/src/components/pages/RetailerProductEdition/utils.js +10 -3
- package/src/index.js +1 -0
- package/.claude/launch.json +0 -15
- package/dist/ai/prompts/attribute.prompt.js +0 -28
- package/dist/ai/prompts/description.prompt.js +0 -33
- package/dist/ai/schemas/attribute.schema.js +0 -35
- package/dist/ai/schemas/description.schema.js +0 -27
|
@@ -208,6 +208,36 @@ export const Container = styled.div`
|
|
|
208
208
|
color: ${GlobalColors.gray};
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
/* La fila es un botón que navega; desvincular tiene que quedar FUERA de
|
|
212
|
+
él —un botón dentro de otro no es HTML válido y el clic se confunde—. */
|
|
213
|
+
.family-item {
|
|
214
|
+
display: flex;
|
|
215
|
+
align-items: center;
|
|
216
|
+
gap: 4px;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.family-item .family-row {
|
|
220
|
+
flex: 1;
|
|
221
|
+
min-width: 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.desvincular {
|
|
225
|
+
flex-shrink: 0;
|
|
226
|
+
border: none;
|
|
227
|
+
background: none;
|
|
228
|
+
padding: 4px 6px;
|
|
229
|
+
cursor: pointer;
|
|
230
|
+
font-family: ${FontFamily.Raleway_500};
|
|
231
|
+
font-size: 10px;
|
|
232
|
+
color: ${GlobalColors.gray};
|
|
233
|
+
text-decoration: underline;
|
|
234
|
+
white-space: nowrap;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.desvincular:hover {
|
|
238
|
+
color: ${PINK};
|
|
239
|
+
}
|
|
240
|
+
|
|
211
241
|
.family-row {
|
|
212
242
|
display: flex;
|
|
213
243
|
align-items: baseline;
|
|
@@ -51,6 +51,7 @@ import { ProductImageModal } from "../../organisms/ProductImageModal";
|
|
|
51
51
|
import { VersionSelector } from "../../organisms/VersionSelector";
|
|
52
52
|
import { Modal } from "../../organisms/Modal";
|
|
53
53
|
import { LinkVariantsModal } from "../../organisms/LinkVariantsModal";
|
|
54
|
+
import { UnlinkVariantModal } from "../../organisms/UnlinkVariantModal";
|
|
54
55
|
import { PropagateChangesModal } from "../../organisms/PropagateChangesModal";
|
|
55
56
|
import { readPayload } from "../../organisms/LinkVariantsModal/api";
|
|
56
57
|
|
|
@@ -185,6 +186,13 @@ const RetailerProductEditionView = ({
|
|
|
185
186
|
const [showLinkVariants, setShowLinkVariants] = useState(false);
|
|
186
187
|
const [family, setFamily] = useState(null);
|
|
187
188
|
const [showFamily, setShowFamily] = useState(false);
|
|
189
|
+
const [loadingVariant, setLoadingVariant] = useState(null);
|
|
190
|
+
// Qué vínculo se está por romper, o null si no hay diálogo abierto. Guarda al
|
|
191
|
+
// HIJO, que es quien lleva la relación y lo que pide la acción `unlink`.
|
|
192
|
+
const [porDesvincular, setPorDesvincular] = useState(null);
|
|
193
|
+
// Por qué un salto no se pudo hacer. Vive aparte de `family.error` porque no
|
|
194
|
+
// es un fallo al leer la familia, sino al abrir uno de sus miembros.
|
|
195
|
+
const [avisoFamilia, setAvisoFamilia] = useState(null);
|
|
188
196
|
const [pendingPropagation, setPendingPropagation] = useState(null);
|
|
189
197
|
const [preparandoPropagacion, setPreparandoPropagacion] = useState(false);
|
|
190
198
|
|
|
@@ -833,20 +841,136 @@ const RetailerProductEditionView = ({
|
|
|
833
841
|
: !!family?.parent;
|
|
834
842
|
|
|
835
843
|
/*
|
|
836
|
-
|
|
844
|
+
Abre otro producto de la familia.
|
|
845
|
+
|
|
846
|
+
Cambiar la URL no basta: esta pantalla no lee el producto de la ruta sino de
|
|
847
|
+
sessionStorage —el router hace JSON.parse(sessionStorage.productSelected) y
|
|
848
|
+
se lo pasa como prop—, así que navegar sin precargar dejaría la URL nueva
|
|
849
|
+
mostrando el producto anterior. Por eso primero se trae el destino y se
|
|
850
|
+
escriben las tres llaves que el listado escribe al hacer clic en una fila
|
|
851
|
+
(productSelected, version, productEdit), y solo entonces se navega.
|
|
852
|
+
|
|
853
|
+
Se pide a /ordered-services y no a read-articles-v2, que es lo que usa la
|
|
854
|
+
aplicación de clientes: aquel filtra por la compañía del usuario y el equipo
|
|
855
|
+
interno es de ContentOh trabajando productos de sus clientes, así que ahí no
|
|
856
|
+
devolvería nada. /ordered-services es el mismo endpoint del listado de esta
|
|
857
|
+
aplicación, así que el objeto llega con la forma exacta que normalizeProduct
|
|
858
|
+
espera —con `article` anidado, `statusByRetailer` y `categoryRetailer`—.
|
|
859
|
+
|
|
860
|
+
Un producto de la familia puede no estar en ninguna orden de trabajo: la
|
|
861
|
+
relación padre/hijo vive en `article` y no exige haber pasado por ContentOh.
|
|
862
|
+
En ese caso no hay nada que abrir aquí, y se dice en vez de navegar a una
|
|
863
|
+
pantalla que mostraría el producto equivocado.
|
|
864
|
+
*/
|
|
865
|
+
/*
|
|
866
|
+
Después de desvincular, esta ficha cambia de forma: si se soltó de su padre
|
|
867
|
+
vuelve a poder ligar, y si soltó a un hijo pierde uno de la cuenta. En esta
|
|
868
|
+
pantalla el bloque de parentesco se decide con `family`, así que hay que
|
|
869
|
+
repreguntarla —vaciarla lo haría desaparecer, que es el error que ya se
|
|
870
|
+
cometió una vez aquí—.
|
|
871
|
+
*/
|
|
872
|
+
const handleOnUnlinked = (result) => {
|
|
873
|
+
if (!result) return;
|
|
837
874
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
875
|
+
const updatedProduct =
|
|
876
|
+
result.mode === "self"
|
|
877
|
+
? { ...state.product, parentArticleId: null, variantsCount: 0 }
|
|
878
|
+
: {
|
|
879
|
+
...state.product,
|
|
880
|
+
variantsCount: Math.max((state.product?.variantsCount ?? 1) - 1, 0),
|
|
881
|
+
};
|
|
842
882
|
|
|
843
|
-
|
|
844
|
-
producto de sessionStorage, así que cambiaría la URL y seguiría mostrando el
|
|
845
|
-
producto anterior, dando a entender que se cambió de producto cuando no.
|
|
883
|
+
dispatch({ type: "SET_PRODUCT", payload: updatedProduct });
|
|
846
884
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
885
|
+
// Se PARCHEA lo guardado: ahí vive el producto con la forma del listado
|
|
886
|
+
// —`article` anidado, servicios, cadenas— y escribir encima la versión
|
|
887
|
+
// aplanada de esta pantalla lo dejaría mutilado en el siguiente F5.
|
|
888
|
+
try {
|
|
889
|
+
const guardado = JSON.parse(
|
|
890
|
+
sessionStorage.getItem("productSelected") ?? "null"
|
|
891
|
+
);
|
|
892
|
+
|
|
893
|
+
if (guardado) {
|
|
894
|
+
sessionStorage.setItem(
|
|
895
|
+
"productSelected",
|
|
896
|
+
JSON.stringify({
|
|
897
|
+
...guardado,
|
|
898
|
+
variantsCount: updatedProduct.variantsCount,
|
|
899
|
+
parentArticleId: updatedProduct.parentArticleId ?? null,
|
|
900
|
+
})
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
} catch (error) {
|
|
904
|
+
console.error("unlinkVariant/sessionStorage: ", error);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/*
|
|
908
|
+
Si ya no queda familia, se cierra el desplegable: su botón desaparece con
|
|
909
|
+
el vínculo, y dejarlo abierto pinta una caja que dice «no tiene hijos» y
|
|
910
|
+
que nadie puede cerrar.
|
|
911
|
+
*/
|
|
912
|
+
if (
|
|
913
|
+
!updatedProduct.parentArticleId &&
|
|
914
|
+
(updatedProduct.variantsCount ?? 0) === 0
|
|
915
|
+
) {
|
|
916
|
+
setShowFamily(false);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
loadFamily(true);
|
|
920
|
+
|
|
921
|
+
// Al desvincular el servidor pone `is_overridden = 0` en todas las
|
|
922
|
+
// versiones, así que los chips de herencia tienen que dejar de dibujarse.
|
|
923
|
+
// Sin `enableLoading` para no parpadear el esqueleto encima de una pantalla
|
|
924
|
+
// que ya está pintada.
|
|
925
|
+
loadData(false);
|
|
926
|
+
};
|
|
927
|
+
|
|
928
|
+
const openFamilyMember = async (articleId) => {
|
|
929
|
+
setLoadingVariant(articleId);
|
|
930
|
+
setAvisoFamilia(null);
|
|
931
|
+
try {
|
|
932
|
+
const res = await axios.get(
|
|
933
|
+
`${process.env.REACT_APP_ORDERED_SERVICES_ENDPOINT}`,
|
|
934
|
+
{
|
|
935
|
+
params: { filterByIdArticle: articleId, includeFilters: false },
|
|
936
|
+
headers: { Authorization: token },
|
|
937
|
+
}
|
|
938
|
+
);
|
|
939
|
+
|
|
940
|
+
// read-order-services responde { total, data: [...] }. La vista trae una
|
|
941
|
+
// fila por orden, así que puede haber varias del mismo artículo; llegan
|
|
942
|
+
// ordenadas por order_id DESC y la primera es la orden más reciente.
|
|
943
|
+
const { data } = readPayload(res) ?? {};
|
|
944
|
+
const encontrado = (data ?? []).find(
|
|
945
|
+
(item) => Number(item?.article?.id_article) === Number(articleId)
|
|
946
|
+
);
|
|
947
|
+
|
|
948
|
+
if (!encontrado) {
|
|
949
|
+
setAvisoFamilia(
|
|
950
|
+
"Ese producto no está en ninguna orden de trabajo, así que no se puede abrir desde aquí."
|
|
951
|
+
);
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
sessionStorage.setItem("productSelected", JSON.stringify(encontrado));
|
|
956
|
+
sessionStorage.setItem("version", JSON.stringify(encontrado.version));
|
|
957
|
+
sessionStorage.setItem(
|
|
958
|
+
"productEdit",
|
|
959
|
+
JSON.stringify({
|
|
960
|
+
ArticleId: encontrado.article.id_article,
|
|
961
|
+
categoryId: encontrado.article.id_article,
|
|
962
|
+
product: [encontrado],
|
|
963
|
+
})
|
|
964
|
+
);
|
|
965
|
+
|
|
966
|
+
window.location.assign("/EditProducts");
|
|
967
|
+
} catch (error) {
|
|
968
|
+
console.error("openFamilyMember: ", error);
|
|
969
|
+
setAvisoFamilia("No se pudo abrir ese producto. Intenta de nuevo.");
|
|
970
|
+
} finally {
|
|
971
|
+
setLoadingVariant(null);
|
|
972
|
+
}
|
|
973
|
+
};
|
|
850
974
|
|
|
851
975
|
/*
|
|
852
976
|
Refresca tras ligar, sin recargar la página: el producto sale de
|
|
@@ -871,9 +995,36 @@ const RetailerProductEditionView = ({
|
|
|
871
995
|
|
|
872
996
|
dispatch({ type: "SET_PRODUCT", payload: updatedProduct });
|
|
873
997
|
|
|
998
|
+
/*
|
|
999
|
+
En sessionStorage se PARCHEA lo guardado; no se reemplaza.
|
|
1000
|
+
|
|
1001
|
+
Lo que hay ahí es el producto tal como lo devuelve el listado de esta
|
|
1002
|
+
aplicación: con `article` anidado, `statusByRetailer`, `categoryRetailer`
|
|
1003
|
+
y los servicios. `updatedProduct` es la versión aplanada que usa esta
|
|
1004
|
+
pantalla, y escribirla encima tiraba todo eso: al siguiente F5 la ficha se
|
|
1005
|
+
reconstruía desde un objeto mutilado —sin relaciones de cadena, sin
|
|
1006
|
+
estatus por cadena— aunque en pantalla se viera bien hasta entonces.
|
|
1007
|
+
|
|
1008
|
+
De ligar solo cambian dos cosas, y son las dos que se copian aquí.
|
|
1009
|
+
*/
|
|
874
1010
|
try {
|
|
875
|
-
|
|
1011
|
+
const guardado = JSON.parse(
|
|
1012
|
+
sessionStorage.getItem("productSelected") ?? "null"
|
|
1013
|
+
);
|
|
1014
|
+
|
|
1015
|
+
if (guardado) {
|
|
1016
|
+
sessionStorage.setItem(
|
|
1017
|
+
"productSelected",
|
|
1018
|
+
JSON.stringify({
|
|
1019
|
+
...guardado,
|
|
1020
|
+
variantsCount: updatedProduct.variantsCount,
|
|
1021
|
+
parentArticleId: updatedProduct.parentArticleId ?? null,
|
|
1022
|
+
})
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
876
1025
|
} catch (error) {
|
|
1026
|
+
// Un sessionStorage inaccesible no debe tumbar la pantalla: el estado en
|
|
1027
|
+
// memoria ya quedó bien y es lo que el usuario está viendo.
|
|
877
1028
|
console.error("linkVariants/sessionStorage: ", error);
|
|
878
1029
|
}
|
|
879
1030
|
|
|
@@ -1773,6 +1924,14 @@ const RetailerProductEditionView = ({
|
|
|
1773
1924
|
onLinked={handleOnLinkedVariants}
|
|
1774
1925
|
/>
|
|
1775
1926
|
)}
|
|
1927
|
+
{porDesvincular && (
|
|
1928
|
+
<UnlinkVariantModal
|
|
1929
|
+
{...porDesvincular}
|
|
1930
|
+
token={token}
|
|
1931
|
+
onClose={() => setPorDesvincular(null)}
|
|
1932
|
+
onUnlinked={handleOnUnlinked}
|
|
1933
|
+
/>
|
|
1934
|
+
)}
|
|
1776
1935
|
{showRejectModal && (
|
|
1777
1936
|
<Modal
|
|
1778
1937
|
title={
|
|
@@ -2033,30 +2192,97 @@ const RetailerProductEditionView = ({
|
|
|
2033
2192
|
</p>
|
|
2034
2193
|
)}
|
|
2035
2194
|
|
|
2195
|
+
{/* Desvincular se ofrece donde se ve el vínculo, y solo en la
|
|
2196
|
+
dirección que corresponde a esta ficha: desde un hijo, sobre
|
|
2197
|
+
su padre; desde un padre, sobre cada hijo. A un hermano no:
|
|
2198
|
+
para eso se abre su ficha. */}
|
|
2036
2199
|
{family?.parent && (
|
|
2037
|
-
<div className="family-
|
|
2038
|
-
<
|
|
2039
|
-
|
|
2040
|
-
|
|
2200
|
+
<div className="family-item">
|
|
2201
|
+
<button
|
|
2202
|
+
type="button"
|
|
2203
|
+
className="family-row parent"
|
|
2204
|
+
disabled={loadingVariant !== null}
|
|
2205
|
+
onClick={() => openFamilyMember(family.parent.articleId)}
|
|
2206
|
+
>
|
|
2207
|
+
<span className="role">
|
|
2208
|
+
{loadingVariant === family.parent.articleId
|
|
2209
|
+
? "Abriendo…"
|
|
2210
|
+
: "Producto padre"}
|
|
2211
|
+
</span>
|
|
2212
|
+
<span className="name">{family.parent.name}</span>
|
|
2213
|
+
<span className="upc">{family.parent.upc}</span>
|
|
2214
|
+
</button>
|
|
2215
|
+
|
|
2216
|
+
<button
|
|
2217
|
+
type="button"
|
|
2218
|
+
className="desvincular"
|
|
2219
|
+
title="Dejar de ser hijo de este producto"
|
|
2220
|
+
onClick={() =>
|
|
2221
|
+
setPorDesvincular({
|
|
2222
|
+
mode: "self",
|
|
2223
|
+
childArticleId: state.product?.id_article,
|
|
2224
|
+
childName: state.product?.name,
|
|
2225
|
+
childUpc: state.product?.upc,
|
|
2226
|
+
parentName: family.parent.name,
|
|
2227
|
+
parentUpc: family.parent.upc,
|
|
2228
|
+
})
|
|
2229
|
+
}
|
|
2230
|
+
>
|
|
2231
|
+
Desvincular
|
|
2232
|
+
</button>
|
|
2041
2233
|
</div>
|
|
2042
2234
|
)}
|
|
2043
2235
|
|
|
2044
2236
|
{family?.variants?.map((variant) => (
|
|
2045
|
-
<div
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2237
|
+
<div className="family-item" key={variant.articleId}>
|
|
2238
|
+
<button
|
|
2239
|
+
type="button"
|
|
2240
|
+
className={`family-row${
|
|
2241
|
+
variant.isCurrent ? " current" : ""
|
|
2242
|
+
}`}
|
|
2243
|
+
disabled={variant.isCurrent || loadingVariant !== null}
|
|
2244
|
+
onClick={() => openFamilyMember(variant.articleId)}
|
|
2245
|
+
>
|
|
2246
|
+
<span className="role">
|
|
2247
|
+
{loadingVariant === variant.articleId
|
|
2248
|
+
? "Abriendo…"
|
|
2249
|
+
: variant.isCurrent
|
|
2250
|
+
? "Estás aquí"
|
|
2251
|
+
: "Hijo"}
|
|
2252
|
+
</span>
|
|
2253
|
+
<span className="name">{variant.name}</span>
|
|
2254
|
+
<span className="upc">{variant.upc}</span>
|
|
2255
|
+
</button>
|
|
2256
|
+
|
|
2257
|
+
{/* Solo cuando esta ficha ES el padre: si hay `parent`, lo
|
|
2258
|
+
que se lista son hermanos. */}
|
|
2259
|
+
{!family.parent && !variant.isCurrent && (
|
|
2260
|
+
<button
|
|
2261
|
+
type="button"
|
|
2262
|
+
className="desvincular"
|
|
2263
|
+
title="Desvincular este hijo"
|
|
2264
|
+
onClick={() =>
|
|
2265
|
+
setPorDesvincular({
|
|
2266
|
+
mode: "child",
|
|
2267
|
+
childArticleId: variant.articleId,
|
|
2268
|
+
childName: variant.name,
|
|
2269
|
+
childUpc: variant.upc,
|
|
2270
|
+
parentName: state.product?.name,
|
|
2271
|
+
parentUpc: state.product?.upc,
|
|
2272
|
+
})
|
|
2273
|
+
}
|
|
2274
|
+
>
|
|
2275
|
+
Desvincular
|
|
2276
|
+
</button>
|
|
2277
|
+
)}
|
|
2054
2278
|
</div>
|
|
2055
2279
|
))}
|
|
2056
2280
|
|
|
2057
2281
|
{family && !family.error && !family.variants?.length && (
|
|
2058
2282
|
<p className="loading">Este producto no tiene hijos.</p>
|
|
2059
2283
|
)}
|
|
2284
|
+
|
|
2285
|
+
{avisoFamilia && <p className="loading">{avisoFamilia}</p>}
|
|
2060
2286
|
</div>
|
|
2061
2287
|
)}
|
|
2062
2288
|
|
|
@@ -215,18 +215,59 @@ export const Container = styled.div`
|
|
|
215
215
|
color: ${GlobalColors.gray};
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
/* La fila es un botón que navega; desvincular tiene que quedar FUERA de
|
|
219
|
+
él —un botón dentro de otro no es HTML válido y el clic se confunde—. */
|
|
220
|
+
.family-item {
|
|
221
|
+
display: flex;
|
|
222
|
+
align-items: center;
|
|
223
|
+
gap: 4px;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.family-item .family-row {
|
|
227
|
+
flex: 1;
|
|
228
|
+
min-width: 0;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.desvincular {
|
|
232
|
+
flex-shrink: 0;
|
|
233
|
+
border: none;
|
|
234
|
+
background: none;
|
|
235
|
+
padding: 4px 6px;
|
|
236
|
+
cursor: pointer;
|
|
237
|
+
font-family: ${FontFamily.Raleway_500};
|
|
238
|
+
font-size: 10px;
|
|
239
|
+
color: ${GlobalColors.gray};
|
|
240
|
+
text-decoration: underline;
|
|
241
|
+
white-space: nowrap;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.desvincular:hover {
|
|
245
|
+
color: ${PINK};
|
|
246
|
+
}
|
|
247
|
+
|
|
218
248
|
.family-row {
|
|
219
249
|
display: flex;
|
|
220
250
|
align-items: baseline;
|
|
221
251
|
gap: 8px;
|
|
222
252
|
padding: 6px 8px;
|
|
253
|
+
border: none;
|
|
223
254
|
border-radius: 4px;
|
|
255
|
+
background: none;
|
|
256
|
+
cursor: pointer;
|
|
224
257
|
text-align: left;
|
|
225
258
|
font-family: ${FontFamily.Raleway_500};
|
|
226
259
|
font-size: 12px;
|
|
227
260
|
color: ${GlobalColors.deep_gray};
|
|
228
261
|
}
|
|
229
262
|
|
|
263
|
+
.family-row:hover:not(:disabled) {
|
|
264
|
+
background-color: ${GlobalColors.s2};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.family-row:disabled {
|
|
268
|
+
cursor: default;
|
|
269
|
+
opacity: 0.7;
|
|
270
|
+
}
|
|
230
271
|
|
|
231
272
|
.family-row .role {
|
|
232
273
|
min-width: 96px;
|
|
@@ -96,9 +96,16 @@ export const normalizeProduct = (product) => {
|
|
|
96
96
|
? productData.statusByRetailer.map((status) => status.retailer_id)
|
|
97
97
|
: [];
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
// Un producto sin ninguna relación de cadena+categoría activa llega con
|
|
100
|
+
// `categoryRetailer` en null, y filtrar sobre null tumbaba la pantalla entera.
|
|
101
|
+
// Se vuelve alcanzable al saltar entre productos de una familia, que es cuando
|
|
102
|
+
// se abren fichas que nadie eligió desde el listado. Se conserva el null para
|
|
103
|
+
// no cambiar lo que ya leen los consumidores.
|
|
104
|
+
const categoryRetailerInOrder = categoryRetailerNormalized
|
|
105
|
+
? categoryRetailerNormalized.filter((rel) =>
|
|
106
|
+
retailersIdsInOrder.includes(rel.id_retailer)
|
|
107
|
+
)
|
|
108
|
+
: null;
|
|
102
109
|
|
|
103
110
|
return {
|
|
104
111
|
id_article: productData.id_article || article.id_article || 0,
|
package/src/index.js
CHANGED
|
@@ -89,6 +89,7 @@ export * from "./components/organisms/ImagesGroup/index";
|
|
|
89
89
|
export * from "./components/organisms/InputGroup/index";
|
|
90
90
|
export * from "./components/organisms/LinkVariantsModal/index";
|
|
91
91
|
export * from "./components/organisms/PropagateChangesModal/index";
|
|
92
|
+
export * from "./components/organisms/UnlinkVariantModal/index";
|
|
92
93
|
export * from "./components/organisms/ProductImageModal/index";
|
|
93
94
|
export * from "./components/organisms/Chat/index";
|
|
94
95
|
export * from "./components/organisms/Modal/index";
|
package/.claude/launch.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "0.0.1",
|
|
3
|
-
"configurations": [
|
|
4
|
-
{
|
|
5
|
-
"name": "creators",
|
|
6
|
-
"runtimeExecutable": "sh",
|
|
7
|
-
"runtimeArgs": [
|
|
8
|
-
"-c",
|
|
9
|
-
"cd /Users/macbook/contentoh/content-creation-frontend && export PATH=/Users/macbook/.nvm/versions/node/v16.20.2/bin:$PATH && exec npm start"
|
|
10
|
-
],
|
|
11
|
-
"port": 3000,
|
|
12
|
-
"autoPort": false
|
|
13
|
-
}
|
|
14
|
-
]
|
|
15
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.generateAttributePrompt = void 0;
|
|
7
|
-
|
|
8
|
-
var generateAttributePrompt = function generateAttributePrompt(_ref) {
|
|
9
|
-
var _ref$upc = _ref.upc,
|
|
10
|
-
upc = _ref$upc === void 0 ? 0 : _ref$upc,
|
|
11
|
-
_ref$inputName = _ref.inputName,
|
|
12
|
-
inputName = _ref$inputName === void 0 ? "" : _ref$inputName,
|
|
13
|
-
_ref$description = _ref.description,
|
|
14
|
-
description = _ref$description === void 0 ? "" : _ref$description,
|
|
15
|
-
_ref$currentValue = _ref.currentValue,
|
|
16
|
-
currentValue = _ref$currentValue === void 0 ? "" : _ref$currentValue,
|
|
17
|
-
_ref$name = _ref.name,
|
|
18
|
-
name = _ref$name === void 0 ? "" : _ref$name,
|
|
19
|
-
_ref$category = _ref.category,
|
|
20
|
-
category = _ref$category === void 0 ? "" : _ref$category,
|
|
21
|
-
_ref$retailer = _ref.retailer,
|
|
22
|
-
retailer = _ref$retailer === void 0 ? "" : _ref$retailer,
|
|
23
|
-
_ref$maxChar = _ref.maxChar,
|
|
24
|
-
maxChar = _ref$maxChar === void 0 ? 100 : _ref$maxChar;
|
|
25
|
-
return "\n Eres un especialista en la generaci\xF3n, optimizaci\xF3n, mejora y captura de atributos de la ficha t\xE9cnica de productos para cat\xE1logos en l\xEDnea.\n Tu tarea es crear atributos claros, concisos y relevantes que resalten las caracter\xEDsticas y beneficios del producto, utilizando un lenguaje preciso y adaptado al p\xFAblico objetivo.\n\n Datos del producto:\n - UPC: ".concat(upc, "\n - Nombre del producto: ").concat(name, "\n - Categor\xEDa: ").concat(category, "\n - Nombre del atributo: ").concat(inputName, "\n - Requerimiento del atributo: ").concat(description, "\n - Valor actual del atributo: ").concat(currentValue, "\n - Cadena comercial dirigida: ").concat(retailer, "\n\n Instrucciones:\n 1. Analiza el nombre del producto y la categor\xEDa para entender su contexto.\n 2. Analiza la descripci\xF3n del atributo actual del producto.\n 3. Identifica la informaci\xF3n clave del atributo que sean relevantes y \xFAtiles para los clientes potenciales.\n 4. Genera una lista de atributos que:\n - Cumplan con la descripcion del atributo proporcionada, no inventes datos o cambies el contexto de lo que pide la descripci\xF3n del atributo.\n - Sean claros y f\xE1ciles de entender.\n - Destaquen las caracter\xEDsticas y beneficios clave del producto.\n - Utilicen un lenguaje preciso y adaptado al p\xFAblico objetivo.\n - Mantengan un tono profesional y coherente con la marca.\n - Aumenten la probabilidad de compra del producto.\n - No excedan los ").concat(maxChar, " caracteres en total.\n - Si existe ejemplo en la descripci\xF3n del atributo, sigue el mismo formato para generar los atributos.\n 5. No incluyas emojis ni signos especiales (*/+\xB4!\xA1?\xBF)\n 6. No repitas el encabezado: ").concat(inputName, "\n 7. No incluyas call to action, ejemplo: \"!Compra ya!\" \"!Da click!\" \"!Apurate!\"\n\n Aseg\xFArate de que los atributos generados cumplan con todas las instrucciones proporcionadas.\n\n No lo olvides, el objetivo principal es mejorar la captura de atributos para la ficha t\xE9cnica del producto para atraer, convencer y dar la informaci\xF3n completa a los clientes potenciales que puedan realizar una compra.\n ");
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
exports.generateAttributePrompt = generateAttributePrompt;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.generateDescriptionPrompt = void 0;
|
|
7
|
-
|
|
8
|
-
// Cadena y Proveedor
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* La cadena ${cadena} tiene estas reglas ${reglas} para el tipo de descripcion que es: ${descripcion}
|
|
12
|
-
*/
|
|
13
|
-
var generateDescriptionPrompt = function generateDescriptionPrompt(_ref) {
|
|
14
|
-
var _ref$upc = _ref.upc,
|
|
15
|
-
upc = _ref$upc === void 0 ? 0 : _ref$upc,
|
|
16
|
-
_ref$inputName = _ref.inputName,
|
|
17
|
-
inputName = _ref$inputName === void 0 ? "" : _ref$inputName,
|
|
18
|
-
_ref$description = _ref.description,
|
|
19
|
-
description = _ref$description === void 0 ? "" : _ref$description,
|
|
20
|
-
_ref$currentValue = _ref.currentValue,
|
|
21
|
-
currentValue = _ref$currentValue === void 0 ? "" : _ref$currentValue,
|
|
22
|
-
_ref$name = _ref.name,
|
|
23
|
-
name = _ref$name === void 0 ? "" : _ref$name,
|
|
24
|
-
_ref$category = _ref.category,
|
|
25
|
-
category = _ref$category === void 0 ? "" : _ref$category,
|
|
26
|
-
_ref$retailer = _ref.retailer,
|
|
27
|
-
retailer = _ref$retailer === void 0 ? "" : _ref$retailer,
|
|
28
|
-
_ref$maxChar = _ref.maxChar,
|
|
29
|
-
maxChar = _ref$maxChar === void 0 ? 100 : _ref$maxChar;
|
|
30
|
-
return "\n Eres un especialista en la generaci\xF3n, optimizaci\xF3n y mejora de descripciones de productos para cat\xE1logos en l\xEDnea.\n Tu tarea es crear descripciones claras, concisas y atractivas que resalten las caracter\xEDsticas y beneficios del producto, utilizando un lenguaje persuasivo y adaptado al p\xFAblico objetivo.\n\n Datos del producto:\n - UPC: ".concat(upc, "\n - Nombre del producto: ").concat(name, "\n - Categor\xEDa: ").concat(category, "\n - Encabezado de la descripci\xF3n: ").concat(inputName, "\n - Requerimiento de la descripcion: ").concat(description, "\n - Descripcion actual del producto: ").concat(currentValue, "\n - Cadena comercial dirigida: ").concat(retailer, "\n\n Instrucciones:\n 1. Analiza la descripci\xF3n actual del producto en caso de tenerla.\n 2. Identifica \xE1reas de mejora, como claridad, concisi\xF3n, atractivo y relevancia.\n 3. Genera una descripci\xF3n que:\n - Sea clara y f\xE1cil de entender.\n - Destaque las caracter\xEDsticas y beneficios clave del producto.\n - Utilice un lenguaje persuasivo y adaptado al p\xFAblico objetivo.\n - Mantenga un tono profesional y coherente con la marca.\n - No exceda los ").concat(maxChar, " caracteres.\n - Aumente la probabilidad de compra del producto, utilizando persuasi\xF3n en la necesidad de compra del producto.\n 4. No incluyas emojis ni signos especiales (*/+\xB4!\xA1?\xBF)\n 5. No repitas el encabezado: ").concat(inputName, "\n 6. No incluyas call to action, ejemplo: \"!Compra ya!\" \"!Da click!\" \"!Apurate!\"\n\n\n Aseg\xFArate de que la descripci\xF3n generada cumpla con todas las instrucciones proporcionadas.\n\n No lo olvides, el objetivo principal es mejorar la descripci\xF3n del producto para atraer y convencer a los clientes potenciales de realizar una compra. Eres un experto en marketing y redacci\xF3n persuasiva.\n\n Nota: No estas hablando con los clientes, estas descripciones ir\xE1n en la tienda de E-commerce de la cadena comercial. No realices saludos, despedidas, sugerencias\n ");
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
exports.generateDescriptionPrompt = generateDescriptionPrompt;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
var schema = {
|
|
8
|
-
type: "object",
|
|
9
|
-
properties: {
|
|
10
|
-
results: {
|
|
11
|
-
type: "array",
|
|
12
|
-
items: {
|
|
13
|
-
type: "object",
|
|
14
|
-
properties: {
|
|
15
|
-
label: {
|
|
16
|
-
type: "string"
|
|
17
|
-
},
|
|
18
|
-
value: {
|
|
19
|
-
type: "string"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
maxItems: 3
|
|
24
|
-
},
|
|
25
|
-
compliance_warnings: {
|
|
26
|
-
type: "array",
|
|
27
|
-
items: {
|
|
28
|
-
type: "string"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
required: ["results"]
|
|
33
|
-
};
|
|
34
|
-
var _default = schema;
|
|
35
|
-
exports.default = _default;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
var schema = {
|
|
8
|
-
type: "object",
|
|
9
|
-
properties: {
|
|
10
|
-
results: {
|
|
11
|
-
type: "array",
|
|
12
|
-
items: {
|
|
13
|
-
type: "object",
|
|
14
|
-
properties: {
|
|
15
|
-
value: {
|
|
16
|
-
type: "string"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
minItems: 1,
|
|
21
|
-
maxItems: 3
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
required: ["results"]
|
|
25
|
-
};
|
|
26
|
-
var _default = schema;
|
|
27
|
-
exports.default = _default;
|