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.
- package/dist/components/atoms/ProgressBar/index.js +1 -1
- package/dist/components/atoms/ProgressBar/styles.js +4 -4
- package/dist/components/atoms/Status/index.js +16 -1
- package/dist/components/atoms/Status/styles.js +1 -1
- package/dist/components/organisms/ChangeStatusModal/index.js +166 -53
- package/dist/components/organisms/ChangeStatusModal/styles.js +12 -8
- package/dist/components/pages/ProviderProductEdition/context/provider-product-edition.context.js +3 -1
- package/dist/components/pages/ProviderProductEdition/index.js +65 -36
- package/dist/components/pages/ProviderProductEdition/utils.js +3 -1
- package/dist/components/pages/RetailerProductEdition/context/reducers/product.js +11 -19
- package/dist/components/pages/RetailerProductEdition/index.js +16 -10
- package/dist/components/pages/RetailerProductEdition/utils.js +1 -1
- package/dist/contexts/AiProductEdition.js +34 -22
- package/dist/global-files/statusDictionary.js +36 -1
- package/package.json +1 -1
- package/src/components/atoms/ProgressBar/index.js +2 -6
- package/src/components/atoms/ProgressBar/styles.js +4 -58
- package/src/components/atoms/Status/index.js +11 -3
- package/src/components/atoms/Status/styles.js +113 -0
- package/src/components/organisms/ChangeStatusModal/index.jsx +103 -29
- package/src/components/organisms/ChangeStatusModal/styles.js +20 -0
- package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx +1 -0
- package/src/components/pages/ProviderProductEdition/index.js +40 -14
- package/src/components/pages/ProviderProductEdition/utils.js +5 -1
- package/src/components/pages/RetailerProductEdition/context/reducers/product.js +4 -20
- package/src/components/pages/RetailerProductEdition/index.js +20 -16
- package/src/components/pages/RetailerProductEdition/utils.js +1 -1
- package/src/contexts/AiProductEdition.jsx +22 -13
- 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: ${
|
|
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: ${
|
|
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" :
|
|
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
|
-
|
|
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
|
|
75
|
-
|
|
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
|
-
|
|
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
|
-
<
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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%;
|
package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx
CHANGED
|
@@ -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
|
|
720
|
+
const retailerId = state.active_retailer?.id_retailer;
|
|
707
721
|
const evalStatus =
|
|
708
|
-
state.product[
|
|
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
|
-
|
|
738
|
-
|
|
739
|
-
|
|
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
|
-
|
|
973
|
-
|
|
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:
|
|
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.
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
}
|