contentoh-components-library 21.6.31 → 21.6.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/ai/prompts/attribute.prompt.js +28 -0
  2. package/dist/ai/prompts/description.prompt.js +33 -0
  3. package/dist/ai/schemas/attribute.schema.js +35 -0
  4. package/dist/ai/schemas/description.schema.js +27 -0
  5. package/dist/components/atoms/InheritanceTag/InheritanceTag.stories.js +5 -5
  6. package/dist/components/atoms/InheritanceTag/index.js +6 -6
  7. package/dist/components/organisms/InputGroup/index.js +12 -1
  8. package/dist/components/organisms/LinkVariantsModal/index.js +269 -356
  9. package/dist/components/organisms/LinkVariantsModal/styles.js +14 -5
  10. package/dist/components/organisms/PropagateChangesModal/index.js +12 -13
  11. package/dist/components/pages/ProviderProductEdition/context/provider-product-edition.context.js +5 -5
  12. package/dist/components/pages/ProviderProductEdition/context/reducers/inputs.js +5 -2
  13. package/dist/components/pages/ProviderProductEdition/index.js +76 -33
  14. package/dist/components/pages/RetailerProductEdition/context/provider-product-edition.context.js +5 -5
  15. package/dist/components/pages/RetailerProductEdition/context/reducers/inputs.js +5 -2
  16. package/dist/components/pages/RetailerProductEdition/index.js +303 -309
  17. package/dist/components/pages/RetailerProductEdition/styles.js +2 -2
  18. package/package.json +1 -1
  19. package/src/components/atoms/InheritanceTag/InheritanceTag.stories.js +3 -3
  20. package/src/components/atoms/InheritanceTag/index.js +6 -6
  21. package/src/components/organisms/InputGroup/index.js +12 -0
  22. package/src/components/organisms/LinkVariantsModal/index.js +260 -287
  23. package/src/components/organisms/LinkVariantsModal/styles.js +65 -32
  24. package/src/components/organisms/PropagateChangesModal/index.js +19 -17
  25. package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx +4 -4
  26. package/src/components/pages/ProviderProductEdition/context/reducers/inputs.js +13 -1
  27. package/src/components/pages/ProviderProductEdition/index.js +48 -20
  28. package/src/components/pages/RetailerProductEdition/context/provider-product-edition.context.jsx +4 -4
  29. package/src/components/pages/RetailerProductEdition/context/reducers/inputs.js +13 -1
  30. package/src/components/pages/RetailerProductEdition/index.js +89 -73
  31. package/src/components/pages/RetailerProductEdition/styles.js +0 -11
@@ -181,11 +181,10 @@ const RetailerProductEditionView = ({
181
181
  const [statusArray, setStatusArray] = useState([]);
182
182
  const [rejectAll, setRejectAll] = useState(false);
183
183
 
184
- // Variantes: mismo comportamiento que la ficha de la aplicación de clientes.
184
+ // Padre/hijo: mismo comportamiento que la ficha de la aplicación de clientes.
185
185
  const [showLinkVariants, setShowLinkVariants] = useState(false);
186
186
  const [family, setFamily] = useState(null);
187
187
  const [showFamily, setShowFamily] = useState(false);
188
- const [loadingVariant, setLoadingVariant] = useState(null);
189
188
  const [pendingPropagation, setPendingPropagation] = useState(null);
190
189
  const [preparandoPropagacion, setPreparandoPropagacion] = useState(false);
191
190
 
@@ -783,12 +782,12 @@ const RetailerProductEditionView = ({
783
782
  };
784
783
 
785
784
  /*
786
- Trae la familia: las variantes del producto, o sus hermanas si el abierto es
785
+ Trae la familia: los hijos del producto, o sus hermanos si el abierto es
787
786
  una de ellas. Se pide al abrir la sección y no al montar la pantalla: la
788
787
  mayoría de los productos no son familia.
789
788
  */
790
- const loadFamily = async () => {
791
- if (family) return family;
789
+ const loadFamily = async (forzar = false) => {
790
+ if (family && !forzar) return family;
792
791
  try {
793
792
  const res = await axios.post(
794
793
  `${process.env.REACT_APP_VARIANTS_ENDPOINT}/family`,
@@ -806,43 +805,48 @@ const RetailerProductEditionView = ({
806
805
  };
807
806
 
808
807
  /*
809
- Abre otra variante. Esta pantalla lee el producto de sessionStorage, no de la
810
- URL, así que hay que dejarlo ahí antes de navegar; si no, cambia la dirección
811
- y sigue mostrando el producto anterior.
808
+ En Creators el parentesco se pregunta, no viene con el producto.
812
809
 
813
- Se pide por ID y no por UPC: hay 12,024 UPC repetidos entre artículos activos
814
- y 5,579 de esos casos caen dentro de la misma compañía.
810
+ Su listado sale del endpoint de reportes, que no trae `variantsCount` ni
811
+ `parentArticleId`: esas columnas se agregaron a las vistas pero DynamoDB no
812
+ las tiene hasta que se corra el recorrido de datos. Y aunque las tuviera,
813
+ dependería de lo actualizado que esté ese recorrido.
814
+
815
+ Preguntar a `family` cuesta una llamada por ficha y da el dato de la base, no
816
+ de una copia. Además aplica el alcance del perfil (§5.1): al equipo interno le
817
+ devuelve los productos solicitados a ContentOh, que es justo lo que puede
818
+ tocar.
815
819
  */
816
- const openVariant = async (articleId) => {
817
- setLoadingVariant(articleId);
818
- try {
819
- const res = await axios.get(`${process.env.REACT_APP_NEW_ARTICLES_ENDPOINT}`, {
820
- params: { listType: "general", filterByArticleId: articleId },
821
- headers: { Authorization: token },
822
- });
820
+ useEffect(() => {
821
+ if (!state.product?.id_article) return;
822
+ loadFamily(true);
823
+ // eslint-disable-next-line react-hooks/exhaustive-deps
824
+ }, [state.product?.id_article]);
823
825
 
824
- const { data } = readPayload(res);
825
- const encontrado = (data ?? []).find(
826
- (item) => Number(item.id_article) === Number(articleId)
827
- );
826
+ // El conteo sale de la familia recién consultada, no del producto.
827
+ const hijosDelProducto = family?.error
828
+ ? 0
829
+ : (family?.variants ?? []).filter((v) => !v.isCurrent).length;
828
830
 
829
- if (encontrado) {
830
- sessionStorage.setItem(
831
- "productSelected",
832
- JSON.stringify({
833
- ...encontrado,
834
- article: { id_article: encontrado.id_article },
835
- })
836
- );
837
- }
838
- } catch (error) {
839
- // Se navega igual: dejar el clic sin efecto parecería que no responde.
840
- console.error("openVariant: ", error);
841
- } finally {
842
- setLoadingVariant(null);
843
- window.location.assign("/EditProducts");
844
- }
845
- };
831
+ const esHijoDeOtro = family?.error
832
+ ? !!state.product?.parentArticleId
833
+ : !!family?.parent;
834
+
835
+ /*
836
+ En Creators la lista de familia es INFORMATIVA: no se salta a otro producto.
837
+
838
+ Saltar exige precargar el producto destino, y el endpoint que hace eso en la
839
+ aplicación de clientes —read-articles-v2— filtra por la compañía del usuario:
840
+ `AND a.company_id = <la del usuario>`. El equipo interno pertenece a ContentOh
841
+ y trabaja productos de sus clientes, así que ahí no devuelve nada.
842
+
843
+ Navegar sin precargar sería peor que no ofrecerlo: esta pantalla lee el
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.
846
+
847
+ Para habilitarlo hace falta una forma de traer un producto por id sin filtro
848
+ de compañía, respetando el alcance del perfil interno (§5.1 del contrato).
849
+ */
846
850
 
847
851
  /*
848
852
  Refresca tras ligar, sin recargar: el producto sale de sessionStorage, así que
@@ -878,18 +882,42 @@ const RetailerProductEditionView = ({
878
882
  Acción "Volver a heredar" de los chips. Repinta en sitio con lo que devuelve
879
883
  el endpoint: recargar la ficha se llevaría lo que haya sin guardar.
880
884
  */
881
- const handleOnRestoreInheritance = async (attributeId) => {
885
+ /*
886
+ `kind` distingue de qué pestaña salió el chip. Las descripciones viven en
887
+ `rel_article_description` y la ficha técnica en `article_data`: el endpoint
888
+ recibe una lista o la otra.
889
+ */
890
+ const handleOnRestoreInheritance = async (attributeId, kind = "attribute") => {
882
891
  if (!attributeId || !state.product?.id_article) return;
883
892
 
893
+ const esDescripcion = kind === "description";
894
+
884
895
  try {
885
896
  const res = await axios.post(
886
897
  `${process.env.REACT_APP_VARIANTS_ENDPOINT}/restore`,
887
- { articleId: state.product.id_article, attributes: [Number(attributeId)] },
898
+ {
899
+ articleId: state.product.id_article,
900
+ ...(esDescripcion
901
+ ? { descriptions: [Number(attributeId)] }
902
+ : { attributes: [Number(attributeId)] }),
903
+ },
888
904
  { headers: { Authorization: token } }
889
905
  );
890
906
 
891
907
  const data = readPayload(res);
892
908
 
909
+ if (esDescripcion) {
910
+ dispatch({
911
+ type: "UPDATE_DESCRIPTIONS_INPUTS",
912
+ payload: (data.descriptionValues || []).map((item) => ({
913
+ attributeId: item.id_description,
914
+ value: item.value,
915
+ isOverridden: 0,
916
+ })),
917
+ });
918
+ return;
919
+ }
920
+
893
921
  dispatch({
894
922
  type: "UPDATE_DATASHEETS_INPUTS",
895
923
  payload: (data.values || []).map((item) => ({
@@ -929,10 +957,10 @@ const RetailerProductEditionView = ({
929
957
  await saveDescriptions(token);
930
958
  break;
931
959
  case "Ficha técnica": {
932
- // Guardar un padre con variantes abre la decisión de propagar. Sin este
933
- // paso el cambio se queda solo en el padre y las variantes se van
960
+ // Guardar un padre con hijos abre la decisión de propagar. Sin este
961
+ // paso el cambio se queda solo en el padre y los hijos se van
934
962
  // separando de él sin que nadie lo note.
935
- const esPadre = state.product?.variantsCount > 0;
963
+ const esPadre = hijosDelProducto > 0;
936
964
  const cambios = cambiosDeFichaTecnica();
937
965
 
938
966
  if (esPadre && cambios.length > 0) {
@@ -1926,9 +1954,9 @@ const RetailerProductEditionView = ({
1926
1954
  </div>
1927
1955
 
1928
1956
  <div className="product-information">
1929
- {/* Solo si el producto NO es ya variante de alguien: ligarlo otra vez
1957
+ {/* Solo si el producto NO es ya hijo de alguien: ligarlo otra vez
1930
1958
  devolvería VARIANT_ALREADY_LINKED sin excepción. */}
1931
- {!state.product?.parentArticleId && (
1959
+ {!esHijoDeOtro && (
1932
1960
  <div className="variants-actions">
1933
1961
  <button
1934
1962
  type="button"
@@ -1937,7 +1965,7 @@ const RetailerProductEditionView = ({
1937
1965
  >
1938
1966
  Ligar productos
1939
1967
  </button>
1940
- {state.product?.variantsCount > 0 && (
1968
+ {hijosDelProducto > 0 && (
1941
1969
  <button
1942
1970
  type="button"
1943
1971
  className="variants-count"
@@ -1947,15 +1975,15 @@ const RetailerProductEditionView = ({
1947
1975
  loadFamily();
1948
1976
  }}
1949
1977
  >
1950
- {state.product.variantsCount} variante
1951
- {state.product.variantsCount === 1 ? "" : "s"}
1978
+ {hijosDelProducto} hijo
1979
+ {hijosDelProducto === 1 ? "" : "s"}
1952
1980
  <span aria-hidden="true">{showFamily ? " ▴" : " ▾"}</span>
1953
1981
  </button>
1954
1982
  )}
1955
1983
  </div>
1956
1984
  )}
1957
1985
 
1958
- {state.product?.parentArticleId && (
1986
+ {esHijoDeOtro && (
1959
1987
  <div className="variants-actions">
1960
1988
  <button
1961
1989
  type="button"
@@ -1966,7 +1994,7 @@ const RetailerProductEditionView = ({
1966
1994
  loadFamily();
1967
1995
  }}
1968
1996
  >
1969
- Variante de otro producto
1997
+ Hijo de otro producto
1970
1998
  <span aria-hidden="true">{showFamily ? " ▴" : " ▾"}</span>
1971
1999
  </button>
1972
2000
  </div>
@@ -1983,44 +2011,28 @@ const RetailerProductEditionView = ({
1983
2011
  )}
1984
2012
 
1985
2013
  {family?.parent && (
1986
- <button
1987
- type="button"
1988
- className="family-row parent"
1989
- disabled={loadingVariant !== null}
1990
- onClick={() => openVariant(family.parent.articleId)}
1991
- >
1992
- <span className="role">
1993
- {loadingVariant === family.parent.articleId
1994
- ? "Abriendo…"
1995
- : "Producto padre"}
1996
- </span>
2014
+ <div className="family-row parent">
2015
+ <span className="role">Producto padre</span>
1997
2016
  <span className="name">{family.parent.name}</span>
1998
2017
  <span className="upc">{family.parent.upc}</span>
1999
- </button>
2018
+ </div>
2000
2019
  )}
2001
2020
 
2002
2021
  {family?.variants?.map((variant) => (
2003
- <button
2022
+ <div
2004
2023
  key={variant.articleId}
2005
- type="button"
2006
2024
  className={`family-row${variant.isCurrent ? " current" : ""}`}
2007
- disabled={variant.isCurrent || loadingVariant !== null}
2008
- onClick={() => openVariant(variant.articleId)}
2009
2025
  >
2010
2026
  <span className="role">
2011
- {loadingVariant === variant.articleId
2012
- ? "Abriendo…"
2013
- : variant.isCurrent
2014
- ? "Estás aquí"
2015
- : "Variante"}
2027
+ {variant.isCurrent ? "Estás aquí" : "Hijo"}
2016
2028
  </span>
2017
2029
  <span className="name">{variant.name}</span>
2018
2030
  <span className="upc">{variant.upc}</span>
2019
- </button>
2031
+ </div>
2020
2032
  ))}
2021
2033
 
2022
2034
  {family && !family.error && !family.variants?.length && (
2023
- <p className="loading">Este producto no tiene variantes.</p>
2035
+ <p className="loading">Este producto no tiene hijos.</p>
2024
2036
  )}
2025
2037
  </div>
2026
2038
  )}
@@ -2107,6 +2119,10 @@ const RetailerProductEditionView = ({
2107
2119
  activeSection={state.active_tab}
2108
2120
  inputGroup={state.descriptions_inputs[0]}
2109
2121
  updatedDescriptions={state.updated_descriptions_inputs}
2122
+ /* El parentesco es del producto, no del servicio: los
2123
+ dos endpoints lo devuelven igual. */
2124
+ variant={state.services?.datasheets?.variant}
2125
+ onRestoreInheritance={handleOnRestoreInheritance}
2110
2126
  articleId={state.product?.id_article}
2111
2127
  version={state.product.version}
2112
2128
  auditInputGroup={auditDescriptions[0]}
@@ -220,24 +220,13 @@ export const Container = styled.div`
220
220
  align-items: baseline;
221
221
  gap: 8px;
222
222
  padding: 6px 8px;
223
- border: none;
224
223
  border-radius: 4px;
225
- background: none;
226
- cursor: pointer;
227
224
  text-align: left;
228
225
  font-family: ${FontFamily.Raleway_500};
229
226
  font-size: 12px;
230
227
  color: ${GlobalColors.deep_gray};
231
228
  }
232
229
 
233
- .family-row:hover:not(:disabled) {
234
- background-color: ${GlobalColors.s2};
235
- }
236
-
237
- .family-row:disabled {
238
- cursor: default;
239
- opacity: 0.7;
240
- }
241
230
 
242
231
  .family-row .role {
243
232
  min-width: 96px;