contentoh-components-library 21.6.0 → 21.6.11

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 (29) hide show
  1. package/dist/components/atoms/ProgressBar/index.js +1 -1
  2. package/dist/components/atoms/ProgressBar/styles.js +4 -4
  3. package/dist/components/atoms/Status/index.js +16 -1
  4. package/dist/components/atoms/Status/styles.js +1 -1
  5. package/dist/components/organisms/ChangeStatusModal/index.js +166 -53
  6. package/dist/components/organisms/ChangeStatusModal/styles.js +12 -8
  7. package/dist/components/pages/ProviderProductEdition/context/provider-product-edition.context.js +3 -1
  8. package/dist/components/pages/ProviderProductEdition/index.js +65 -36
  9. package/dist/components/pages/ProviderProductEdition/utils.js +3 -1
  10. package/dist/components/pages/RetailerProductEdition/context/reducers/product.js +11 -19
  11. package/dist/components/pages/RetailerProductEdition/index.js +16 -10
  12. package/dist/components/pages/RetailerProductEdition/utils.js +1 -1
  13. package/dist/contexts/AiProductEdition.js +34 -22
  14. package/dist/global-files/statusDictionary.js +36 -1
  15. package/package.json +1 -1
  16. package/src/components/atoms/ProgressBar/index.js +2 -6
  17. package/src/components/atoms/ProgressBar/styles.js +4 -58
  18. package/src/components/atoms/Status/index.js +11 -3
  19. package/src/components/atoms/Status/styles.js +113 -0
  20. package/src/components/organisms/ChangeStatusModal/index.jsx +103 -29
  21. package/src/components/organisms/ChangeStatusModal/styles.js +20 -0
  22. package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx +1 -0
  23. package/src/components/pages/ProviderProductEdition/index.js +40 -14
  24. package/src/components/pages/ProviderProductEdition/utils.js +5 -1
  25. package/src/components/pages/RetailerProductEdition/context/reducers/product.js +4 -20
  26. package/src/components/pages/RetailerProductEdition/index.js +20 -16
  27. package/src/components/pages/RetailerProductEdition/utils.js +1 -1
  28. package/src/contexts/AiProductEdition.jsx +22 -13
  29. package/src/global-files/statusDictionary.js +31 -1
@@ -2,7 +2,8 @@ import styled from "styled-components";
2
2
  import { FontFamily, GlobalColors } from "../../../global-files/variables";
3
3
 
4
4
  export const Container = styled.div`
5
- background-color: ${GlobalColors.s3};
5
+ background-color: ${(props) =>
6
+ props.percentageRequired >= 100 ? GlobalColors.color_pink : GlobalColors.s3};
6
7
  width: fit-content;
7
8
  height: 27px;
8
9
  padding: 4px;
@@ -11,62 +12,7 @@ export const Container = styled.div`
11
12
  font-weight: 600;
12
13
  font-size: 14px;
13
14
  line-height: 19px;
14
- color: ${(backgroundColor) =>
15
- backgroundColor === "s2" || backgroundColor === "s1"
16
- ? GlobalColors.s4
17
- : GlobalColors.white};
18
-
19
- &.status-CA,
20
- &.status-IE {
21
- background-color: ${GlobalColors.in_progress};
22
- }
23
-
24
- &.status-R,
25
- &.status-AS,
26
- &.status-PA {
27
- background-color: ${GlobalColors.reception};
28
- }
29
-
30
- &.status-AA,
31
- &.status-AP,
32
- &.status-ACA,
33
- &.status-AC {
34
- background-color: ${GlobalColors.finished};
35
- }
36
-
37
- &.status-RA,
38
- &.status-RC,
39
- &.status-RP,
40
- &.status-RCA {
41
- background-color: ${GlobalColors.rejected_status};
42
- }
43
-
44
- &.status-Dat,
45
- &.status-Dsc,
46
- &.status-Imgs {
47
- background-color: ${GlobalColors.s4};
48
- }
49
-
50
- &.status-Ex {
51
- background-color: ${GlobalColors.exported};
52
- }
53
-
54
- &.status-DDI {
55
- background-color: ${GlobalColors.original_purpura};
56
- }
57
-
58
- &.status-GLD {
59
- background-color: ${GlobalColors.in_progress};
60
- }
61
-
62
- &.status-TAB {
63
- background-color: ${GlobalColors.deep_gray};
64
- }
65
-
66
- &.status-Pt {
67
- background-color: ${GlobalColors.s2};
68
- color: ${GlobalColors.s4};
69
- }
15
+ color: ${GlobalColors.white};
70
16
  `;
71
17
  export const ContainerIcon = styled.div`
72
18
  cursor: pointer;
@@ -89,6 +35,6 @@ export const ContainerIcon = styled.div`
89
35
  ${(props) => (props.percentageRequired < 100 ? 0 : 1)},
90
36
  "wght" 400, "GRAD" 0, "opsz" 48;
91
37
  color: ${(props) =>
92
- props.percentageRequired < 100 ? "#d4d1d7" : "#e33aa9"};
38
+ props.percentageRequired < 100 ? "#d4d1d7" : GlobalColors.color_pink};
93
39
  }
94
40
  `;
@@ -1,11 +1,19 @@
1
1
  import { Container } from "./styles";
2
+ import { STATUS_DICTIONARY } from "../../../global-files/statusDictionary";
3
+
4
+ const getStatusName = (statusType) => {
5
+ if (!statusType) return null;
6
+ const parts = statusType.split("/");
7
+ const names = parts.map((key) => STATUS_DICTIONARY[key]?.name).filter(Boolean);
8
+ return names.length > 0 ? names.join(" / ") : null;
9
+ };
2
10
 
3
11
  export const Status = ({ statusType, ovalForm }) => {
12
+ const tooltipLabel = getStatusName(statusType);
4
13
  return (
5
14
  <Container
6
- className={`status-${statusType?.replace(/\/.*/, "")} ${
7
- ovalForm && "oval-form"
8
- }`}
15
+ className={`status-${statusType?.replace(/\/.*/, "")} ${ovalForm ? "oval-form" : ""}`}
16
+ data-tooltip={tooltipLabel}
9
17
  >
10
18
  <p>{statusType ?? "NS"}</p>
11
19
  </Container>
@@ -2,11 +2,13 @@ import styled from "styled-components";
2
2
  import { FontFamily, GlobalColors } from "../../../global-files/variables";
3
3
 
4
4
  export const Container = styled.div`
5
+ position: relative;
5
6
  width: fit-content;
6
7
  padding: 0 10px;
7
8
  height: 20px;
8
9
  background-color: ${GlobalColors.s3};
9
10
  border-radius: 3px;
11
+ cursor: default;
10
12
 
11
13
  p {
12
14
  text-align: center;
@@ -16,6 +18,117 @@ export const Container = styled.div`
16
18
  line-height: 20px;
17
19
  }
18
20
 
21
+ &[data-tooltip]::after {
22
+ content: attr(data-tooltip);
23
+ position: absolute;
24
+ bottom: calc(100% + 7px);
25
+ left: 50%;
26
+ transform: translateX(-50%) translateY(4px);
27
+ background-color: ${GlobalColors.s3};
28
+ color: ${GlobalColors.white};
29
+ font-family: ${FontFamily.Lato};
30
+ font-size: 11px;
31
+ font-weight: 600;
32
+ padding: 4px 10px;
33
+ border-radius: 6px;
34
+ white-space: nowrap;
35
+ z-index: 200;
36
+ pointer-events: none;
37
+ opacity: 0;
38
+ visibility: hidden;
39
+ transition: opacity 0.18s ease, transform 0.18s ease;
40
+ }
41
+
42
+ &[data-tooltip]::before {
43
+ content: "";
44
+ position: absolute;
45
+ bottom: calc(100% + 1px);
46
+ left: 50%;
47
+ transform: translateX(-50%) translateY(4px);
48
+ border: 6px solid transparent;
49
+ border-top-color: ${GlobalColors.s3};
50
+ z-index: 200;
51
+ pointer-events: none;
52
+ opacity: 0;
53
+ visibility: hidden;
54
+ transition: opacity 0.18s ease, transform 0.18s ease;
55
+ }
56
+
57
+ &[data-tooltip]:hover::after,
58
+ &[data-tooltip]:hover::before {
59
+ opacity: 1;
60
+ visibility: visible;
61
+ transform: translateX(-50%) translateY(0);
62
+ }
63
+
64
+ &.status-CA[data-tooltip]::after,
65
+ &.status-IE[data-tooltip]::after {
66
+ background-color: ${GlobalColors.in_progress};
67
+ }
68
+ &.status-CA[data-tooltip]::before,
69
+ &.status-IE[data-tooltip]::before {
70
+ border-top-color: ${GlobalColors.in_progress};
71
+ }
72
+
73
+ &.status-R[data-tooltip]::after,
74
+ &.status-AS[data-tooltip]::after,
75
+ &.status-SAC[data-tooltip]::after,
76
+ &.status-PA[data-tooltip]::after {
77
+ background-color: ${GlobalColors.reception};
78
+ }
79
+ &.status-R[data-tooltip]::before,
80
+ &.status-AS[data-tooltip]::before,
81
+ &.status-SAC[data-tooltip]::before,
82
+ &.status-PA[data-tooltip]::before {
83
+ border-top-color: ${GlobalColors.reception};
84
+ }
85
+
86
+ &.status-AA[data-tooltip]::after,
87
+ &.status-AP[data-tooltip]::after,
88
+ &.status-AC[data-tooltip]::after,
89
+ &.status-AAC[data-tooltip]::after,
90
+ &.status-ACA[data-tooltip]::after {
91
+ background-color: ${GlobalColors.finished};
92
+ }
93
+ &.status-AA[data-tooltip]::before,
94
+ &.status-AP[data-tooltip]::before,
95
+ &.status-AC[data-tooltip]::before,
96
+ &.status-AAC[data-tooltip]::before,
97
+ &.status-ACA[data-tooltip]::before {
98
+ border-top-color: ${GlobalColors.finished};
99
+ }
100
+
101
+ &.status-RA[data-tooltip]::after,
102
+ &.status-RC[data-tooltip]::after,
103
+ &.status-RP[data-tooltip]::after,
104
+ &.status-RAC[data-tooltip]::after,
105
+ &.status-RCA[data-tooltip]::after {
106
+ background-color: ${GlobalColors.rejected_status};
107
+ }
108
+ &.status-RA[data-tooltip]::before,
109
+ &.status-RC[data-tooltip]::before,
110
+ &.status-RP[data-tooltip]::before,
111
+ &.status-RAC[data-tooltip]::before,
112
+ &.status-RCA[data-tooltip]::before {
113
+ border-top-color: ${GlobalColors.rejected_status};
114
+ }
115
+
116
+ &.status-FAP[data-tooltip]::after,
117
+ &.status-Ex[data-tooltip]::after {
118
+ background-color: ${GlobalColors.exported};
119
+ }
120
+ &.status-FAP[data-tooltip]::before,
121
+ &.status-Ex[data-tooltip]::before {
122
+ border-top-color: ${GlobalColors.exported};
123
+ }
124
+
125
+ &.status-DDI[data-tooltip]::after {
126
+ background-color: ${GlobalColors.original_purpura};
127
+ }
128
+ &.status-DDI[data-tooltip]::before {
129
+ border-top-color: ${GlobalColors.original_purpura};
130
+ }
131
+
19
132
  &.status-CA,
20
133
  &.status-IE {
21
134
  background-color: ${GlobalColors.in_progress};
@@ -31,6 +31,8 @@ import {
31
31
  ScopeButton,
32
32
  HelperText,
33
33
  StatusGrid,
34
+ StatusGridWrapper,
35
+ StatusGridOverlay,
34
36
  StatusPill,
35
37
  StyledTextArea,
36
38
  StyledFormControl,
@@ -42,15 +44,6 @@ import {
42
44
  } from "./styles";
43
45
  import axios from "axios";
44
46
 
45
- const statusOptions = [
46
- { value: "PA", label: "Por Asignar" },
47
- { value: "AS", label: "Asignado" },
48
- { value: "AC", label: "Aprobado Coordinador" },
49
- { value: "AP", label: "Aprobado Proveedor" },
50
- { value: "R", label: "Rechazado" },
51
- { value: "RP", label: "Rechazo Pendiente" },
52
- ];
53
-
54
47
  const availableServices = ["description", "datasheet", "images"];
55
48
 
56
49
  const ChangeStatusModal = ({
@@ -71,8 +64,68 @@ const ChangeStatusModal = ({
71
64
 
72
65
  const [currentStatusObj, setCurrentStatusObj] = useState({});
73
66
 
74
- const isStatusValid =
75
- newStatus !== "" && newStatus !== currentStatusObj.label;
67
+ const getServiceStatusStr = (retailerId, service) => {
68
+ const sbyR = state?.product?.statusByRetailer;
69
+ if (!sbyR) return null;
70
+ if (Array.isArray(sbyR)) {
71
+ return sbyR.find((item) => item.retailer_id === retailerId && item.service === service)?.status ?? null;
72
+ }
73
+ return sbyR[retailerId]?.[service] ?? null;
74
+ };
75
+
76
+ const serviceStatusObj = (() => {
77
+ if (scope !== "service" || selectedChains.length !== 1 || selectedServices.length !== 1) return null;
78
+ const statusStr = getServiceStatusStr(selectedChains[0], selectedServices[0]);
79
+ const statusKey = statusStr?.split("/").pop();
80
+ return statusKey ? STATUS_DICTIONARY[statusKey] : null;
81
+ })();
82
+
83
+ // Statuses for multi-service/chain selection (when not exactly 1+1)
84
+ const multiServiceStatuses = (() => {
85
+ if (scope !== "service" || selectedChains.length === 0 || selectedServices.length === 0) return [];
86
+ if (selectedChains.length === 1 && selectedServices.length === 1) return [];
87
+ const results = [];
88
+ for (const chainId of selectedChains) {
89
+ const chainName = availableRetailers.find((r) => r.id_retailer === chainId)?.name ?? chainId;
90
+ for (const service of selectedServices) {
91
+ const statusStr = getServiceStatusStr(chainId, service);
92
+ const statusKey = statusStr?.split("/").pop();
93
+ const statusObj = statusKey ? STATUS_DICTIONARY[statusKey] : null;
94
+ if (statusObj) {
95
+ results.push({ chainId, chainName, service, statusName: statusObj.name });
96
+ }
97
+ }
98
+ }
99
+ return results;
100
+ })();
101
+
102
+ // If all selected services share the same status, block it; otherwise null
103
+ const multiAllSameStatus = (() => {
104
+ if (multiServiceStatuses.length === 0) return null;
105
+ const names = [...new Set(multiServiceStatuses.map((s) => s.statusName))];
106
+ return names.length === 1 ? names[0] : null;
107
+ })();
108
+
109
+ // Map statusName -> owner labels to show below each pill when statuses differ
110
+ const statusOwnerMap = (() => {
111
+ if (multiServiceStatuses.length === 0 || multiAllSameStatus !== null) return {};
112
+ const serviceLabel = (service) =>
113
+ service === "description" ? "Descripciones" : service === "datasheet" ? "Ficha Técnica" : "Imágenes";
114
+ return multiServiceStatuses.reduce((acc, item) => {
115
+ if (!acc[item.statusName]) acc[item.statusName] = [];
116
+ const label = selectedChains.length > 1
117
+ ? `${item.chainName}: ${serviceLabel(item.service)}`
118
+ : serviceLabel(item.service);
119
+ acc[item.statusName].push(label);
120
+ return acc;
121
+ }, {});
122
+ })();
123
+
124
+ const disabledStatusName = scope === "service"
125
+ ? serviceStatusObj?.name ?? multiAllSameStatus ?? null
126
+ : currentStatusObj?.name;
127
+
128
+ const isStatusValid = newStatus !== "" && newStatus !== disabledStatusName;
76
129
  const isCommentValid = comment.trim().length > 0;
77
130
 
78
131
  let isScopeValid = false;
@@ -157,7 +210,8 @@ const ChangeStatusModal = ({
157
210
 
158
211
  useEffect(() => {
159
212
  if (!state) return;
160
- setCurrentStatusObj(STATUS_DICTIONARY[state?.product?.status]);
213
+ const statusKey = state?.product?.status?.split("/").pop();
214
+ setCurrentStatusObj(STATUS_DICTIONARY[statusKey]);
161
215
 
162
216
  setAvailableRetailers(state?.product?.categoryRetailerInOrder || []);
163
217
  }, [state]);
@@ -381,9 +435,9 @@ const ChangeStatusModal = ({
381
435
  )}
382
436
 
383
437
  <Section>
384
- <SectionTitle>Estatus actual:</SectionTitle>
438
+ <SectionTitle>Estatus actual del producto:</SectionTitle>
385
439
  <StatusPill
386
- label={currentStatusObj?.name}
440
+ label={serviceStatusObj?.name ?? multiAllSameStatus ?? currentStatusObj?.name}
387
441
  selected={false}
388
442
  disabled={true}
389
443
  />
@@ -391,20 +445,40 @@ const ChangeStatusModal = ({
391
445
 
392
446
  <Section>
393
447
  <SectionTitle>Nuevo estatus:</SectionTitle>
394
- <StatusGrid>
395
- {Object.values(STATUS_DICTIONARY).map((status) => (
396
- <StatusPill
397
- key={status.name}
398
- label={status.name}
399
- disabled={status.name === currentStatusObj?.name}
400
- selected={status.name === newStatus}
401
- onClick={() =>
402
- status.name !== currentStatusObj?.name &&
403
- setNewStatus(status.name)
404
- }
405
- />
406
- ))}
407
- </StatusGrid>
448
+ <StatusGridWrapper>
449
+ <StatusGrid>
450
+ {Object.values(STATUS_DICTIONARY).map((status) => {
451
+ const ownerLabels = statusOwnerMap[status.name];
452
+ return (
453
+ <div
454
+ key={status.name}
455
+ style={{ display: "flex", flexDirection: "column", alignItems: "flex-start", gap: 4 }}
456
+ >
457
+ <StatusPill
458
+ label={status.name}
459
+ disabled={status.name === disabledStatusName}
460
+ selected={status.name === newStatus}
461
+ onClick={() =>
462
+ status.name !== disabledStatusName && setNewStatus(status.name)
463
+ }
464
+ />
465
+ {ownerLabels?.length > 0 && (
466
+ <span style={{ fontSize: "0.68rem", color: colors.primary, fontFamily: "Raleway, sans-serif", paddingLeft: 2 }}>
467
+ {ownerLabels.join(", ")}
468
+ </span>
469
+ )}
470
+ </div>
471
+ );
472
+ })}
473
+ </StatusGrid>
474
+ {!isScopeValid && (
475
+ <StatusGridOverlay>
476
+ {scope === "retailer"
477
+ ? "Selecciona una cadena para continuar"
478
+ : "Selecciona una cadena y un servicio para continuar"}
479
+ </StatusGridOverlay>
480
+ )}
481
+ </StatusGridWrapper>
408
482
  </Section>
409
483
 
410
484
  <Section>
@@ -431,7 +505,7 @@ const ChangeStatusModal = ({
431
505
  <span className="summary-title">Resumen de impacto:</span>
432
506
  <div className="status-flow">
433
507
  <StatusPill
434
- label={currentStatusObj?.name}
508
+ label={serviceStatusObj?.name ?? multiAllSameStatus ?? currentStatusObj?.name}
435
509
  selected={false}
436
510
  disabled={true}
437
511
  size="small"
@@ -181,6 +181,26 @@ export const StatusGrid = styled(Box)`
181
181
  gap: 12px;
182
182
  `;
183
183
 
184
+ export const StatusGridWrapper = styled(Box)`
185
+ position: relative;
186
+ `;
187
+
188
+ export const StatusGridOverlay = styled(Box)`
189
+ position: absolute;
190
+ inset: -8px -4px;
191
+ background: rgba(255, 255, 255, 0.82);
192
+ backdrop-filter: blur(1px);
193
+ border-radius: 8px;
194
+ display: flex;
195
+ align-items: center;
196
+ justify-content: center;
197
+ font-family: "Raleway", sans-serif;
198
+ font-size: 13px;
199
+ font-weight: 600;
200
+ color: rgba(0, 0, 0, 0.45);
201
+ pointer-events: none;
202
+ `;
203
+
184
204
  export const StyledTextArea = styled(TextField)`
185
205
  && {
186
206
  width: 100%;
@@ -6,6 +6,7 @@ import {
6
6
  ACTIONS,
7
7
  } from "./provider-product-edition.reducer";
8
8
  import axios from "axios";
9
+ import { getConceptByTab } from "../utils";
9
10
  import successIcon from "../../../../assets/images/genericModal/genericModalCheck.svg";
10
11
  import errorIcon from "../../../../assets/images/genericModal/errorModal.svg";
11
12
  import warningIcon from "../../../../assets/images/genericModal/genericModalWarning.svg";
@@ -9,6 +9,7 @@ import {
9
9
  useProviderProductEdition,
10
10
  } from "./context/provider-product-edition.context";
11
11
  import { normalizeProduct, getConceptByTab } from "./utils";
12
+ import { getMinorStatus, getMinorStatusFromRetailerMap, STATUS_DICTIONARY } from "../../../global-files/statusDictionary";
12
13
 
13
14
  import {
14
15
  getPercentage,
@@ -269,11 +270,24 @@ const ProviderProductEditionView = ({
269
270
  {},
270
271
  );
271
272
 
273
+ const getServiceMinorStatus = (serviceName) => {
274
+ const records = servicesDataRes.filter((s) => s.service === serviceName);
275
+ return records.length > 0 ? getMinorStatus(records.map((s) => s.status)) : undefined;
276
+ };
277
+
278
+ const imagesMinorStatus = getServiceMinorStatus("images");
279
+ const descriptionMinorStatus = getServiceMinorStatus("description");
280
+ const datasheetMinorStatus = getServiceMinorStatus("datasheet");
281
+
272
282
  dispatch({
273
283
  type: "SET_PRODUCT",
274
284
  payload: {
275
285
  ...state.product,
276
286
  statusByRetailer: updatedStatusByRetailer,
287
+ status: getMinorStatusFromRetailerMap(updatedStatusByRetailer),
288
+ ...(imagesMinorStatus !== undefined && { images_status: imagesMinorStatus }),
289
+ ...(descriptionMinorStatus !== undefined && { description_status: descriptionMinorStatus }),
290
+ ...(datasheetMinorStatus !== undefined && { datasheet_status: datasheetMinorStatus }),
277
291
  },
278
292
  });
279
293
 
@@ -703,14 +717,14 @@ const ProviderProductEditionView = ({
703
717
  const concept = getConceptByTab(state.active_tab);
704
718
  const articleId = state.product.id_article;
705
719
  const orderId = state.product.id_order ?? state.product.orderId;
706
- const sectionStatusKey = `${concept}_status`;
720
+ const retailerId = state.active_retailer?.id_retailer;
707
721
  const evalStatus =
708
- state.product[sectionStatusKey] || state.product?.version_status;
722
+ state.product.statusByRetailer?.[retailerId]?.[concept] ||
723
+ state.product[`${concept}_status`] ||
724
+ state.product?.version_status;
709
725
 
710
726
  let data = { articleId, orderId, concept, evalStatus };
711
727
 
712
- const retailerId = state.active_retailer?.id_retailer;
713
-
714
728
  try {
715
729
  if (result) {
716
730
  data.result = result;
@@ -731,15 +745,19 @@ const ProviderProductEditionView = ({
731
745
  newStatuses.newServiceStatus[articleId][`${concept}Status`];
732
746
 
733
747
  // Actualizar el producto con los nuevos estados
748
+ const updatedStatusByRetailer = {
749
+ ...state.product.statusByRetailer,
750
+ [retailerId]: {
751
+ ...state.product.statusByRetailer[retailerId],
752
+ [concept]: newStatuses?.newStatus ?? serviceStatus,
753
+ },
754
+ };
734
755
  const updatedProduct = {
735
756
  ...state.product,
736
- statusByRetailer: {
737
- ...state.product.statusByRetailer,
738
- [retailerId]: {
739
- ...state.product.statusByRetailer[retailerId],
740
- [concept]: newStatuses?.newStatus ?? serviceStatus,
741
- },
742
- },
757
+ statusByRetailer: updatedStatusByRetailer,
758
+ status: getMinorStatus(
759
+ Object.values(updatedStatusByRetailer).flatMap(Object.values)
760
+ ),
743
761
  };
744
762
 
745
763
  const updatedServicesData = state.services_data?.map((service) => ({
@@ -967,14 +985,19 @@ const ProviderProductEditionView = ({
967
985
  };
968
986
 
969
987
  // Crear todas las evaluaciones para cada servicio y retailer
988
+ const isProvider = !user.is_retailer;
970
989
  state.services_data?.forEach((ret) => {
971
990
  const { service, id_retailer } = ret;
972
- let data = {};
973
- data = {
991
+ const currentEvalStatus = state.product.statusByRetailer[id_retailer]?.[service];
992
+
993
+ if (isProvider && currentEvalStatus !== STATUS_DICTIONARY.AA.status) return;
994
+ if (!isProvider && currentEvalStatus !== STATUS_DICTIONARY.AP.status) return;
995
+
996
+ const data = {
974
997
  ...dataGeneral,
975
998
  concept: service,
976
999
  retailerId: id_retailer,
977
- evalStatus: state.product.statusByRetailer[id_retailer][service],
1000
+ evalStatus: currentEvalStatus,
978
1001
  };
979
1002
  evaluationArray.push(
980
1003
  axios.put(`${process.env.REACT_APP_EVALUATION_ENDPOINT}`, data, {
@@ -1005,6 +1028,9 @@ const ProviderProductEditionView = ({
1005
1028
  const updatedProduct = {
1006
1029
  ...state.product,
1007
1030
  article_status: status,
1031
+ status: getMinorStatus(
1032
+ Object.values(updatedStatusByRetailer).flatMap(Object.values)
1033
+ ),
1008
1034
  datasheet_status:
1009
1035
  state.product.datasheet_status === "NA" ? "NA" : status,
1010
1036
  description_status:
@@ -1,3 +1,5 @@
1
+ import { getMinorStatusFromRetailerMap } from "../../../global-files/statusDictionary";
2
+
1
3
  export const normalizeProduct = (product) => {
2
4
  // Handle case where product might be wrapped in a product property
3
5
  const productData = product.product || product;
@@ -44,7 +46,9 @@ export const normalizeProduct = (product) => {
44
46
 
45
47
  // from tasks
46
48
  id_order: productData.orderId || 0,
47
- status: productData.status || null,
49
+ status: productData.statusByRetailer
50
+ ? getMinorStatusFromRetailerMap(productData.statusByRetailer)
51
+ : productData.status || null,
48
52
  datasheet_status: productData.datasheet_status || null,
49
53
  description_status: productData.description_status || null,
50
54
  images_status: productData.images_status || null,
@@ -1,4 +1,4 @@
1
- import { STATUS_DICTIONARY } from "../../../../../global-files/statusDictionary";
1
+ import { STATUS_DICTIONARY, getMinorStatus } from "../../../../../global-files/statusDictionary";
2
2
 
3
3
  export const productInitialState = {
4
4
  product: null,
@@ -92,23 +92,7 @@ export const productReducer = (state, action) => {
92
92
  }
93
93
  };
94
94
 
95
- function getMinorStatus(servicesStatus = []) {
96
- if (!servicesStatus || servicesStatus.length === 0)
97
- return STATUS_DICTIONARY.NS.name;
98
-
99
- console.log({ servicesStatus });
100
-
101
- const winner = servicesStatus.reduce((minor, current) => {
102
- const currentObj =
103
- typeof current === "string" ? STATUS_DICTIONARY[current] : current;
104
- const minorObj =
105
- typeof minor === "string" ? STATUS_DICTIONARY[minor] : minor;
106
-
107
- if (!currentObj || typeof currentObj.weight === "undefined") return minor;
108
- if (!minorObj || typeof minorObj.weight === "undefined") return current;
109
-
110
- return currentObj.weight < minorObj.weight ? currentObj : minorObj;
111
- }, servicesStatus[0] || STATUS_DICTIONARY.NS);
112
-
113
- return winner?.status || STATUS_DICTIONARY.NS?.status;
95
+ // Wrapper for array format: [{ status: "AS" }, ...]
96
+ export function getMinorStatusFromRetailer(statusByRetailer = []) {
97
+ return getMinorStatus(statusByRetailer.map((s) => s?.status));
114
98
  }