contentoh-components-library 21.6.27 → 21.6.29
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/PropagateChangesModal/index.js +213 -0
- package/dist/components/organisms/PropagateChangesModal/styles.js +53 -0
- package/dist/components/pages/ProviderProductEdition/context/provider-product-edition.context.js +16 -7
- package/dist/components/pages/ProviderProductEdition/index.js +172 -56
- package/dist/components/pages/ProviderProductEdition/styles.js +2 -2
- package/dist/index.js +25 -12
- package/package.json +1 -1
- package/src/components/organisms/PropagateChangesModal/index.js +209 -0
- package/src/components/organisms/PropagateChangesModal/styles.js +184 -0
- package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx +9 -1
- package/src/components/pages/ProviderProductEdition/index.js +160 -34
- package/src/components/pages/ProviderProductEdition/styles.js +13 -0
- package/src/index.js +1 -0
|
@@ -9,7 +9,11 @@ import {
|
|
|
9
9
|
useProviderProductEdition,
|
|
10
10
|
} from "./context/provider-product-edition.context";
|
|
11
11
|
import { normalizeProduct, getConceptByTab } from "./utils";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
getMinorStatus,
|
|
14
|
+
getMinorStatusFromRetailerMap,
|
|
15
|
+
STATUS_DICTIONARY,
|
|
16
|
+
} from "../../../global-files/statusDictionary";
|
|
13
17
|
|
|
14
18
|
import {
|
|
15
19
|
getPercentage,
|
|
@@ -35,6 +39,7 @@ import { ImageDataTable } from "../../organisms/ImageDataTable";
|
|
|
35
39
|
import { ImagePreviewer } from "../../organisms/ImagePreviewer";
|
|
36
40
|
import { InputGroup } from "../../organisms/InputGroup";
|
|
37
41
|
import { LinkVariantsModal } from "../../organisms/LinkVariantsModal";
|
|
42
|
+
import { PropagateChangesModal } from "../../organisms/PropagateChangesModal";
|
|
38
43
|
import { readPayload } from "../../organisms/LinkVariantsModal/api";
|
|
39
44
|
import { ProductImageModal } from "../../organisms/ProductImageModal";
|
|
40
45
|
import { VersionSelector } from "../../organisms/VersionSelector";
|
|
@@ -79,6 +84,8 @@ const ProviderProductEditionView = ({
|
|
|
79
84
|
const [family, setFamily] = useState(null);
|
|
80
85
|
const [showFamily, setShowFamily] = useState(false);
|
|
81
86
|
const [loadingVariant, setLoadingVariant] = useState(null);
|
|
87
|
+
const [pendingPropagation, setPendingPropagation] = useState(null);
|
|
88
|
+
const [preparandoPropagacion, setPreparandoPropagacion] = useState(false);
|
|
82
89
|
const [showRejectModal, setShowRejectModal] = useState(false);
|
|
83
90
|
const [headerTop, setHeaderTop] = useState(0);
|
|
84
91
|
const [assig, setAssig] = useState({});
|
|
@@ -233,7 +240,7 @@ const ProviderProductEditionView = ({
|
|
|
233
240
|
id_category,
|
|
234
241
|
version,
|
|
235
242
|
token,
|
|
236
|
-
id_retailer
|
|
243
|
+
id_retailer
|
|
237
244
|
),
|
|
238
245
|
getPercentage({ data, headers }),
|
|
239
246
|
getServicesData({
|
|
@@ -245,11 +252,10 @@ const ProviderProductEditionView = ({
|
|
|
245
252
|
]);
|
|
246
253
|
|
|
247
254
|
const percentageRaw = percentageRes?.[0];
|
|
248
|
-
const percentages =
|
|
249
|
-
Array.isArray(percentageRaw)
|
|
255
|
+
const percentages =
|
|
256
|
+
(Array.isArray(percentageRaw)
|
|
250
257
|
? percentageRaw[0]?.relations
|
|
251
|
-
: JSON.parse(percentageRaw?.body ?? "null")?.[0]?.relations
|
|
252
|
-
) ?? [];
|
|
258
|
+
: JSON.parse(percentageRaw?.body ?? "null")?.[0]?.relations) ?? [];
|
|
253
259
|
|
|
254
260
|
const orderMap =
|
|
255
261
|
services[2].inputsByRetailer ??
|
|
@@ -277,12 +283,16 @@ const ProviderProductEditionView = ({
|
|
|
277
283
|
|
|
278
284
|
return acc;
|
|
279
285
|
},
|
|
280
|
-
{}
|
|
286
|
+
{}
|
|
281
287
|
);
|
|
282
288
|
|
|
283
289
|
const getServiceMinorStatus = (serviceName) => {
|
|
284
|
-
const records = servicesDataRes.filter(
|
|
285
|
-
|
|
290
|
+
const records = servicesDataRes.filter(
|
|
291
|
+
(s) => s.service === serviceName
|
|
292
|
+
);
|
|
293
|
+
return records.length > 0
|
|
294
|
+
? getMinorStatus(records.map((s) => s.status))
|
|
295
|
+
: undefined;
|
|
286
296
|
};
|
|
287
297
|
|
|
288
298
|
const imagesMinorStatus = getServiceMinorStatus("images");
|
|
@@ -295,9 +305,15 @@ const ProviderProductEditionView = ({
|
|
|
295
305
|
...state.product,
|
|
296
306
|
statusByRetailer: updatedStatusByRetailer,
|
|
297
307
|
status: getMinorStatusFromRetailerMap(updatedStatusByRetailer),
|
|
298
|
-
...(imagesMinorStatus !== undefined && {
|
|
299
|
-
|
|
300
|
-
|
|
308
|
+
...(imagesMinorStatus !== undefined && {
|
|
309
|
+
images_status: imagesMinorStatus,
|
|
310
|
+
}),
|
|
311
|
+
...(descriptionMinorStatus !== undefined && {
|
|
312
|
+
description_status: descriptionMinorStatus,
|
|
313
|
+
}),
|
|
314
|
+
...(datasheetMinorStatus !== undefined && {
|
|
315
|
+
datasheet_status: datasheetMinorStatus,
|
|
316
|
+
}),
|
|
301
317
|
},
|
|
302
318
|
});
|
|
303
319
|
|
|
@@ -320,7 +336,7 @@ const ProviderProductEditionView = ({
|
|
|
320
336
|
const activePercentage =
|
|
321
337
|
percentages.find(({ id_retailer: rId }) => rId === id_retailer) ||
|
|
322
338
|
state.product.percentages?.find(
|
|
323
|
-
({ id_retailer: rId }) => rId === id_retailer
|
|
339
|
+
({ id_retailer: rId }) => rId === id_retailer
|
|
324
340
|
);
|
|
325
341
|
|
|
326
342
|
dispatch({
|
|
@@ -364,7 +380,10 @@ const ProviderProductEditionView = ({
|
|
|
364
380
|
};
|
|
365
381
|
dispatch({
|
|
366
382
|
type: "SET_DATASHEETS_INPUTS",
|
|
367
|
-
payload: [
|
|
383
|
+
payload: [
|
|
384
|
+
datasheetsActiveRetailer,
|
|
385
|
+
state.services.datasheets.inputs,
|
|
386
|
+
],
|
|
368
387
|
});
|
|
369
388
|
} else {
|
|
370
389
|
dispatch({ type: "SET_DATASHEETS_INPUTS", payload: [] });
|
|
@@ -373,7 +392,7 @@ const ProviderProductEditionView = ({
|
|
|
373
392
|
|
|
374
393
|
if (state.services.descriptions) {
|
|
375
394
|
const descriptionsActiveRetailer = state.services.descriptions.filter(
|
|
376
|
-
(item) => item.id === state.active_retailer.id_retailer
|
|
395
|
+
(item) => item.id === state.active_retailer.id_retailer
|
|
377
396
|
);
|
|
378
397
|
|
|
379
398
|
dispatch({
|
|
@@ -388,8 +407,8 @@ const ProviderProductEditionView = ({
|
|
|
388
407
|
retailerInput.some(
|
|
389
408
|
(input) =>
|
|
390
409
|
input.id_retailer === state.active_retailer.id_retailer &&
|
|
391
|
-
input.id_image === value.image_id
|
|
392
|
-
)
|
|
410
|
+
input.id_image === value.image_id
|
|
411
|
+
)
|
|
393
412
|
);
|
|
394
413
|
});
|
|
395
414
|
|
|
@@ -419,7 +438,7 @@ const ProviderProductEditionView = ({
|
|
|
419
438
|
const { status: currentStatus } = state.services_data.find(
|
|
420
439
|
(service) =>
|
|
421
440
|
service.service === currentService &&
|
|
422
|
-
service.id_retailer === currentRetailer
|
|
441
|
+
service.id_retailer === currentRetailer
|
|
423
442
|
);
|
|
424
443
|
|
|
425
444
|
const originTab = origin[state.active_tab];
|
|
@@ -488,7 +507,7 @@ const ProviderProductEditionView = ({
|
|
|
488
507
|
name: e?.name,
|
|
489
508
|
required: e?.required,
|
|
490
509
|
active: state.images_values?.values?.some(
|
|
491
|
-
(value) => value?.image_id === e?.id
|
|
510
|
+
(value) => value?.image_id === e?.id
|
|
492
511
|
),
|
|
493
512
|
}));
|
|
494
513
|
const imageType = state.images_values?.imageType?.map((e) => ({
|
|
@@ -499,7 +518,7 @@ const ProviderProductEditionView = ({
|
|
|
499
518
|
(e) => ({
|
|
500
519
|
value: e?.id,
|
|
501
520
|
name: e?.name,
|
|
502
|
-
})
|
|
521
|
+
})
|
|
503
522
|
);
|
|
504
523
|
|
|
505
524
|
return state.images_values?.values?.map((image, index) => (
|
|
@@ -658,15 +677,56 @@ const ProviderProductEditionView = ({
|
|
|
658
677
|
});
|
|
659
678
|
};
|
|
660
679
|
|
|
680
|
+
/*
|
|
681
|
+
Los atributos que se acaban de tocar, con el nombre que ve el usuario.
|
|
682
|
+
|
|
683
|
+
`updated_datasheets_inputs` trae { attributeId, value } y nada más, así que el
|
|
684
|
+
nombre se busca en los inputs de la cadena activa: un diálogo que preguntara
|
|
685
|
+
por "el atributo 1023" no serviría para decidir nada.
|
|
686
|
+
*/
|
|
687
|
+
const cambiosDeFichaTecnica = () => {
|
|
688
|
+
const retailerId = state.active_retailer?.id_retailer;
|
|
689
|
+
const inputs = state.services?.datasheets?.inputs ?? {};
|
|
690
|
+
|
|
691
|
+
return (state.updated_datasheets_inputs ?? []).map((item) => {
|
|
692
|
+
const input = inputs[`${item.attributeId}_${retailerId}`];
|
|
693
|
+
return {
|
|
694
|
+
id: Number(item.attributeId),
|
|
695
|
+
name: input?.name ?? `Atributo ${item.attributeId}`,
|
|
696
|
+
value: item.value,
|
|
697
|
+
};
|
|
698
|
+
});
|
|
699
|
+
};
|
|
700
|
+
|
|
661
701
|
const handleOnClickSave = () => {
|
|
662
|
-
|
|
702
|
+
// `preparandoPropagacion` cubre la ventana entre el clic y la apertura del
|
|
703
|
+
// diálogo: sin esto, dos clics seguidos lanzan dos consultas de familia.
|
|
704
|
+
if (state.saving || preparandoPropagacion) return;
|
|
663
705
|
switch (state.active_tab) {
|
|
664
706
|
case "Descripción":
|
|
665
707
|
saveDescriptions(token);
|
|
666
708
|
break;
|
|
667
|
-
case "Ficha técnica":
|
|
709
|
+
case "Ficha técnica": {
|
|
710
|
+
// Guardar un padre con variantes abre la decisión de propagar. Sin este
|
|
711
|
+
// paso el cambio se queda solo en el padre y las variantes se van
|
|
712
|
+
// separando de él sin que nadie lo note.
|
|
713
|
+
const esPadre = state.product?.variantsCount > 0;
|
|
714
|
+
const cambios = cambiosDeFichaTecnica();
|
|
715
|
+
|
|
716
|
+
if (esPadre && cambios.length > 0) {
|
|
717
|
+
// Se espera a tener la familia antes de abrir: si no, el diálogo
|
|
718
|
+
// aparece diciendo "0 variantes" hasta que llega la respuesta, que es
|
|
719
|
+
// justo lo contrario de lo que va a preguntar.
|
|
720
|
+
setPreparandoPropagacion(true);
|
|
721
|
+
loadFamily()
|
|
722
|
+
.then(() => setPendingPropagation({ cambios }))
|
|
723
|
+
.finally(() => setPreparandoPropagacion(false));
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
|
|
668
727
|
saveDatasheets(token);
|
|
669
728
|
break;
|
|
729
|
+
}
|
|
670
730
|
case "Imágenes":
|
|
671
731
|
updateImages(token);
|
|
672
732
|
break;
|
|
@@ -709,7 +769,7 @@ const ProviderProductEditionView = ({
|
|
|
709
769
|
peso que paga todo el mundo por el caso de unos pocos.
|
|
710
770
|
*/
|
|
711
771
|
const loadFamily = async () => {
|
|
712
|
-
if (family) return;
|
|
772
|
+
if (family) return family;
|
|
713
773
|
try {
|
|
714
774
|
const res = await axios.post(
|
|
715
775
|
`${process.env.REACT_APP_VARIANTS_ENDPOINT}/family`,
|
|
@@ -738,6 +798,40 @@ const ProviderProductEditionView = ({
|
|
|
738
798
|
Es un rodeo, y lo es porque el origen del dato está mal puesto. Arreglarlo de
|
|
739
799
|
raíz —que la ficha lea de la URL— toca todas las plataformas y no cabe aquí.
|
|
740
800
|
*/
|
|
801
|
+
/*
|
|
802
|
+
Abre la edición múltiple con las variantes de la familia ya cargadas.
|
|
803
|
+
|
|
804
|
+
Esa pantalla lee `multipleEditionList` de sessionStorage —así la deja el
|
|
805
|
+
listado al pulsar "editar varios"— y de cada producto solo usa id_article y
|
|
806
|
+
version. Se reproduce esa forma en vez de inventar otra vía de entrada.
|
|
807
|
+
|
|
808
|
+
Va SIN el producto padre a propósito, aunque estemos parados en su ficha: en
|
|
809
|
+
la edición múltiple no existe el diálogo de propagación, así que incluirlo
|
|
810
|
+
abriría un camino para cambiar el padre sin decidir si eso baja a los hijos
|
|
811
|
+
—justo la decisión que la ficha obliga a tomar—. Para editar el padre está su
|
|
812
|
+
propia pantalla.
|
|
813
|
+
*/
|
|
814
|
+
const openMultipleEdition = () => {
|
|
815
|
+
const variantes = (family?.variants ?? []).map((variant) => ({
|
|
816
|
+
id_article: variant.articleId,
|
|
817
|
+
version: variant.version ?? 1,
|
|
818
|
+
}));
|
|
819
|
+
|
|
820
|
+
if (!variantes.length) return;
|
|
821
|
+
|
|
822
|
+
try {
|
|
823
|
+
sessionStorage.setItem(
|
|
824
|
+
"multipleEditionList",
|
|
825
|
+
JSON.stringify(
|
|
826
|
+
variantes.sort((a, b) => a.id_article - b.id_article)
|
|
827
|
+
)
|
|
828
|
+
);
|
|
829
|
+
window.location.assign("/products/multipleEdition");
|
|
830
|
+
} catch (error) {
|
|
831
|
+
console.error("openMultipleEdition: ", error);
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
|
|
741
835
|
const openVariant = async (articleId) => {
|
|
742
836
|
setLoadingVariant(articleId);
|
|
743
837
|
try {
|
|
@@ -853,7 +947,10 @@ const ProviderProductEditionView = ({
|
|
|
853
947
|
try {
|
|
854
948
|
const res = await axios.post(
|
|
855
949
|
`${process.env.REACT_APP_VARIANTS_ENDPOINT}/restore`,
|
|
856
|
-
{
|
|
950
|
+
{
|
|
951
|
+
articleId: state.product.id_article,
|
|
952
|
+
attributes: [Number(attributeId)],
|
|
953
|
+
},
|
|
857
954
|
{ headers: { Authorization: token } }
|
|
858
955
|
);
|
|
859
956
|
|
|
@@ -929,7 +1026,7 @@ const ProviderProductEditionView = ({
|
|
|
929
1026
|
headers: {
|
|
930
1027
|
Authorization: token,
|
|
931
1028
|
},
|
|
932
|
-
}
|
|
1029
|
+
}
|
|
933
1030
|
);
|
|
934
1031
|
|
|
935
1032
|
const newStatuses = JSON.parse(res.data.body);
|
|
@@ -1180,10 +1277,13 @@ const ProviderProductEditionView = ({
|
|
|
1180
1277
|
const isProvider = !user.is_retailer;
|
|
1181
1278
|
state.services_data?.forEach((ret) => {
|
|
1182
1279
|
const { service, id_retailer } = ret;
|
|
1183
|
-
const currentEvalStatus =
|
|
1280
|
+
const currentEvalStatus =
|
|
1281
|
+
state.product.statusByRetailer[id_retailer]?.[service];
|
|
1184
1282
|
|
|
1185
|
-
if (isProvider && currentEvalStatus !== STATUS_DICTIONARY.AA.status)
|
|
1186
|
-
|
|
1283
|
+
if (isProvider && currentEvalStatus !== STATUS_DICTIONARY.AA.status)
|
|
1284
|
+
return;
|
|
1285
|
+
if (!isProvider && currentEvalStatus !== STATUS_DICTIONARY.AP.status)
|
|
1286
|
+
return;
|
|
1187
1287
|
|
|
1188
1288
|
const data = {
|
|
1189
1289
|
...dataGeneral,
|
|
@@ -1196,7 +1296,7 @@ const ProviderProductEditionView = ({
|
|
|
1196
1296
|
headers: {
|
|
1197
1297
|
Authorization: token,
|
|
1198
1298
|
},
|
|
1199
|
-
})
|
|
1299
|
+
})
|
|
1200
1300
|
);
|
|
1201
1301
|
});
|
|
1202
1302
|
|
|
@@ -1244,7 +1344,7 @@ const ProviderProductEditionView = ({
|
|
|
1244
1344
|
ArticleId: updatedProduct.id_article,
|
|
1245
1345
|
idCategory: updatedProduct.id_category,
|
|
1246
1346
|
product: updatedProduct,
|
|
1247
|
-
})
|
|
1347
|
+
})
|
|
1248
1348
|
);
|
|
1249
1349
|
|
|
1250
1350
|
// Mostrar modal de éxito
|
|
@@ -1323,6 +1423,18 @@ const ProviderProductEditionView = ({
|
|
|
1323
1423
|
jwt={token}
|
|
1324
1424
|
/>
|
|
1325
1425
|
)}
|
|
1426
|
+
{pendingPropagation && (
|
|
1427
|
+
<PropagateChangesModal
|
|
1428
|
+
changedAttributes={pendingPropagation.cambios}
|
|
1429
|
+
variants={(family?.variants ?? []).filter((v) => !v.isCurrent)}
|
|
1430
|
+
saving={state.saving}
|
|
1431
|
+
onCancel={() => setPendingPropagation(null)}
|
|
1432
|
+
onConfirm={(propagation) => {
|
|
1433
|
+
setPendingPropagation(null);
|
|
1434
|
+
saveDatasheets(token, propagation ?? undefined);
|
|
1435
|
+
}}
|
|
1436
|
+
/>
|
|
1437
|
+
)}
|
|
1326
1438
|
{showLinkVariants && (
|
|
1327
1439
|
<LinkVariantsModal
|
|
1328
1440
|
articleId={state.product?.id_article}
|
|
@@ -1418,7 +1530,7 @@ const ProviderProductEditionView = ({
|
|
|
1418
1530
|
size={12}
|
|
1419
1531
|
onClick={async () => {
|
|
1420
1532
|
const elements = document.querySelectorAll(
|
|
1421
|
-
"#modal-message-box .ql-container .ql-editor > p"
|
|
1533
|
+
"#modal-message-box .ql-container .ql-editor > p"
|
|
1422
1534
|
);
|
|
1423
1535
|
|
|
1424
1536
|
if (!elements || elements.length === 0) {
|
|
@@ -1435,7 +1547,7 @@ const ProviderProductEditionView = ({
|
|
|
1435
1547
|
|
|
1436
1548
|
if (isMessageEmpty) {
|
|
1437
1549
|
const container = document.querySelector(
|
|
1438
|
-
".container-customComponent"
|
|
1550
|
+
".container-customComponent"
|
|
1439
1551
|
);
|
|
1440
1552
|
const existingAlert =
|
|
1441
1553
|
container.querySelector(".alert-error");
|
|
@@ -1601,7 +1713,9 @@ const ProviderProductEditionView = ({
|
|
|
1601
1713
|
<button
|
|
1602
1714
|
key={variant.articleId}
|
|
1603
1715
|
type="button"
|
|
1604
|
-
className={`family-row${
|
|
1716
|
+
className={`family-row${
|
|
1717
|
+
variant.isCurrent ? " current" : ""
|
|
1718
|
+
}`}
|
|
1605
1719
|
disabled={variant.isCurrent || loadingVariant !== null}
|
|
1606
1720
|
onClick={() => openVariant(variant.articleId)}
|
|
1607
1721
|
>
|
|
@@ -1620,6 +1734,18 @@ const ProviderProductEditionView = ({
|
|
|
1620
1734
|
{family && !family.error && !family.variants?.length && (
|
|
1621
1735
|
<p className="loading">Este producto no tiene variantes.</p>
|
|
1622
1736
|
)}
|
|
1737
|
+
|
|
1738
|
+
{/* Editarlas juntas evita abrir seis fichas para llenar lo
|
|
1739
|
+
mismo seis veces, que es el caso real de una familia. */}
|
|
1740
|
+
{family?.variants?.length > 1 && (
|
|
1741
|
+
<button
|
|
1742
|
+
type="button"
|
|
1743
|
+
className="editar-juntas"
|
|
1744
|
+
onClick={openMultipleEdition}
|
|
1745
|
+
>
|
|
1746
|
+
Editar las {family.variants.length} variantes juntas
|
|
1747
|
+
</button>
|
|
1748
|
+
)}
|
|
1623
1749
|
</div>
|
|
1624
1750
|
)}
|
|
1625
1751
|
<FullProductNameHeader
|
|
@@ -1754,7 +1880,7 @@ const ProviderProductEditionView = ({
|
|
|
1754
1880
|
handleOnUpdateApprovedInputs
|
|
1755
1881
|
}
|
|
1756
1882
|
/>
|
|
1757
|
-
)
|
|
1883
|
+
)
|
|
1758
1884
|
)
|
|
1759
1885
|
) : (
|
|
1760
1886
|
<ScreenHeader
|
|
@@ -253,5 +253,18 @@ export const Container = styled.div`
|
|
|
253
253
|
font-size: 11px;
|
|
254
254
|
color: ${GlobalColors.gray};
|
|
255
255
|
}
|
|
256
|
+
|
|
257
|
+
.editar-juntas {
|
|
258
|
+
align-self: flex-start;
|
|
259
|
+
margin-top: 4px;
|
|
260
|
+
border: 1px solid ${PINK};
|
|
261
|
+
border-radius: 6px;
|
|
262
|
+
background: none;
|
|
263
|
+
padding: 6px 12px;
|
|
264
|
+
cursor: pointer;
|
|
265
|
+
font-family: ${FontFamily.Raleway_600};
|
|
266
|
+
font-size: 11px;
|
|
267
|
+
color: ${PINK};
|
|
268
|
+
}
|
|
256
269
|
}
|
|
257
270
|
`;
|
package/src/index.js
CHANGED
|
@@ -88,6 +88,7 @@ export * from "./components/organisms/ImagePreviewer/index";
|
|
|
88
88
|
export * from "./components/organisms/ImagesGroup/index";
|
|
89
89
|
export * from "./components/organisms/InputGroup/index";
|
|
90
90
|
export * from "./components/organisms/LinkVariantsModal/index";
|
|
91
|
+
export * from "./components/organisms/PropagateChangesModal/index";
|
|
91
92
|
export * from "./components/organisms/ProductImageModal/index";
|
|
92
93
|
export * from "./components/organisms/Chat/index";
|
|
93
94
|
export * from "./components/organisms/Modal/index";
|