contentoh-components-library 21.6.57 → 21.6.59
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/.claude/settings.local.json +7 -0
- package/dist/components/pages/CreatorsProductEdition/CreatorsProductEditionView.js +90 -135
- package/dist/components/pages/CreatorsProductEdition/hooks/useCreatorsProductEdition.js +148 -162
- package/dist/components/pages/CreatorsProductEdition/mocks/api.fixtures.js +16 -0
- package/dist/components/pages/CreatorsProductEdition/mocks/mockApi.js +1 -0
- package/dist/components/pages/CreatorsProductEdition/sections/ImageGallery.js +433 -0
- package/dist/components/pages/CreatorsProductEdition/sections/NoticeDialog.js +155 -0
- package/dist/components/pages/CreatorsProductEdition/sections/RejectDialog.js +201 -0
- package/dist/components/pages/CreatorsProductEdition/sections/VersionDrawer.js +615 -0
- package/dist/components/pages/CreatorsProductEdition/stories/CreatorsProductEdition.stories.js +3 -31
- package/dist/components/pages/CreatorsProductEdition/stories/CreatorsProductEditionAPI.stories.js +55 -30
- package/dist/components/pages/CreatorsProductEdition/stories/products.js +923 -0
- package/dist/components/pages/CreatorsProductEdition/styles.js +27 -7
- package/dist/components/pages/ProviderProductEdition/ProviderProductEdition.stories.js +2 -1
- package/dist/components/pages/ProviderProductEdition/context/provider-product-edition.context.js +325 -10
- package/dist/components/pages/ProviderProductEdition/context/provider-product-edition.reducer.js +12 -2
- package/dist/components/pages/ProviderProductEdition/index.js +486 -231
- package/dist/index.js +13 -0
- package/package.json +1 -1
- package/src/components/pages/CreatorsProductEdition/CreatorsProductEditionView.jsx +777 -0
- package/src/components/pages/CreatorsProductEdition/constants.js +21 -0
- package/src/components/pages/CreatorsProductEdition/hooks/useCreatorsProductEdition.js +2238 -0
- package/src/components/pages/CreatorsProductEdition/index.js +19 -0
- package/src/components/pages/CreatorsProductEdition/mocks/api.fixtures.js +357 -0
- package/src/components/pages/CreatorsProductEdition/mocks/mockApi.js +144 -0
- package/src/components/pages/CreatorsProductEdition/sections/CommentBox.jsx +183 -0
- package/src/components/pages/CreatorsProductEdition/sections/ImageGallery.jsx +269 -0
- package/src/components/pages/CreatorsProductEdition/sections/ImagePanel.jsx +332 -0
- package/src/components/pages/CreatorsProductEdition/sections/ImagesSection.jsx +385 -0
- package/src/components/pages/CreatorsProductEdition/sections/NoticeDialog.jsx +111 -0
- package/src/components/pages/CreatorsProductEdition/sections/ProductHeader.jsx +305 -0
- package/src/components/pages/CreatorsProductEdition/sections/ProductMedia.jsx +101 -0
- package/src/components/pages/CreatorsProductEdition/sections/RejectDialog.jsx +125 -0
- package/src/components/pages/CreatorsProductEdition/sections/RetailerMenu.jsx +129 -0
- package/src/components/pages/CreatorsProductEdition/sections/ServiceActions.jsx +382 -0
- package/src/components/pages/CreatorsProductEdition/sections/StatusChip.jsx +37 -0
- package/src/components/pages/CreatorsProductEdition/sections/TabsBar.jsx +187 -0
- package/src/components/pages/CreatorsProductEdition/sections/VariantsPanel.jsx +311 -0
- package/src/components/pages/CreatorsProductEdition/sections/VersionDrawer.jsx +357 -0
- package/src/components/pages/CreatorsProductEdition/sections/tokens.js +63 -0
- package/src/components/pages/CreatorsProductEdition/stories/CreatorsProductEdition.stories.js +111 -0
- package/src/components/pages/CreatorsProductEdition/stories/CreatorsProductEditionAPI.stories.js +85 -0
- package/src/components/pages/CreatorsProductEdition/stories/products.js +966 -0
- package/src/components/pages/CreatorsProductEdition/styles.js +178 -0
- package/src/components/pages/ProviderProductEdition/ProviderProductEdition.stories.js +1 -0
- package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx +201 -0
- package/src/components/pages/ProviderProductEdition/context/provider-product-edition.reducer.js +12 -0
- package/src/components/pages/ProviderProductEdition/index.js +228 -7
- package/src/index.js +1 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import axios from "axios";
|
|
4
4
|
import { useDropzone } from "react-dropzone";
|
|
@@ -21,6 +21,8 @@ import {
|
|
|
21
21
|
getServicesData,
|
|
22
22
|
} from "../../../global-files/data";
|
|
23
23
|
import { useCloseModal } from "../../../global-files/customHooks";
|
|
24
|
+
import { useDigitalAssets } from "../../../global-files/digital-assets/useDigitalAssets";
|
|
25
|
+
import { countUnsavedAssets } from "../../../global-files/digital-assets/assets.reducer";
|
|
24
26
|
|
|
25
27
|
import { Button } from "../../atoms/GeneralButton";
|
|
26
28
|
import { GenericModal } from "../../atoms/GenericModal";
|
|
@@ -30,12 +32,14 @@ import { ButtonV2 } from "../../atoms/ButtonV2";
|
|
|
30
32
|
|
|
31
33
|
import { GalleryElement } from "../../molecules/GalleryElement";
|
|
32
34
|
import { GalleryHeader } from "../../molecules/GalleryHeader";
|
|
35
|
+
import { GalleryTrayTabs, TRAYS } from "../../molecules/GalleryTrayTabs";
|
|
33
36
|
import { HeaderTop } from "../../molecules/HeaderTop";
|
|
34
37
|
import { TagAndInput } from "../../molecules/TagAndInput/index";
|
|
35
38
|
|
|
36
39
|
import { FullProductNameHeader } from "../../organisms/FullProductNameHeader";
|
|
37
40
|
import { FullTabsMenu } from "../../organisms/FullTabsMenu";
|
|
38
41
|
import { ImageDataTable } from "../../organisms/ImageDataTable";
|
|
42
|
+
import { DigitalAssetsTray } from "../../organisms/DigitalAssetsTray";
|
|
39
43
|
import { ImagePreviewer } from "../../organisms/ImagePreviewer";
|
|
40
44
|
import { InputGroup } from "../../organisms/InputGroup";
|
|
41
45
|
import { LinkVariantsModal } from "../../organisms/LinkVariantsModal";
|
|
@@ -67,6 +71,14 @@ const ProviderProductEditionView = ({
|
|
|
67
71
|
showSurvey,
|
|
68
72
|
company,
|
|
69
73
|
addToCart,
|
|
74
|
+
/*
|
|
75
|
+
Activos digitales (360, video, gif, pdf). Apagado por omisión, igual que en
|
|
76
|
+
RetailerProductEdition: la interfaz ya está, pero mientras el backend no
|
|
77
|
+
devuelva `assets` en los servicios del producto la bandeja solo muestra lo
|
|
78
|
+
que el usuario acaba de soltar. La app que consuma la librería lo enciende
|
|
79
|
+
cuando el backend esté listo.
|
|
80
|
+
*/
|
|
81
|
+
enableDigitalAssets = false,
|
|
70
82
|
}) => {
|
|
71
83
|
const {
|
|
72
84
|
state,
|
|
@@ -75,6 +87,8 @@ const ProviderProductEditionView = ({
|
|
|
75
87
|
saveDescriptions,
|
|
76
88
|
updateImages,
|
|
77
89
|
deleteImages,
|
|
90
|
+
saveAssets,
|
|
91
|
+
registerUploadedAssets,
|
|
78
92
|
handleOnDownloadImages,
|
|
79
93
|
createComment,
|
|
80
94
|
} = useProviderProductEdition();
|
|
@@ -122,6 +136,49 @@ const ProviderProductEditionView = ({
|
|
|
122
136
|
Imágenes: null,
|
|
123
137
|
});
|
|
124
138
|
|
|
139
|
+
/*
|
|
140
|
+
Bandeja de activos digitales. La lista vive en el reducer de la ficha
|
|
141
|
+
(`state.assets_values`), igual que las imágenes, para que el guardado del
|
|
142
|
+
contexto pueda leerla. El hook solo aporta validación y ciclo de vida.
|
|
143
|
+
*/
|
|
144
|
+
const [assetNotices, setAssetNotices] = useState([]);
|
|
145
|
+
const digitalAssets = useDigitalAssets({
|
|
146
|
+
assets: state.assets_values,
|
|
147
|
+
dispatch,
|
|
148
|
+
notices: assetNotices,
|
|
149
|
+
setNotices: setAssetNotices,
|
|
150
|
+
// Con los dos, la subida a S3 arranca sola al soltar los archivos. Sin
|
|
151
|
+
// ellos —en Storybook, por ejemplo— la bandeja funciona igual pero no sube.
|
|
152
|
+
articleId: state.product?.id_article ?? null,
|
|
153
|
+
token,
|
|
154
|
+
// Al terminar la subida el activo queda registrado solo, sin esperar al
|
|
155
|
+
// botón de guardar: con la barra llena, nadie supone que falta un paso.
|
|
156
|
+
onUploaded: (uploaded) => registerUploadedAssets(token, uploaded),
|
|
157
|
+
});
|
|
158
|
+
const [activeTray, setActiveTray] = useState(TRAYS.IMAGES);
|
|
159
|
+
const currentTray = enableDigitalAssets ? activeTray : TRAYS.IMAGES;
|
|
160
|
+
|
|
161
|
+
/*
|
|
162
|
+
De qué artículo se cargaron ya los activos. `state.services` se recalcula
|
|
163
|
+
cada vez que cambia la cadena activa, pero los activos son generales: no
|
|
164
|
+
dependen de la cadena, así que recargarlos borraría lo que el usuario
|
|
165
|
+
acaba de soltar y todavía no guarda. Por eso se cargan una sola vez por
|
|
166
|
+
artículo.
|
|
167
|
+
*/
|
|
168
|
+
const assetsLoadedFor = useRef(null);
|
|
169
|
+
|
|
170
|
+
const handleOnSetSelectedAssets = (assets) =>
|
|
171
|
+
dispatch({
|
|
172
|
+
type: "SET_SELECTED_ASSETS",
|
|
173
|
+
payload: assets,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const handleOnSetAllAssetsChecked = (isChecked) =>
|
|
177
|
+
dispatch({
|
|
178
|
+
type: "TOGGLE_CHECK_ALL_ASSETS",
|
|
179
|
+
payload: isChecked,
|
|
180
|
+
});
|
|
181
|
+
|
|
125
182
|
const [showVersionSelector, setShowVersionSelector] =
|
|
126
183
|
useCloseModal("version-selector");
|
|
127
184
|
const { getRootProps, getInputProps, isDragActive, open } = useDropzone({
|
|
@@ -366,6 +423,19 @@ const ProviderProductEditionView = ({
|
|
|
366
423
|
|
|
367
424
|
dispatch({ type: "SET_SERVICES_DATA", payload: servicesDataRes });
|
|
368
425
|
|
|
426
|
+
/*
|
|
427
|
+
Activos digitales. `services[2].assets` todavía no existe en la
|
|
428
|
+
respuesta del backend: hasta que exista, esto no hace nada, y el día
|
|
429
|
+
que llegue la bandeja se llena sola sin tocar nada más.
|
|
430
|
+
*/
|
|
431
|
+
if (
|
|
432
|
+
Array.isArray(services[2].assets) &&
|
|
433
|
+
assetsLoadedFor.current !== id_article
|
|
434
|
+
) {
|
|
435
|
+
assetsLoadedFor.current = id_article;
|
|
436
|
+
digitalAssets.replaceAll(services[2].assets);
|
|
437
|
+
}
|
|
438
|
+
|
|
369
439
|
dispatch({ type: "SET_PERCENTAGES", payload: percentages });
|
|
370
440
|
|
|
371
441
|
const activePercentage =
|
|
@@ -594,6 +664,27 @@ const ProviderProductEditionView = ({
|
|
|
594
664
|
}
|
|
595
665
|
};
|
|
596
666
|
|
|
667
|
+
/*
|
|
668
|
+
Guarda los activos y fuerza la recarga si algo se escribió.
|
|
669
|
+
|
|
670
|
+
Esta pantalla no tiene una función `loadData` reutilizable como
|
|
671
|
+
RetailerProductEdition: la carga de servicios vive en un `useEffect` que
|
|
672
|
+
solo se dispara por sus dependencias. `linkNonce` ya existe ahí para eso
|
|
673
|
+
mismo —forzar un refetch sin recargar la página—, así que se reutiliza en
|
|
674
|
+
vez de duplicar el mecanismo.
|
|
675
|
+
|
|
676
|
+
La recarga no es opcional: un activo recién creado sigue en memoria con su
|
|
677
|
+
id temporal y sin el id de la base. Sin volver a leer, el siguiente
|
|
678
|
+
guardado lo mandaría otra vez como nuevo y se duplicaría.
|
|
679
|
+
*/
|
|
680
|
+
const handleOnSaveAssets = async () => {
|
|
681
|
+
const guardado = await saveAssets(token);
|
|
682
|
+
if (!guardado) return;
|
|
683
|
+
|
|
684
|
+
assetsLoadedFor.current = null;
|
|
685
|
+
setLinkNonce((n) => n + 1);
|
|
686
|
+
};
|
|
687
|
+
|
|
597
688
|
const handleOnApproveAll = () => {
|
|
598
689
|
const currentOrigin = origin[state.active_tab];
|
|
599
690
|
|
|
@@ -671,7 +762,98 @@ const ProviderProductEditionView = ({
|
|
|
671
762
|
setShowRejectModal(true);
|
|
672
763
|
};
|
|
673
764
|
|
|
765
|
+
/*
|
|
766
|
+
Descarga de activos: los seleccionados, o todos si no hay selección — el
|
|
767
|
+
mismo criterio que usa la descarga de imágenes.
|
|
768
|
+
|
|
769
|
+
Solo se descarga lo que ya está en S3. Un activo recién soltado vive como
|
|
770
|
+
referencia al archivo del disco del usuario: "descargarlo" le devolvería el
|
|
771
|
+
archivo que él mismo acaba de elegir, lo cual no tiene sentido.
|
|
772
|
+
*/
|
|
773
|
+
const handleOnDownloadAssets = () => {
|
|
774
|
+
const seleccion = state.selected_assets.length
|
|
775
|
+
? state.selected_assets
|
|
776
|
+
: state.assets_values;
|
|
777
|
+
|
|
778
|
+
const descargables = seleccion.filter((asset) => asset.id && asset.url);
|
|
779
|
+
|
|
780
|
+
if (descargables.length === 0) {
|
|
781
|
+
dispatch({
|
|
782
|
+
type: "SET_MODAL",
|
|
783
|
+
payload: {
|
|
784
|
+
show: true,
|
|
785
|
+
title: "Nada que descargar",
|
|
786
|
+
message:
|
|
787
|
+
"Los activos seleccionados todavía no se han guardado. Guárdalos primero.",
|
|
788
|
+
image: warningIcon,
|
|
789
|
+
},
|
|
790
|
+
});
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
descargables.forEach((asset) => saveAs(asset.url, asset.name));
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
/*
|
|
798
|
+
Borrado en lote de activos.
|
|
799
|
+
|
|
800
|
+
A diferencia de las imágenes, que se borran contra el backend en el
|
|
801
|
+
momento, los activos se quitan de la bandeja y su baja viaja en el mismo
|
|
802
|
+
PUT del guardado (`deleteAssets`). Es lo que permite al usuario deshacerse
|
|
803
|
+
de un borrado por error: basta con no guardar. El mensaje lo dice, para que
|
|
804
|
+
nadie se quede pensando que ya se aplicó.
|
|
805
|
+
*/
|
|
806
|
+
const handleOnAskToDeleteAssets = () => {
|
|
807
|
+
if (state.selected_assets.length === 0) {
|
|
808
|
+
dispatch({
|
|
809
|
+
type: "SET_MODAL",
|
|
810
|
+
payload: {
|
|
811
|
+
show: true,
|
|
812
|
+
title: "Eliminar activos digitales",
|
|
813
|
+
message: "No has seleccionado ningún activo para eliminar.",
|
|
814
|
+
image: warningIcon,
|
|
815
|
+
},
|
|
816
|
+
});
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
const seleccionados = state.selected_assets;
|
|
821
|
+
|
|
822
|
+
dispatch({
|
|
823
|
+
type: "SET_MODAL",
|
|
824
|
+
payload: {
|
|
825
|
+
show: true,
|
|
826
|
+
title: "Eliminar activos digitales",
|
|
827
|
+
message: `Se quitarán ${seleccionados.length} activo(s) de la bandeja. El borrado se aplica al guardar.`,
|
|
828
|
+
image: warningIcon,
|
|
829
|
+
buttons: [
|
|
830
|
+
{
|
|
831
|
+
text: "Cancelar",
|
|
832
|
+
buttonType: "general-white-button",
|
|
833
|
+
action: () =>
|
|
834
|
+
dispatch({ type: "SET_MODAL", payload: { show: false } }),
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
text: "Eliminar",
|
|
838
|
+
buttonType: "general-button-default",
|
|
839
|
+
action: () => {
|
|
840
|
+
dispatch({ type: "SET_MODAL", payload: { show: false } });
|
|
841
|
+
seleccionados.forEach((asset) =>
|
|
842
|
+
digitalAssets.removeAsset(asset),
|
|
843
|
+
);
|
|
844
|
+
},
|
|
845
|
+
},
|
|
846
|
+
],
|
|
847
|
+
},
|
|
848
|
+
});
|
|
849
|
+
};
|
|
850
|
+
|
|
674
851
|
const handleOnAskToDeleteImages = () => {
|
|
852
|
+
if (currentTray === TRAYS.ASSETS) {
|
|
853
|
+
handleOnAskToDeleteAssets();
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
|
|
675
857
|
if (state.selected_images.length === 0) {
|
|
676
858
|
dispatch({
|
|
677
859
|
type: "SET_MODAL",
|
|
@@ -847,6 +1029,13 @@ const ProviderProductEditionView = ({
|
|
|
847
1029
|
break;
|
|
848
1030
|
}
|
|
849
1031
|
case "Imágenes":
|
|
1032
|
+
// Se guarda la bandeja que el usuario tiene a la vista: guardar las
|
|
1033
|
+
// dos de golpe mandaría cambios de la otra bandeja que quizá no dio
|
|
1034
|
+
// por terminados.
|
|
1035
|
+
if (currentTray === TRAYS.ASSETS) {
|
|
1036
|
+
handleOnSaveAssets();
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
850
1039
|
updateImages(token);
|
|
851
1040
|
break;
|
|
852
1041
|
default:
|
|
@@ -2269,7 +2458,11 @@ const ProviderProductEditionView = ({
|
|
|
2269
2458
|
updatedImages={state.updated_images_values}
|
|
2270
2459
|
images={state.services.images}
|
|
2271
2460
|
// actions
|
|
2272
|
-
downloadImages={
|
|
2461
|
+
downloadImages={
|
|
2462
|
+
currentTray === TRAYS.ASSETS
|
|
2463
|
+
? handleOnDownloadAssets
|
|
2464
|
+
: handleOnDownloadImages
|
|
2465
|
+
}
|
|
2273
2466
|
askToDeleteImages={handleOnAskToDeleteImages}
|
|
2274
2467
|
showSaveButton={canShowSaveButton(state.product.version_status)}
|
|
2275
2468
|
onClickSave={handleOnClickSave}
|
|
@@ -2395,17 +2588,44 @@ const ProviderProductEditionView = ({
|
|
|
2395
2588
|
{state.active_tab === "Imágenes" &&
|
|
2396
2589
|
(state.product?.images_status !== "NS" ? (
|
|
2397
2590
|
<>
|
|
2398
|
-
{
|
|
2591
|
+
{enableDigitalAssets && (
|
|
2592
|
+
<GalleryTrayTabs
|
|
2593
|
+
activeTray={currentTray}
|
|
2594
|
+
setActiveTray={setActiveTray}
|
|
2595
|
+
imagesCount={
|
|
2596
|
+
state.images_values?.values?.length ?? 0
|
|
2597
|
+
}
|
|
2598
|
+
assetsCount={digitalAssets.assets.length}
|
|
2599
|
+
/>
|
|
2600
|
+
)}
|
|
2601
|
+
{currentTray === TRAYS.ASSETS && (
|
|
2602
|
+
<section
|
|
2603
|
+
className="container"
|
|
2604
|
+
style={{ position: "relative" }}
|
|
2605
|
+
>
|
|
2606
|
+
<DigitalAssetsTray
|
|
2607
|
+
{...digitalAssets}
|
|
2608
|
+
unsaved={countUnsavedAssets(state)}
|
|
2609
|
+
gridLayout={imageLayout}
|
|
2610
|
+
readOnly={false}
|
|
2611
|
+
selectedAssets={state.selected_assets}
|
|
2612
|
+
setSelectedAssets={handleOnSetSelectedAssets}
|
|
2613
|
+
setCheckAll={handleOnSetAllAssetsChecked}
|
|
2614
|
+
/>
|
|
2615
|
+
</section>
|
|
2616
|
+
)}
|
|
2617
|
+
{currentTray === TRAYS.IMAGES && !imageLayout && (
|
|
2399
2618
|
<GalleryHeader
|
|
2400
2619
|
checkAll={state.all_image_checked} // Determina si el checkbox "Seleccionar todo" está marcado
|
|
2401
2620
|
setCheckAll={handleOnSetCheckAll} // Toggler de true o false para el checkbox "Seleccionar todo"
|
|
2402
2621
|
setSelectedImages={handleOnSetSelectedImages}
|
|
2403
2622
|
/>
|
|
2404
2623
|
)}
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2624
|
+
{currentTray === TRAYS.IMAGES && (
|
|
2625
|
+
<section
|
|
2626
|
+
className="container"
|
|
2627
|
+
style={{ position: "relative" }}
|
|
2628
|
+
>
|
|
2409
2629
|
<div
|
|
2410
2630
|
{...getRootProps({
|
|
2411
2631
|
className: `dropzone ${
|
|
@@ -2467,6 +2687,7 @@ const ProviderProductEditionView = ({
|
|
|
2467
2687
|
</div>
|
|
2468
2688
|
)}
|
|
2469
2689
|
</section>
|
|
2690
|
+
)}
|
|
2470
2691
|
</>
|
|
2471
2692
|
) : (
|
|
2472
2693
|
<ScreenHeader
|
package/src/index.js
CHANGED
|
@@ -115,6 +115,7 @@ export * from "./components/pages/OnboardPlan";
|
|
|
115
115
|
export * from "./components/pages/RegistrationLoginSecondStep";
|
|
116
116
|
export * from "./components/pages/RegistrationLoginThirdStep";
|
|
117
117
|
export * from "./components/pages/RetailerProductEdition";
|
|
118
|
+
export * from "./components/pages/CreatorsProductEdition";
|
|
118
119
|
export * from "./components/pages/ProviderProductEdition";
|
|
119
120
|
export * from "./components/pages/VerificationCodeResetPassword";
|
|
120
121
|
export * from "./components/pages/MultipleEdition";
|