contentoh-components-library 21.5.84 → 21.5.86
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/GeneralButton/styles.js +1 -1
- package/dist/components/atoms/GeneralInput/index.js +4 -2
- package/dist/components/molecules/TagAndInput/index.js +2 -2
- package/dist/components/organisms/ChangeStatusModal/index.js +531 -0
- package/dist/components/organisms/ChangeStatusModal/styles.js +85 -0
- package/dist/components/pages/RetailerProductEdition/RetailerProductEdition.stories.js +108 -231
- package/dist/components/pages/RetailerProductEdition/context/reducers/product.js +48 -2
- package/dist/components/pages/RetailerProductEdition/index.js +329 -101
- package/dist/components/pages/RetailerProductEdition/styles.js +1 -1
- package/dist/global-files/statusDictionary.js +103 -0
- package/package.json +1 -1
- package/src/components/atoms/GeneralButton/styles.js +4 -0
- package/src/components/atoms/GeneralInput/index.js +9 -8
- package/src/components/molecules/TagAndInput/index.js +2 -5
- package/src/components/organisms/ChangeStatusModal/index.jsx +488 -0
- package/src/components/organisms/ChangeStatusModal/styles.js +333 -0
- package/src/components/pages/RetailerProductEdition/RetailerProductEdition.stories.js +107 -259
- package/src/components/pages/RetailerProductEdition/context/reducers/product.js +55 -0
- package/src/components/pages/RetailerProductEdition/index.js +236 -78
- package/src/components/pages/RetailerProductEdition/styles.js +6 -0
- package/src/contexts/AiProductEdition.jsx +1 -0
- package/src/global-files/statusDictionary.js +103 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var STATUS_DICTIONARY = {
|
|
4
|
+
// R: {
|
|
5
|
+
// status: "R",
|
|
6
|
+
// name: "Recepción",
|
|
7
|
+
// weight: 1
|
|
8
|
+
// },
|
|
9
|
+
PA: {
|
|
10
|
+
status: "PA",
|
|
11
|
+
name: "Por Asignar",
|
|
12
|
+
weight: 2
|
|
13
|
+
},
|
|
14
|
+
AS: {
|
|
15
|
+
status: "AS",
|
|
16
|
+
name: "Asignado",
|
|
17
|
+
weight: 3
|
|
18
|
+
},
|
|
19
|
+
CA: {
|
|
20
|
+
status: "CA",
|
|
21
|
+
name: "Capturando",
|
|
22
|
+
weight: 4
|
|
23
|
+
},
|
|
24
|
+
// IE: {
|
|
25
|
+
// status: "IE",
|
|
26
|
+
// name: "Información Enviada",
|
|
27
|
+
// weight: 5
|
|
28
|
+
// },
|
|
29
|
+
RCA: {
|
|
30
|
+
status: "RCA",
|
|
31
|
+
name: "Rechazado Cadena",
|
|
32
|
+
weight: 6
|
|
33
|
+
},
|
|
34
|
+
RP: {
|
|
35
|
+
status: "RP",
|
|
36
|
+
name: "Rechazado Proveedor",
|
|
37
|
+
weight: 7
|
|
38
|
+
},
|
|
39
|
+
RA: {
|
|
40
|
+
status: "RA",
|
|
41
|
+
name: "Rechazado Auditor",
|
|
42
|
+
weight: 8
|
|
43
|
+
},
|
|
44
|
+
RC: {
|
|
45
|
+
status: "RC",
|
|
46
|
+
name: "Rechazo Coordinador",
|
|
47
|
+
weight: 9
|
|
48
|
+
},
|
|
49
|
+
AC: {
|
|
50
|
+
status: "AC",
|
|
51
|
+
name: "Aprobado Coordinador",
|
|
52
|
+
weight: 10
|
|
53
|
+
},
|
|
54
|
+
AA: {
|
|
55
|
+
status: "AA",
|
|
56
|
+
name: "Aprobado Auditor",
|
|
57
|
+
weight: 11
|
|
58
|
+
},
|
|
59
|
+
AP: {
|
|
60
|
+
status: "AP",
|
|
61
|
+
name: "Aprobado Proveedor",
|
|
62
|
+
weight: 12
|
|
63
|
+
},
|
|
64
|
+
ACA: {
|
|
65
|
+
status: "ACA",
|
|
66
|
+
name: "Aprobado Cadena",
|
|
67
|
+
weight: 13
|
|
68
|
+
},
|
|
69
|
+
Ex: {
|
|
70
|
+
status: "Ex",
|
|
71
|
+
name: "Exportado",
|
|
72
|
+
weight: 14
|
|
73
|
+
},
|
|
74
|
+
// RAC: {
|
|
75
|
+
// status: "RAC",
|
|
76
|
+
// name: "Rechazo de Auditoría Content-oh!",
|
|
77
|
+
// weight: 15
|
|
78
|
+
// },
|
|
79
|
+
// SAC: {
|
|
80
|
+
// status: "SAC",
|
|
81
|
+
// name: "Solicitud de Auditoría Content-oh!",
|
|
82
|
+
// weight: 16
|
|
83
|
+
// },
|
|
84
|
+
// AAC: {
|
|
85
|
+
// status: "AAC",
|
|
86
|
+
// name: "Aprobado Auditoría Content-oh!",
|
|
87
|
+
// weight: 17
|
|
88
|
+
// },
|
|
89
|
+
// FAP: {
|
|
90
|
+
// status: "FAP",
|
|
91
|
+
// name: "Finalización de Auditoría por Proveedor",
|
|
92
|
+
// weight: 18
|
|
93
|
+
// },
|
|
94
|
+
//El status NS necesita ser el mayor de todos
|
|
95
|
+
NS: {
|
|
96
|
+
status: "NS",
|
|
97
|
+
name: "No Solicitado",
|
|
98
|
+
weight: 100
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
module.exports = {
|
|
102
|
+
STATUS_DICTIONARY: STATUS_DICTIONARY
|
|
103
|
+
};
|
package/package.json
CHANGED
|
@@ -68,11 +68,12 @@ export const GeneralInput = ({
|
|
|
68
68
|
const [aiSuggestionAccepted, setAiSuggestionAccepted] = useState(false);
|
|
69
69
|
const [valueAccepted, setValueAccepted] = useState(inputValue);
|
|
70
70
|
|
|
71
|
-
const updateParentData = (generalValue, isAiAccepted) => {
|
|
72
|
-
|
|
71
|
+
const updateParentData = (generalValue, isAiAccepted, newBaseValue = null) => {
|
|
73
72
|
setTextValue({ value: generalValue });
|
|
74
73
|
|
|
75
|
-
const
|
|
74
|
+
const baseToCompare = newBaseValue !== null ? newBaseValue : valueAccepted;
|
|
75
|
+
|
|
76
|
+
const similarity = getTextSimilarityPercentage(baseToCompare, generalValue);
|
|
76
77
|
|
|
77
78
|
const generatedWithAi = (isAiAccepted || aiGenerated) && similarity >= 50;
|
|
78
79
|
|
|
@@ -186,13 +187,13 @@ export const GeneralInput = ({
|
|
|
186
187
|
//AI Generation
|
|
187
188
|
|
|
188
189
|
const handleAcceptSuggestion = (suggestionValue) => {
|
|
189
|
-
|
|
190
|
+
if(!suggestionValue) return;
|
|
190
191
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
setValueAccepted(suggestionValue);
|
|
193
|
+
setAiSuggestionAccepted(true);
|
|
194
|
+
setIsAiActive(false);
|
|
194
195
|
|
|
195
|
-
|
|
196
|
+
updateParentData(suggestionValue, true, suggestionValue);
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
return (
|
|
@@ -234,7 +234,6 @@ export const TagAndInput = ({
|
|
|
234
234
|
}, [boxOnboardingList]);
|
|
235
235
|
|
|
236
236
|
useEffect(() => {
|
|
237
|
-
|
|
238
237
|
const currentDescriptionUpdate = Array.isArray(updatedDescriptions)
|
|
239
238
|
? updatedDescriptions.find(desc => desc?.attributeId === inputId)
|
|
240
239
|
: null;
|
|
@@ -253,7 +252,7 @@ export const TagAndInput = ({
|
|
|
253
252
|
|
|
254
253
|
setInputsGeneratedWithAi(prev => ({
|
|
255
254
|
...prev,
|
|
256
|
-
[`${inputId}-${inputType}-${version
|
|
255
|
+
[`${inputId}-${inputType}-${version}`]: {
|
|
257
256
|
inputType,
|
|
258
257
|
inputId,
|
|
259
258
|
version,
|
|
@@ -265,9 +264,7 @@ export const TagAndInput = ({
|
|
|
265
264
|
}, [updatedDescriptions, updatedDatasheets, aiGenerated, inputId]);
|
|
266
265
|
|
|
267
266
|
useEffect(() => {
|
|
268
|
-
|
|
269
|
-
setIsAiGenerated(!!inputsGeneratedWithAi[`${inputId}-${inputType}-${version ?? label}`]?.isAiGenerated);
|
|
270
|
-
|
|
267
|
+
setIsAiGenerated(!!inputsGeneratedWithAi[`${inputId}-${inputType}-${version}`]?.isAiGenerated);
|
|
271
268
|
}, [inputsGeneratedWithAi]);
|
|
272
269
|
|
|
273
270
|
useEffect(() => {
|
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { startTransition, useEffect, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
IconButton,
|
|
4
|
+
MenuItem,
|
|
5
|
+
Checkbox,
|
|
6
|
+
ListItemText,
|
|
7
|
+
InputLabel,
|
|
8
|
+
} from "@mui/material";
|
|
9
|
+
|
|
10
|
+
import CloseIcon from "@mui/icons-material/Close";
|
|
11
|
+
import LinkIcon from "@mui/icons-material/Link";
|
|
12
|
+
import BuildOutlinedIcon from "@mui/icons-material/BuildOutlined";
|
|
13
|
+
import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
|
|
14
|
+
import LayersIcon from "@mui/icons-material/Layers";
|
|
15
|
+
import ViewInArOutlined from "@mui/icons-material/ViewInArOutlined";
|
|
16
|
+
import { CachedOutlined } from "@mui/icons-material";
|
|
17
|
+
|
|
18
|
+
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
|
|
19
|
+
import RadioButtonUncheckedIcon from "@mui/icons-material/RadioButtonUnchecked";
|
|
20
|
+
|
|
21
|
+
import { STATUS_DICTIONARY } from "../../../global-files/statusDictionary";
|
|
22
|
+
|
|
23
|
+
import {
|
|
24
|
+
StyledDialog,
|
|
25
|
+
ModalHeader,
|
|
26
|
+
BadgeCircle,
|
|
27
|
+
MainSection,
|
|
28
|
+
Section,
|
|
29
|
+
SectionTitle,
|
|
30
|
+
ScopeButtonGroup,
|
|
31
|
+
ScopeButton,
|
|
32
|
+
HelperText,
|
|
33
|
+
StatusGrid,
|
|
34
|
+
StatusPill,
|
|
35
|
+
StyledTextArea,
|
|
36
|
+
StyledFormControl,
|
|
37
|
+
StyledSelect,
|
|
38
|
+
FooterActions,
|
|
39
|
+
ActionButton,
|
|
40
|
+
ImpactSummary,
|
|
41
|
+
colors,
|
|
42
|
+
} from "./styles";
|
|
43
|
+
import axios from "axios";
|
|
44
|
+
|
|
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
|
+
const availableServices = ["description", "datasheet", "images"];
|
|
55
|
+
|
|
56
|
+
const ChangeStatusModal = ({
|
|
57
|
+
state,
|
|
58
|
+
open,
|
|
59
|
+
onClose,
|
|
60
|
+
token = "",
|
|
61
|
+
reloadData = () => {},
|
|
62
|
+
}) => {
|
|
63
|
+
const [scope, setScope] = useState("product");
|
|
64
|
+
const [newStatus, setNewStatus] = useState("");
|
|
65
|
+
const [comment, setComment] = useState("");
|
|
66
|
+
const [availableRetailers, setAvailableRetailers] = useState([]);
|
|
67
|
+
const [selectedChains, setSelectedChains] = useState([]);
|
|
68
|
+
const [selectedServices, setSelectedServices] = useState([]);
|
|
69
|
+
|
|
70
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
71
|
+
|
|
72
|
+
const [currentStatusObj, setCurrentStatusObj] = useState({});
|
|
73
|
+
|
|
74
|
+
const isStatusValid =
|
|
75
|
+
newStatus !== "" && newStatus !== currentStatusObj.label;
|
|
76
|
+
const isCommentValid = comment.trim().length > 0;
|
|
77
|
+
|
|
78
|
+
let isScopeValid = false;
|
|
79
|
+
if (scope === "product") isScopeValid = true;
|
|
80
|
+
if (scope === "retailer") isScopeValid = selectedChains.length > 0;
|
|
81
|
+
if (scope === "service")
|
|
82
|
+
isScopeValid = selectedChains.length > 0 && selectedServices.length > 0;
|
|
83
|
+
|
|
84
|
+
const canSubmit = isStatusValid && isCommentValid && isScopeValid;
|
|
85
|
+
|
|
86
|
+
const handleScopeChange = (newScope) => {
|
|
87
|
+
setScope(newScope);
|
|
88
|
+
setSelectedChains([]);
|
|
89
|
+
setSelectedServices([]);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const handleSubmit = async () => {
|
|
93
|
+
if (!canSubmit || isSubmitting) return;
|
|
94
|
+
|
|
95
|
+
setIsSubmitting(true);
|
|
96
|
+
|
|
97
|
+
const upc = state?.product?.upc;
|
|
98
|
+
const article_id = state?.product?.id_article;
|
|
99
|
+
const order_id = state?.product?.id_order;
|
|
100
|
+
const version = state?.product?.version;
|
|
101
|
+
const retailers_selected = availableRetailers
|
|
102
|
+
?.filter((retailer) => selectedChains?.includes(retailer.id_retailer))
|
|
103
|
+
?.map((retailer) => ({
|
|
104
|
+
id: retailer?.id_retailer,
|
|
105
|
+
name: retailer?.name,
|
|
106
|
+
}));
|
|
107
|
+
const services_selected = selectedServices;
|
|
108
|
+
|
|
109
|
+
const old_status = state?.product?.status;
|
|
110
|
+
const new_status = Object.values(STATUS_DICTIONARY).find(
|
|
111
|
+
(status) => status.name === newStatus,
|
|
112
|
+
).status;
|
|
113
|
+
|
|
114
|
+
const commentary = comment;
|
|
115
|
+
|
|
116
|
+
const payload = {
|
|
117
|
+
upc,
|
|
118
|
+
articleId: article_id,
|
|
119
|
+
orderId: order_id,
|
|
120
|
+
version: version,
|
|
121
|
+
retailers:
|
|
122
|
+
scope === "product"
|
|
123
|
+
? availableRetailers?.map((retailer) => ({
|
|
124
|
+
id: retailer?.id_retailer,
|
|
125
|
+
name: retailer?.name,
|
|
126
|
+
}))
|
|
127
|
+
: retailers_selected,
|
|
128
|
+
services:
|
|
129
|
+
scope !== "service"
|
|
130
|
+
? Object.keys(state?.product.services)
|
|
131
|
+
.filter((service) => !!state?.product?.services[service])
|
|
132
|
+
.map((service) =>
|
|
133
|
+
service
|
|
134
|
+
.replace("datasheets", "datasheet")
|
|
135
|
+
.replace("descriptions", "description"),
|
|
136
|
+
)
|
|
137
|
+
: services_selected,
|
|
138
|
+
oldStatus: old_status,
|
|
139
|
+
newStatus: new_status,
|
|
140
|
+
commentary: commentary,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const response = await axios.post(
|
|
144
|
+
process.env.REACT_APP_REQUEST_CHANGE_STATUS,
|
|
145
|
+
payload,
|
|
146
|
+
{
|
|
147
|
+
headers: {
|
|
148
|
+
Authorization: token,
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
reloadData();
|
|
154
|
+
setIsSubmitting(false);
|
|
155
|
+
onClose();
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
useEffect(() => {
|
|
159
|
+
if (!state) return;
|
|
160
|
+
setCurrentStatusObj(STATUS_DICTIONARY[state?.product?.status]);
|
|
161
|
+
|
|
162
|
+
setAvailableRetailers(state?.product?.categoryRetailerInOrder || []);
|
|
163
|
+
}, [state]);
|
|
164
|
+
|
|
165
|
+
const selectMenuProps = {
|
|
166
|
+
PaperProps: {
|
|
167
|
+
style: {
|
|
168
|
+
borderRadius: "5px",
|
|
169
|
+
marginTop: "5px",
|
|
170
|
+
boxShadow: "0px 4px 20px rgba(0,0,0,0.1)",
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<StyledDialog open={open} onClose={onClose}>
|
|
177
|
+
<ModalHeader>
|
|
178
|
+
<IconButton className="close-icon" onClick={onClose} size="small">
|
|
179
|
+
<CloseIcon fontSize="small" />
|
|
180
|
+
</IconButton>
|
|
181
|
+
<BadgeCircle>
|
|
182
|
+
<CachedOutlined />
|
|
183
|
+
</BadgeCircle>
|
|
184
|
+
<div className="title-container">
|
|
185
|
+
<h2>Cambio de Estatus</h2>
|
|
186
|
+
<p>{state?.product?.name}</p>
|
|
187
|
+
</div>
|
|
188
|
+
</ModalHeader>
|
|
189
|
+
|
|
190
|
+
<MainSection>
|
|
191
|
+
<Section>
|
|
192
|
+
<SectionTitle>Alcance del cambio:</SectionTitle>
|
|
193
|
+
<ScopeButtonGroup>
|
|
194
|
+
<ScopeButton
|
|
195
|
+
active={scope === "product"}
|
|
196
|
+
onClick={() => handleScopeChange("product")}
|
|
197
|
+
>
|
|
198
|
+
<ViewInArOutlined /> Producto completo
|
|
199
|
+
</ScopeButton>
|
|
200
|
+
<ScopeButton
|
|
201
|
+
active={scope === "retailer"}
|
|
202
|
+
onClick={() => handleScopeChange("retailer")}
|
|
203
|
+
>
|
|
204
|
+
<LinkIcon /> Por Cadena
|
|
205
|
+
</ScopeButton>
|
|
206
|
+
<ScopeButton
|
|
207
|
+
active={scope === "service"}
|
|
208
|
+
onClick={() => handleScopeChange("service")}
|
|
209
|
+
>
|
|
210
|
+
<BuildOutlinedIcon /> Por Servicio
|
|
211
|
+
</ScopeButton>
|
|
212
|
+
</ScopeButtonGroup>
|
|
213
|
+
{scope === "product" && (
|
|
214
|
+
<HelperText>
|
|
215
|
+
Se cambiará el estatus de todos los servicios y cadenas
|
|
216
|
+
</HelperText>
|
|
217
|
+
)}
|
|
218
|
+
{scope === "retailer" && (
|
|
219
|
+
<HelperText>
|
|
220
|
+
Afectará todos los servicios de las cadenas seleccionadas
|
|
221
|
+
</HelperText>
|
|
222
|
+
)}
|
|
223
|
+
{scope === "service" && (
|
|
224
|
+
<HelperText>
|
|
225
|
+
Afectará únicamente los servicios de las cadenas seleccionadas
|
|
226
|
+
</HelperText>
|
|
227
|
+
)}
|
|
228
|
+
</Section>
|
|
229
|
+
|
|
230
|
+
{(scope === "retailer" || scope === "service") && (
|
|
231
|
+
<Section style={{ paddingTop: 10 }}>
|
|
232
|
+
<StyledFormControl fullWidth size="small">
|
|
233
|
+
<InputLabel id="chain-label">Selecciona Cadena(s)</InputLabel>
|
|
234
|
+
<StyledSelect
|
|
235
|
+
labelId="chain-label"
|
|
236
|
+
multiple
|
|
237
|
+
// 1. El value debe ser directamente tu estado (el arreglo de IDs)
|
|
238
|
+
value={selectedChains}
|
|
239
|
+
// 2. onChange seguro para MUI
|
|
240
|
+
onChange={(e) => {
|
|
241
|
+
const {
|
|
242
|
+
target: { value },
|
|
243
|
+
} = e;
|
|
244
|
+
setSelectedChains(
|
|
245
|
+
typeof value === "string" ? value.split(",") : value,
|
|
246
|
+
);
|
|
247
|
+
}}
|
|
248
|
+
// 3. renderValue traduce los IDs a los Nombres de las cadenas para mostrarlos separados por coma
|
|
249
|
+
renderValue={(selected) =>
|
|
250
|
+
availableRetailers
|
|
251
|
+
.filter((retailer) =>
|
|
252
|
+
selected.includes(retailer.id_retailer),
|
|
253
|
+
)
|
|
254
|
+
.map((retailer) => retailer.name)
|
|
255
|
+
.join(", ")
|
|
256
|
+
}
|
|
257
|
+
MenuProps={selectMenuProps}
|
|
258
|
+
>
|
|
259
|
+
{availableRetailers.map((retailer) => (
|
|
260
|
+
<MenuItem
|
|
261
|
+
key={retailer.name}
|
|
262
|
+
value={retailer.id_retailer}
|
|
263
|
+
sx={{
|
|
264
|
+
fontFamily: "Raleway",
|
|
265
|
+
fontSize: "0.85rem",
|
|
266
|
+
padding: "6px 12px",
|
|
267
|
+
"&.Mui-selected": {
|
|
268
|
+
backgroundColor: `${colors.primary}1A`,
|
|
269
|
+
},
|
|
270
|
+
"&.Mui-selected:hover": {
|
|
271
|
+
backgroundColor: `${colors.primary}33`,
|
|
272
|
+
},
|
|
273
|
+
}}
|
|
274
|
+
>
|
|
275
|
+
<Checkbox
|
|
276
|
+
icon={<RadioButtonUncheckedIcon sx={{ fontSize: 18 }} />}
|
|
277
|
+
checkedIcon={<CheckCircleIcon sx={{ fontSize: 18 }} />}
|
|
278
|
+
checked={
|
|
279
|
+
selectedChains.indexOf(retailer.id_retailer) > -1
|
|
280
|
+
}
|
|
281
|
+
style={{
|
|
282
|
+
color: colors.primary,
|
|
283
|
+
padding: "4px 8px 4px 4px",
|
|
284
|
+
}}
|
|
285
|
+
/>
|
|
286
|
+
<img
|
|
287
|
+
src={`https://content-management-images.s3.amazonaws.com/retailers/${retailer?.id_retailer}.png`}
|
|
288
|
+
alt={retailer?.name}
|
|
289
|
+
style={{
|
|
290
|
+
width: "20px",
|
|
291
|
+
height: "20px",
|
|
292
|
+
objectFit: "contain",
|
|
293
|
+
marginRight: "12px",
|
|
294
|
+
borderRadius: "4px",
|
|
295
|
+
}}
|
|
296
|
+
/>
|
|
297
|
+
<ListItemText
|
|
298
|
+
primary={retailer?.name}
|
|
299
|
+
primaryTypographyProps={{
|
|
300
|
+
style: { fontFamily: "Raleway", fontSize: "0.85rem" },
|
|
301
|
+
}}
|
|
302
|
+
/>
|
|
303
|
+
</MenuItem>
|
|
304
|
+
))}
|
|
305
|
+
</StyledSelect>
|
|
306
|
+
</StyledFormControl>
|
|
307
|
+
</Section>
|
|
308
|
+
)}
|
|
309
|
+
|
|
310
|
+
{scope === "service" && (
|
|
311
|
+
<Section style={{ paddingTop: 0 }}>
|
|
312
|
+
<StyledFormControl fullWidth size="small">
|
|
313
|
+
<InputLabel id="service-label">Selecciona Servicio(s)</InputLabel>
|
|
314
|
+
<StyledSelect
|
|
315
|
+
labelId="service-label"
|
|
316
|
+
multiple
|
|
317
|
+
value={selectedServices}
|
|
318
|
+
onChange={(e) => {
|
|
319
|
+
const {
|
|
320
|
+
target: { value },
|
|
321
|
+
} = e;
|
|
322
|
+
setSelectedServices(
|
|
323
|
+
typeof value === "string" ? value.split(",") : value,
|
|
324
|
+
);
|
|
325
|
+
}}
|
|
326
|
+
renderValue={(selected) =>
|
|
327
|
+
selected
|
|
328
|
+
.map((service) =>
|
|
329
|
+
service === "description"
|
|
330
|
+
? "Descripciones"
|
|
331
|
+
: service === "datasheet"
|
|
332
|
+
? "Ficha Técnica"
|
|
333
|
+
: "Imágenes",
|
|
334
|
+
)
|
|
335
|
+
.join(", ")
|
|
336
|
+
}
|
|
337
|
+
MenuProps={selectMenuProps}
|
|
338
|
+
>
|
|
339
|
+
{availableServices.map((service) => (
|
|
340
|
+
<MenuItem
|
|
341
|
+
key={service}
|
|
342
|
+
value={service}
|
|
343
|
+
sx={{
|
|
344
|
+
fontFamily: "Raleway",
|
|
345
|
+
fontSize: "0.85rem",
|
|
346
|
+
padding: "6px 12px",
|
|
347
|
+
"&.Mui-selected": {
|
|
348
|
+
backgroundColor: `${colors.primary}1A`,
|
|
349
|
+
},
|
|
350
|
+
"&.Mui-selected:hover": {
|
|
351
|
+
backgroundColor: `${colors.primary}33`,
|
|
352
|
+
},
|
|
353
|
+
}}
|
|
354
|
+
>
|
|
355
|
+
<Checkbox
|
|
356
|
+
icon={<RadioButtonUncheckedIcon sx={{ fontSize: 18 }} />}
|
|
357
|
+
checkedIcon={<CheckCircleIcon sx={{ fontSize: 18 }} />}
|
|
358
|
+
checked={selectedServices.indexOf(service) > -1}
|
|
359
|
+
style={{
|
|
360
|
+
color: colors.primary,
|
|
361
|
+
padding: "4px 8px 4px 4px",
|
|
362
|
+
}}
|
|
363
|
+
/>
|
|
364
|
+
<ListItemText
|
|
365
|
+
primary={
|
|
366
|
+
service === "description"
|
|
367
|
+
? "Descripciones"
|
|
368
|
+
: service === "datasheet"
|
|
369
|
+
? "Ficha Técnica"
|
|
370
|
+
: "Imágenes"
|
|
371
|
+
}
|
|
372
|
+
primaryTypographyProps={{
|
|
373
|
+
style: { fontFamily: "Raleway", fontSize: "0.85rem" },
|
|
374
|
+
}}
|
|
375
|
+
/>
|
|
376
|
+
</MenuItem>
|
|
377
|
+
))}
|
|
378
|
+
</StyledSelect>
|
|
379
|
+
</StyledFormControl>
|
|
380
|
+
</Section>
|
|
381
|
+
)}
|
|
382
|
+
|
|
383
|
+
<Section>
|
|
384
|
+
<SectionTitle>Estatus actual:</SectionTitle>
|
|
385
|
+
<StatusPill
|
|
386
|
+
label={currentStatusObj.name}
|
|
387
|
+
selected={false}
|
|
388
|
+
disabled={true}
|
|
389
|
+
/>
|
|
390
|
+
</Section>
|
|
391
|
+
|
|
392
|
+
<Section>
|
|
393
|
+
<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>
|
|
408
|
+
</Section>
|
|
409
|
+
|
|
410
|
+
<Section>
|
|
411
|
+
<SectionTitle>Comentario:</SectionTitle>
|
|
412
|
+
<StyledTextArea
|
|
413
|
+
multiline
|
|
414
|
+
rows={3}
|
|
415
|
+
placeholder="Explica el motivo del cambio de estatus..."
|
|
416
|
+
value={comment}
|
|
417
|
+
onChange={(e) => {
|
|
418
|
+
if (e.target.value.length <= 255) {
|
|
419
|
+
setComment(e.target.value);
|
|
420
|
+
}
|
|
421
|
+
}}
|
|
422
|
+
inputProps={{ maxLength: 255 }}
|
|
423
|
+
helperText={`${comment.length}/255 caracteres`}
|
|
424
|
+
FormHelperTextProps={{
|
|
425
|
+
style: { textAlign: "right" }
|
|
426
|
+
}}
|
|
427
|
+
/>
|
|
428
|
+
</Section>
|
|
429
|
+
|
|
430
|
+
<ImpactSummary>
|
|
431
|
+
<span className="summary-title">Resumen de impacto:</span>
|
|
432
|
+
<div className="status-flow">
|
|
433
|
+
<StatusPill
|
|
434
|
+
label={currentStatusObj.name}
|
|
435
|
+
selected={false}
|
|
436
|
+
disabled={true}
|
|
437
|
+
size="small"
|
|
438
|
+
/>
|
|
439
|
+
<ArrowForwardIcon
|
|
440
|
+
fontSize="small"
|
|
441
|
+
sx={{ color: colors.textMuted }}
|
|
442
|
+
/>
|
|
443
|
+
<StatusPill
|
|
444
|
+
label={newStatus || "Selecciona un estatus"}
|
|
445
|
+
selected={!!newStatus}
|
|
446
|
+
size="small"
|
|
447
|
+
/>
|
|
448
|
+
</div>
|
|
449
|
+
<div className="impact-counts">
|
|
450
|
+
<div>
|
|
451
|
+
<LinkIcon fontSize="small" />
|
|
452
|
+
{scope === "product"
|
|
453
|
+
? state?.product?.categoryRetailerInOrder?.length
|
|
454
|
+
: selectedChains.length}{" "}
|
|
455
|
+
cadena(s)
|
|
456
|
+
</div>
|
|
457
|
+
<div>
|
|
458
|
+
<BuildOutlinedIcon fontSize="small" />
|
|
459
|
+
{scope === "service"
|
|
460
|
+
? selectedServices.length
|
|
461
|
+
: Object.values(state?.product?.services ?? {})
|
|
462
|
+
? Object.values(state?.product?.services ?? {}).filter(
|
|
463
|
+
(service) => !!service,
|
|
464
|
+
).length
|
|
465
|
+
: "No es un array"}
|
|
466
|
+
servicios
|
|
467
|
+
</div>
|
|
468
|
+
</div>
|
|
469
|
+
</ImpactSummary>
|
|
470
|
+
</MainSection>
|
|
471
|
+
|
|
472
|
+
<FooterActions>
|
|
473
|
+
<ActionButton className="cancel" onClick={onClose}>
|
|
474
|
+
Cancelar
|
|
475
|
+
</ActionButton>
|
|
476
|
+
<ActionButton
|
|
477
|
+
className="submit"
|
|
478
|
+
disabled={!canSubmit || isSubmitting}
|
|
479
|
+
onClick={handleSubmit}
|
|
480
|
+
>
|
|
481
|
+
{isSubmitting ? "Guardando..." : "Realizar cambio"}
|
|
482
|
+
</ActionButton>
|
|
483
|
+
</FooterActions>
|
|
484
|
+
</StyledDialog>
|
|
485
|
+
);
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
export default ChangeStatusModal;
|