contentoh-components-library 21.5.92 → 21.5.93
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 +54 -245
- package/dist/components/atoms/GeneralInput/styles.js +3 -7
- package/dist/components/atoms/InputFormatter/index.js +68 -223
- package/dist/components/atoms/InputFormatter/styles.js +4 -20
- package/dist/components/molecules/StatusAsignationInfo/index.js +1 -11
- package/dist/components/molecules/TabsMenu/index.js +12 -13
- package/dist/components/molecules/TagAndInput/index.js +24 -361
- package/dist/components/molecules/TagAndInput/styles.js +2 -2
- package/dist/components/organisms/FullProductNameHeader/index.js +22 -6
- package/dist/components/organisms/InputGroup/index.js +18 -22
- package/dist/components/pages/ProviderProductEdition/ProviderProductEdition.stories.js +337 -150
- package/dist/components/pages/ProviderProductEdition/context/provider-product-edition.context.js +15 -15
- package/dist/components/pages/ProviderProductEdition/index.js +362 -368
- package/dist/components/pages/ProviderProductEdition/utils.js +0 -1
- package/dist/components/pages/RetailerProductEdition/RetailerProductEdition.stories.js +196 -179
- package/dist/components/pages/RetailerProductEdition/context/provider-product-edition.context.js +260 -59
- package/dist/components/pages/RetailerProductEdition/context/reducers/product.js +38 -50
- package/dist/components/pages/RetailerProductEdition/index.js +2234 -1716
- package/dist/components/pages/RetailerProductEdition/styles.js +2 -4
- package/dist/components/pages/RetailerProductEdition/utils.js +2 -251
- package/dist/contexts/AiProductEdition.js +158 -230
- package/package.json +2 -4
- package/src/components/atoms/GeneralButton/styles.js +0 -4
- package/src/components/atoms/GeneralInput/index.js +60 -237
- package/src/components/atoms/GeneralInput/styles.js +0 -81
- package/src/components/atoms/InputFormatter/index.js +51 -200
- package/src/components/atoms/InputFormatter/styles.js +0 -284
- package/src/components/molecules/StatusAsignationInfo/index.js +1 -9
- package/src/components/molecules/TabsMenu/index.js +11 -12
- package/src/components/molecules/TagAndInput/index.js +21 -286
- package/src/components/molecules/TagAndInput/styles.js +17 -59
- package/src/components/organisms/FullProductNameHeader/index.js +28 -4
- package/src/components/organisms/FullTabsMenu/index.js +1 -1
- package/src/components/organisms/InputGroup/index.js +4 -12
- package/src/components/pages/ProviderProductEdition/ProviderProductEdition.stories.js +202 -174
- package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx +14 -14
- package/src/components/pages/ProviderProductEdition/index.js +452 -453
- package/src/components/pages/ProviderProductEdition/utils.js +2 -2
- package/src/components/pages/RetailerProductEdition/RetailerProductEdition.stories.js +224 -201
- package/src/components/pages/RetailerProductEdition/index.js +1718 -1547
- package/src/components/pages/RetailerProductEdition/styles.js +2 -67
- package/src/components/pages/RetailerProductEdition/utils.js +0 -240
- package/dist/ai/utils/compare-strings.js +0 -45
- package/dist/components/organisms/ChangeStatusModal/index.js +0 -531
- package/dist/components/organisms/ChangeStatusModal/styles.js +0 -85
- package/dist/global-files/statusDictionary.js +0 -103
- package/src/ai/utils/compare-strings.js +0 -45
- package/src/assets/images/Icons/arrow.png +0 -0
- package/src/assets/images/Icons/cancel.png +0 -0
- package/src/assets/images/Icons/ia-icon.png +0 -0
- package/src/assets/images/Icons/loading.svg +0 -5
- package/src/assets/images/Icons/reload.png +0 -0
- package/src/components/atoms/RetailerSelector/RetailerSelector.stories.js +0 -10
- package/src/components/atoms/RetailerSelector/index.js +0 -3
- package/src/components/atoms/RetailerSelector/styles.js +0 -0
- package/src/components/organisms/ChangeStatusModal/index.jsx +0 -488
- package/src/components/organisms/ChangeStatusModal/styles.js +0 -333
- package/src/components/pages/RetailerProductEdition/context/provider-product-edition.context.jsx +0 -575
- package/src/components/pages/RetailerProductEdition/context/provider-product-edition.reducer.js +0 -62
- package/src/components/pages/RetailerProductEdition/context/reducers/active-state.js +0 -344
- package/src/components/pages/RetailerProductEdition/context/reducers/inputs.js +0 -155
- package/src/components/pages/RetailerProductEdition/context/reducers/product.js +0 -114
- package/src/components/pages/RetailerProductEdition/context/reducers/system.js +0 -60
- package/src/components/pages/RetailerProductEdition/index_old.js +0 -1979
- package/src/components/pages/RetailerProductEdition/stories/Auditor.stories.js +0 -101
- package/src/components/pages/RetailerProductEdition/stories/ImageEditor.stories.js +0 -115
- package/src/components/pages/RetailerProductEdition/stories/TextEditor.stories.js +0 -174
- package/src/contexts/AiProductEdition.jsx +0 -339
- package/src/global-files/statusDictionary.js +0 -103
|
@@ -1,286 +1,392 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
1
|
+
import { Container } from "./styles";
|
|
2
|
+
import { HeaderTop } from "../../molecules/HeaderTop";
|
|
3
|
+
import { ImagePreviewer } from "../../organisms/ImagePreviewer";
|
|
4
|
+
import { ImageDataTable } from "../../organisms/ImageDataTable";
|
|
5
|
+
import { FullProductNameHeader } from "../../organisms/FullProductNameHeader";
|
|
6
|
+
import { FullTabsMenu } from "../../organisms/FullTabsMenu";
|
|
7
|
+
import { InputGroup } from "../../organisms/InputGroup";
|
|
8
|
+
import { useEffect, useReducer, useState, useCallback } from "react";
|
|
9
|
+
import { GalleryElement } from "../../molecules/GalleryElement";
|
|
5
10
|
import { saveAs } from "file-saver";
|
|
6
|
-
|
|
11
|
+
import { Commentary } from "../../atoms/Commentary";
|
|
7
12
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
getRetailerServices,
|
|
14
|
+
getPercentage,
|
|
15
|
+
fetchUsers,
|
|
16
|
+
} from "../../../global-files/data";
|
|
17
|
+
import { GalleryHeader } from "../../molecules/GalleryHeader";
|
|
18
|
+
import { ProductImageModal } from "../../organisms/ProductImageModal";
|
|
19
|
+
import { useDropzone } from "react-dropzone";
|
|
20
|
+
import axios from "axios";
|
|
21
|
+
import { v4 as uuidv4 } from "uuid";
|
|
22
|
+
import AWS from "aws-sdk";
|
|
23
|
+
import attributesSent from "../../../assets/images/modalsSVGs/attributesSent.svg";
|
|
24
|
+
import descriptionSent from "../../../assets/images/modalsSVGs/descriptionSent.svg";
|
|
25
|
+
import imagesSent from "../../../assets/images/modalsSVGs/uploadingImages.svg";
|
|
26
|
+
import { TagAndInput } from "../../molecules/TagAndInput/index";
|
|
27
|
+
import { Button } from "../../atoms/GeneralButton";
|
|
28
|
+
import { GenericModal } from "../../atoms/GenericModal";
|
|
29
|
+
import { ScreenHeader } from "../../atoms/ScreenHeader";
|
|
30
|
+
import { Loading } from "../../atoms/Loading";
|
|
31
|
+
import succes from "../../../assets/images/genericModal/genericModalCheck.svg";
|
|
32
|
+
import { VersionSelector } from "../../organisms/VersionSelector";
|
|
33
|
+
import { useCloseModal } from "../../../global-files/customHooks";
|
|
11
34
|
import {
|
|
12
|
-
normalizeProduct,
|
|
13
|
-
getConceptByTab,
|
|
14
35
|
getAuditVersion,
|
|
15
36
|
getInputsData,
|
|
16
37
|
createMessage,
|
|
17
38
|
sendMessage,
|
|
18
|
-
translateConcept,
|
|
19
|
-
getStatusArrayByRole,
|
|
20
|
-
getConceptsByRole,
|
|
21
|
-
buildCollaboratorAssignations,
|
|
22
|
-
calculateRequiredNull,
|
|
23
39
|
} from "./utils";
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
fetchUsers,
|
|
27
|
-
getPercentage,
|
|
28
|
-
getRetailerServices,
|
|
29
|
-
getServicesData,
|
|
30
|
-
} from "../../../global-files/data";
|
|
31
|
-
import { useCloseModal } from "../../../global-files/customHooks";
|
|
32
|
-
|
|
33
|
-
import { Button } from "../../atoms/GeneralButton";
|
|
34
|
-
import { GenericModal } from "../../atoms/GenericModal";
|
|
35
|
-
import { Loading } from "../../atoms/Loading";
|
|
36
|
-
import { ScreenHeader } from "../../atoms/ScreenHeader";
|
|
40
|
+
import { Modal } from "../../organisms/Modal";
|
|
37
41
|
import { ButtonV2 } from "../../atoms/ButtonV2";
|
|
42
|
+
import generateThumbnail from "./generateThumnail";
|
|
43
|
+
|
|
44
|
+
const reducerImages = (state, action) => {
|
|
45
|
+
let { values, attrForImgs, inputsByRetailer } = state;
|
|
46
|
+
switch (action.action) {
|
|
47
|
+
case "init":
|
|
48
|
+
const newInputsByRetailer = {};
|
|
49
|
+
action?.init?.inputsByRetailer?.forEach((inputs) => {
|
|
50
|
+
inputs?.forEach((input) => {
|
|
51
|
+
if (!newInputsByRetailer[`${input.id_retailer}`])
|
|
52
|
+
newInputsByRetailer[`${input.id_retailer}`] = [];
|
|
53
|
+
newInputsByRetailer[`${input.id_retailer}`].push(input);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
inputsByRetailer = newInputsByRetailer;
|
|
57
|
+
return {
|
|
58
|
+
...action.init,
|
|
59
|
+
inputsByRetailer,
|
|
60
|
+
valuesInitial: action.init.values,
|
|
61
|
+
inputsInitial: action.init.inputs,
|
|
62
|
+
};
|
|
63
|
+
case "addImg":
|
|
64
|
+
values = [...values, action.img];
|
|
65
|
+
return { ...state, values };
|
|
66
|
+
case "changeImageInfo":
|
|
67
|
+
values[action.index][action.attribute] = action.value;
|
|
68
|
+
return { ...state, values };
|
|
69
|
+
case "changeShotType":
|
|
70
|
+
values[action.index][action.attribute] = action.value;
|
|
71
|
+
return { ...state, values };
|
|
72
|
+
|
|
73
|
+
case "changeAttrValue":
|
|
74
|
+
const index = attrForImgs.general.findIndex((f) => f.id === action.id);
|
|
75
|
+
if (index !== -1) {
|
|
76
|
+
attrForImgs.general[index].value = action.value;
|
|
77
|
+
}
|
|
38
78
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
79
|
+
return { ...state, attrForImgs, values };
|
|
80
|
+
case "deleteImage":
|
|
81
|
+
values = values.filter(
|
|
82
|
+
(value) => action.selectedImages.indexOf(value) === -1
|
|
83
|
+
);
|
|
84
|
+
return { ...state, values };
|
|
85
|
+
case "orderImages": {
|
|
86
|
+
let { inputsByRetailer, valuesInitial, inputsInitial, inputs } = state;
|
|
87
|
+
try {
|
|
88
|
+
const orderedImages = [];
|
|
89
|
+
const imageIdArray = [];
|
|
90
|
+
if (action?.retailerId && !inputsByRetailer[action.retailerId]) {
|
|
91
|
+
inputsByRetailer[action.retailerId] = [];
|
|
92
|
+
}
|
|
93
|
+
action.retailerId &&
|
|
94
|
+
inputsByRetailer[action.retailerId]?.filter((input) => {
|
|
95
|
+
imageIdArray.push(input.id_image);
|
|
96
|
+
valuesInitial.forEach(async (value) => {
|
|
97
|
+
if (value.ext == "mp4") {
|
|
98
|
+
convertirVideoABase64(
|
|
99
|
+
"https://" +
|
|
100
|
+
process.env.REACT_APP_IMAGES_BUCKET +
|
|
101
|
+
".s3.amazonaws.com/" +
|
|
102
|
+
value.srcDB
|
|
103
|
+
)
|
|
104
|
+
.then(async (base64) => {
|
|
105
|
+
const videoSrc =
|
|
106
|
+
"data:video/mp4;base64," + base64.split(",")[1]; // Añade el tipo MIME adecuado
|
|
107
|
+
value.src = await generateThumbnail(videoSrc, 2);
|
|
108
|
+
})
|
|
109
|
+
.catch((error) => {
|
|
110
|
+
console.error("Error:", error);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
if (value.image_id === input.id_image) orderedImages.push(value);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
inputs = inputsInitial?.filter((input) =>
|
|
117
|
+
imageIdArray.includes(input.id)
|
|
118
|
+
);
|
|
52
119
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
120
|
+
values = orderedImages.length > 0 ? orderedImages : [];
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.log(error);
|
|
123
|
+
}
|
|
124
|
+
return { ...state, values, inputs };
|
|
125
|
+
}
|
|
126
|
+
default:
|
|
127
|
+
return state;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
59
130
|
|
|
60
|
-
|
|
61
|
-
|
|
131
|
+
const S3_BUCKET = process.env.REACT_APP_IMAGES_BUCKET;
|
|
132
|
+
const REGION = "us-east-1";
|
|
133
|
+
|
|
134
|
+
function convertirVideoABase64(url) {
|
|
135
|
+
return new Promise((resolve, reject) => {
|
|
136
|
+
const xhr = new XMLHttpRequest();
|
|
137
|
+
xhr.open("GET", url, true);
|
|
138
|
+
xhr.responseType = "blob";
|
|
139
|
+
xhr.onload = function () {
|
|
140
|
+
if (xhr.status === 200) {
|
|
141
|
+
const blob = xhr.response;
|
|
142
|
+
const reader = new FileReader();
|
|
143
|
+
reader.onloadend = function () {
|
|
144
|
+
resolve(reader.result);
|
|
145
|
+
};
|
|
146
|
+
reader.readAsDataURL(blob);
|
|
147
|
+
} else {
|
|
148
|
+
reject(new Error("Error al cargar el video"));
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
xhr.onerror = function () {
|
|
152
|
+
reject(new Error("Error de red al cargar el video"));
|
|
153
|
+
};
|
|
154
|
+
xhr.send();
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function obtenerDuracionVideoBase64(base64Data) {
|
|
159
|
+
return new Promise((resolve, reject) => {
|
|
160
|
+
const video = document.createElement("video");
|
|
161
|
+
video.src = base64Data;
|
|
162
|
+
video.addEventListener("loadedmetadata", () => {
|
|
163
|
+
resolve(video.duration);
|
|
164
|
+
});
|
|
165
|
+
video.addEventListener("error", reject);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
62
168
|
|
|
63
|
-
|
|
64
|
-
|
|
169
|
+
AWS.config.update({
|
|
170
|
+
accessKeyId: process.env.REACT_APP_KUTS3,
|
|
171
|
+
secretAccessKey: process.env.REACT_APP_AKUTS3,
|
|
172
|
+
});
|
|
65
173
|
|
|
66
|
-
|
|
174
|
+
const myBucket = new AWS.S3({
|
|
175
|
+
params: { Bucket: S3_BUCKET },
|
|
176
|
+
region: REGION,
|
|
177
|
+
});
|
|
67
178
|
|
|
68
|
-
const
|
|
179
|
+
export const RetailerProductEdition = ({
|
|
69
180
|
tabsSections,
|
|
70
181
|
productSelected = {},
|
|
71
182
|
user = {},
|
|
72
183
|
token,
|
|
73
184
|
location,
|
|
74
185
|
}) => {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
dispatch,
|
|
78
|
-
saveDatasheets,
|
|
79
|
-
saveDescriptions,
|
|
80
|
-
updateImages,
|
|
81
|
-
saveImageAttrs,
|
|
82
|
-
deleteImages,
|
|
83
|
-
handleOnDownloadImages,
|
|
84
|
-
createComment,
|
|
85
|
-
} = useProviderProductEdition();
|
|
86
|
-
|
|
87
|
-
const isRetailer = user?.is_retailer;
|
|
88
|
-
|
|
89
|
-
const [showVersionSelector, setShowVersionSelector] =
|
|
90
|
-
useCloseModal("version-selector");
|
|
91
|
-
const [auditableVersion, setAuditableVersion] = useState(null);
|
|
92
|
-
const [headerTop, setHeaderTop] = useState(0);
|
|
93
|
-
const [shotThd, setShotThd] = useState(false);
|
|
94
|
-
const [observation, setObservation] = useState();
|
|
95
|
-
const [showRejectModal, setShowRejectModal] = useState(false);
|
|
96
|
-
const [isObservationVisible, setObservationVisible] = useState(false);
|
|
186
|
+
const [activeTab, setActiveTab] = useState("Descripción");
|
|
187
|
+
const [activeImage, setActiveImage] = useState();
|
|
97
188
|
const [imageLayout, setImageLayout] = useState(false);
|
|
98
|
-
const [
|
|
99
|
-
const [
|
|
100
|
-
const [
|
|
101
|
-
|
|
102
|
-
const [auditServices, setAuditServices] = useState([]);
|
|
103
|
-
const [auditDatasheets, setAuditDatasheets] = useState([]);
|
|
104
|
-
const [auditDescriptions, setAuditDescriptions] = useState([]);
|
|
189
|
+
const [headerTop, setHeaderTop] = useState(0);
|
|
190
|
+
const [descriptions, setDescriptions] = useState([]);
|
|
191
|
+
const [datasheets, setDatasheets] = useState([]);
|
|
192
|
+
const [images, setImages] = useReducer(reducerImages, {});
|
|
105
193
|
const [showModal, setShowModal] = useState(false);
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
accept: "image/*",
|
|
194
|
+
const [showRejectModal, setShowRejectModal] = useState(false);
|
|
195
|
+
const { getRootProps, getInputProps } = useDropzone({
|
|
196
|
+
accept: "image/*, video/mp4",
|
|
110
197
|
noKeyboard: true,
|
|
111
198
|
multiple: true,
|
|
112
199
|
noClick: true,
|
|
113
200
|
onDrop: (acceptedFiles) => {
|
|
201
|
+
const newImages = [];
|
|
114
202
|
acceptedFiles.map((file) => {
|
|
115
203
|
const reader = new FileReader();
|
|
116
204
|
reader.fileName = file.name;
|
|
117
|
-
|
|
118
205
|
reader.onload = async function (e) {
|
|
119
|
-
const
|
|
120
|
-
const fileExtension = fileName.split(".").pop();
|
|
121
|
-
const fileDataURL = e.target.result;
|
|
122
|
-
|
|
206
|
+
const ext = e.srcElement.fileName.split(".");
|
|
123
207
|
const img = new Image();
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
208
|
+
if (ext[ext.length - 1] == "mp4") {
|
|
209
|
+
obtenerDuracionVideoBase64(e.target.result)
|
|
210
|
+
.then(async (duracion) => {
|
|
211
|
+
if (duracion > 15 && duracion < 600) {
|
|
212
|
+
img.src = await generateThumbnail(e.target.result, 2);
|
|
213
|
+
setTimeout(() => {
|
|
214
|
+
const width = img.width;
|
|
215
|
+
const height = img.height;
|
|
216
|
+
const newImg = {
|
|
217
|
+
action: "addImg",
|
|
218
|
+
img: {
|
|
219
|
+
src: img.src, //e.target.result,
|
|
220
|
+
name: e.target.fileName,
|
|
221
|
+
ext: ext[ext.length - 1],
|
|
222
|
+
width: width,
|
|
223
|
+
height: height,
|
|
224
|
+
video_src:
|
|
225
|
+
ext[ext.length - 1] == "mp4" ? e.target.result : "",
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
setImages(newImg);
|
|
229
|
+
}, 500);
|
|
230
|
+
} else {
|
|
231
|
+
setModalAlert({
|
|
232
|
+
show: true,
|
|
233
|
+
title: "Hubo un error al subir el video",
|
|
234
|
+
message:
|
|
235
|
+
"Los videos deben durar entre 15 segundos y 10 minutos",
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
.catch((error) => {
|
|
240
|
+
console.error("Error al obtener la duración del video:", error);
|
|
241
|
+
});
|
|
242
|
+
} else {
|
|
243
|
+
img.src = e.target.result;
|
|
244
|
+
setTimeout(() => {
|
|
245
|
+
const width = img.width;
|
|
246
|
+
const height = img.height;
|
|
247
|
+
const newImg = {
|
|
248
|
+
action: "addImg",
|
|
249
|
+
img: {
|
|
250
|
+
src: img.src, //e.target.result,
|
|
251
|
+
name: e.target.fileName,
|
|
252
|
+
ext: ext[ext.length - 1],
|
|
253
|
+
width: width,
|
|
254
|
+
height: height,
|
|
255
|
+
video_src:
|
|
256
|
+
ext[ext.length - 1] == "mp4" ? e.target.result : "",
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
setImages(newImg);
|
|
260
|
+
}, 500);
|
|
261
|
+
}
|
|
143
262
|
};
|
|
144
|
-
|
|
145
263
|
reader.onerror = function (error) {
|
|
146
264
|
console.log("dropzoneError: ", error);
|
|
147
265
|
};
|
|
148
|
-
|
|
149
266
|
reader.readAsDataURL(file);
|
|
150
267
|
return file;
|
|
151
268
|
});
|
|
152
269
|
},
|
|
153
270
|
});
|
|
271
|
+
const [updatedDatasheets, setUpdatedDatasheets] = useState([]);
|
|
272
|
+
const [updatedDescriptions, setUpdatedDescriptions] = useState([]);
|
|
273
|
+
const [imagesUploaded, setImagesUploaded] = useState(false);
|
|
274
|
+
const [dataImages, setDataImages] = useState();
|
|
275
|
+
const [percentages, setPercentages] = useState(
|
|
276
|
+
new Array(product?.retailers?.length).fill({ percentage: 0 })
|
|
277
|
+
);
|
|
278
|
+
// const [percentages, setPercentages] = useState([{ retailers: {} }]);
|
|
279
|
+
const [activePercentage, setActivePercentage] = useState(0);
|
|
280
|
+
const [activeRetailer, setActiveRetailer] = useState({});
|
|
281
|
+
const [services, setServices] = useState([]);
|
|
282
|
+
const [servicesData, setServicesData] = useState([]);
|
|
283
|
+
const [message, setMessage] = useState("");
|
|
284
|
+
const [product, setProduct] = useState(
|
|
285
|
+
JSON.parse(sessionStorage.getItem("productSelected"))
|
|
286
|
+
? JSON.parse(sessionStorage.getItem("productSelected"))
|
|
287
|
+
: productSelected
|
|
288
|
+
);
|
|
289
|
+
const [icon, setIcon] = useState(null);
|
|
290
|
+
const [version, setVersion] = useState(product?.version);
|
|
291
|
+
const [comments, setComments] = useState({});
|
|
292
|
+
const [comment, setComment] = useState("");
|
|
293
|
+
const [requiredNull, setRequiredNull] = useState({
|
|
294
|
+
"Ficha técnica": 0,
|
|
295
|
+
Descripción: 0,
|
|
296
|
+
Imágenes: 0,
|
|
297
|
+
});
|
|
298
|
+
const [crossComment, setCrossComment] = useState(false);
|
|
299
|
+
const [userGroups, setUserGroups] = useState([]);
|
|
300
|
+
const [assig, setAssig] = useState({});
|
|
301
|
+
const [selectedImages, setSelectedImages] = useState([]);
|
|
302
|
+
const [componentsArray, setComponentsArray] = useState([]);
|
|
303
|
+
const [checkAll, setCheckAll] = useState(false);
|
|
304
|
+
const isRetailer = user?.is_retailer;
|
|
305
|
+
const [loading, setLoading] = useState(true);
|
|
306
|
+
const [retailerStatus, setRetailerStatus] = useState("-");
|
|
307
|
+
const [statusArray, setStatusArray] = useState([]);
|
|
308
|
+
const [socketType, setSocketType] = useState(null);
|
|
309
|
+
const [saving, setSaving] = useState(loading);
|
|
310
|
+
const [showVersionSelector, setShowVersionSelector] =
|
|
311
|
+
useCloseModal("version-selector");
|
|
312
|
+
const shotThd = [58, 59, 60, 61].includes(activeRetailer.id);
|
|
313
|
+
const [auditableVersion, setAuditableVersion] = useState(null);
|
|
314
|
+
const [auditServices, setAuditServices] = useState([]);
|
|
315
|
+
const [auditDatasheets, setAuditDatasheets] = useState([]);
|
|
316
|
+
const [auditDescriptions, setAuditDescriptions] = useState([]);
|
|
317
|
+
const [auditImages, setAuditImages] = useState([]);
|
|
318
|
+
const [compare, setCompare] = useState(false);
|
|
319
|
+
const [observation, setObservation] = useState();
|
|
320
|
+
const [valRejAll, setValRejAll] = useState(false);
|
|
321
|
+
const [modalAlert, setModalAlert] = useState({
|
|
322
|
+
show: false,
|
|
323
|
+
title: "",
|
|
324
|
+
message: "",
|
|
325
|
+
errorInputMessage: false,
|
|
326
|
+
});
|
|
154
327
|
|
|
155
|
-
const [
|
|
328
|
+
const [desc, setDesc] = useState([]);
|
|
329
|
+
const [fich, setFich] = useState([]);
|
|
330
|
+
const [imag, setImag] = useState([]);
|
|
156
331
|
|
|
157
|
-
const
|
|
158
|
-
const imageInputs = state.images_values?.inputs?.map((e) => ({
|
|
159
|
-
value: e?.id,
|
|
160
|
-
name: e?.name,
|
|
161
|
-
required: e?.required,
|
|
162
|
-
active: state.images_values?.values?.some(
|
|
163
|
-
(value) => value?.image_id === e?.id,
|
|
164
|
-
),
|
|
165
|
-
}));
|
|
166
|
-
const imageType = state.images_values?.imageType?.map((e) => ({
|
|
167
|
-
value: e?.id,
|
|
168
|
-
name: e?.name,
|
|
169
|
-
}));
|
|
170
|
-
const imagePackagingType = state.images_values?.imagePackagingType?.map(
|
|
171
|
-
(e) => ({
|
|
172
|
-
value: e?.id,
|
|
173
|
-
name: e?.name,
|
|
174
|
-
}),
|
|
175
|
-
);
|
|
332
|
+
const [isObservationVisible, setObservationVisible] = useState(false);
|
|
176
333
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
/>
|
|
200
|
-
));
|
|
334
|
+
const toggleObservation = () => {
|
|
335
|
+
setObservationVisible(!isObservationVisible);
|
|
336
|
+
};
|
|
337
|
+
// const handleClickOutside = (event) => {
|
|
338
|
+
// if (
|
|
339
|
+
// isObservationVisible &&
|
|
340
|
+
// !event.target.closest(".Observation") &&
|
|
341
|
+
// !event.target.closest(".Container")
|
|
342
|
+
// ) {
|
|
343
|
+
// hideObservation();
|
|
344
|
+
// }
|
|
345
|
+
// };
|
|
346
|
+
|
|
347
|
+
// useEffect(() => {
|
|
348
|
+
// document.addEventListener("click", handleClickOutside);
|
|
349
|
+
// return () => {
|
|
350
|
+
// document.removeEventListener("click", handleClickOutside);
|
|
351
|
+
// };
|
|
352
|
+
// }, [isObservationVisible]);
|
|
353
|
+
|
|
354
|
+
const hideObservation = () => {
|
|
355
|
+
setObservationVisible(false);
|
|
201
356
|
};
|
|
202
357
|
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const productNormalized = normalizeProduct(product);
|
|
210
|
-
|
|
211
|
-
dispatch({
|
|
212
|
-
type: "SET_PRODUCT",
|
|
213
|
-
payload: productNormalized,
|
|
214
|
-
});
|
|
215
|
-
dispatch({
|
|
216
|
-
type: "SET_ACTIVE_RETAILER",
|
|
217
|
-
payload: productNormalized.categoryRetailerInOrder[0],
|
|
218
|
-
});
|
|
219
|
-
setShotThd(
|
|
220
|
-
[58, 59, 60, 61].includes(
|
|
221
|
-
productNormalized.categoryRetailerInOrder[0].id_retailer,
|
|
222
|
-
),
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
// Configurar statusArray según el rol del usuario
|
|
226
|
-
setStatusArray(getStatusArrayByRole(user.id_role));
|
|
227
|
-
|
|
228
|
-
// Cargar usuarios y asignaciones
|
|
229
|
-
const users = await fetchUsers(token);
|
|
230
|
-
if (users.length > 0) {
|
|
231
|
-
dispatch({
|
|
232
|
-
type: "SET_COLLABORATOR_ASSIGNATIONS",
|
|
233
|
-
payload: buildCollaboratorAssignations(productNormalized, users),
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const { id_article } = productNormalized;
|
|
238
|
-
if (id_article) {
|
|
239
|
-
await getAuditVersion(id_article, setAuditableVersion, token);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (id_article && productNormalized.id_order) {
|
|
243
|
-
const response = await axios.get(
|
|
244
|
-
process.env.REACT_APP_READ_OBSERVATION,
|
|
245
|
-
{
|
|
246
|
-
params: {
|
|
247
|
-
articleId: id_article,
|
|
248
|
-
orderId: productNormalized.id_order,
|
|
249
|
-
},
|
|
250
|
-
headers: {
|
|
251
|
-
Authorization: sessionStorage.getItem("jwt"),
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
);
|
|
255
|
-
const parseData = JSON.parse(response.data.body).data[0];
|
|
256
|
-
setObservation(parseData.observations);
|
|
257
|
-
}
|
|
258
|
-
} catch (error) {
|
|
259
|
-
console.log("Error setting product data: ", error);
|
|
260
|
-
}
|
|
358
|
+
const handleCommentSubmit = (e) => {
|
|
359
|
+
e.preventDefault();
|
|
360
|
+
const commentText = document.querySelector(
|
|
361
|
+
"#commentary-box .ql-container .ql-editor > p"
|
|
362
|
+
).innerHTML;
|
|
363
|
+
createComment(e, commentText, activeTab);
|
|
261
364
|
};
|
|
262
365
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
366
|
+
useEffect(async () => {
|
|
367
|
+
const { id_article } = product?.article || {};
|
|
368
|
+
if (id_article)
|
|
369
|
+
await getAuditVersion(id_article, setAuditableVersion, token);
|
|
266
370
|
}, []);
|
|
267
371
|
|
|
268
372
|
const loadAuditableData = async () => {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
373
|
+
if (auditableVersion) {
|
|
374
|
+
const auditServices = await getRetailerServices(
|
|
375
|
+
product?.article?.id_article,
|
|
376
|
+
product?.article?.category,
|
|
377
|
+
parseInt(product?.article?.id_category),
|
|
378
|
+
auditableVersion.version,
|
|
379
|
+
token
|
|
380
|
+
);
|
|
381
|
+
getInputsData(
|
|
382
|
+
auditServices,
|
|
383
|
+
activeRetailer,
|
|
384
|
+
setAuditDatasheets,
|
|
385
|
+
setAuditDescriptions
|
|
386
|
+
);
|
|
387
|
+
setAuditServices(auditServices);
|
|
388
|
+
setAuditImages(auditServices[2]);
|
|
389
|
+
}
|
|
284
390
|
};
|
|
285
391
|
|
|
286
392
|
useEffect(() => {
|
|
@@ -289,438 +395,682 @@ const RetailerProductEditionView = ({
|
|
|
289
395
|
}
|
|
290
396
|
}, [auditableVersion]);
|
|
291
397
|
|
|
292
|
-
|
|
398
|
+
useEffect(() => {
|
|
399
|
+
checkAll && setSelectedImages(images.values);
|
|
400
|
+
}, [checkAll]);
|
|
401
|
+
|
|
402
|
+
const loadData = async () => {
|
|
293
403
|
try {
|
|
294
|
-
|
|
404
|
+
setLoading(true);
|
|
405
|
+
|
|
406
|
+
const ids =
|
|
407
|
+
product?.statusByRetailer?.map((item) => item.retailer_id) ??
|
|
408
|
+
product?.statusByRetailer?.map((item) => item.id_retailer) ??
|
|
409
|
+
[];
|
|
410
|
+
const uniqueIds = [...new Set(ids)];
|
|
411
|
+
|
|
412
|
+
let activeRetailerId = activeRetailer?.id;
|
|
413
|
+
if (!activeRetailerId) {
|
|
414
|
+
const firstValid = product?.article?.categoryRetailer?.find((item) =>
|
|
415
|
+
uniqueIds.includes(item.id_retailer || item.retailer_id)
|
|
416
|
+
);
|
|
417
|
+
if (firstValid) {
|
|
418
|
+
activeRetailerId = firstValid.id_retailer || firstValid.retailer_id;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const categoryRetailer =
|
|
423
|
+
product?.article?.categoryRetailer?.filter(
|
|
424
|
+
(item) =>
|
|
425
|
+
uniqueIds.includes(item.id_retailer) &&
|
|
426
|
+
item.id_retailer === activeRetailerId
|
|
427
|
+
) ??
|
|
428
|
+
product?.article?.categoryRetailer?.filter(
|
|
429
|
+
(item) =>
|
|
430
|
+
uniqueIds.includes(item.retailer_id) &&
|
|
431
|
+
item.retailer_id === activeRetailerId
|
|
432
|
+
) ??
|
|
433
|
+
[];
|
|
434
|
+
|
|
435
|
+
const categoryName = categoryRetailer[0]?.category_name;
|
|
436
|
+
const categoryId = categoryRetailer[0]?.id_category;
|
|
437
|
+
|
|
438
|
+
const category_name =
|
|
439
|
+
categoryName ??
|
|
440
|
+
(product?.article?.company_name || product?.categoryName);
|
|
441
|
+
const category_id =
|
|
442
|
+
categoryId ??
|
|
443
|
+
parseInt(product?.article?.id_category || product?.id_category);
|
|
444
|
+
|
|
445
|
+
const retailer_id = activeRetailerId ?? categoryRetailer?.id_retailer;
|
|
446
|
+
|
|
447
|
+
const services = await getRetailerServices(
|
|
448
|
+
product?.id_article || product?.article?.id_article,
|
|
449
|
+
category_name,
|
|
450
|
+
category_id,
|
|
451
|
+
version,
|
|
452
|
+
token,
|
|
453
|
+
retailer_id
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
if (auditableVersion && retailer_id) {
|
|
457
|
+
loadAuditableData();
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
setServices(services);
|
|
461
|
+
const generalServices = await getServices();
|
|
462
|
+
|
|
463
|
+
setImages({ action: "init", init: services[2] });
|
|
295
464
|
|
|
296
|
-
|
|
297
|
-
const { category, id_category, id_retailer } = state.active_retailer;
|
|
465
|
+
if (services[2]?.values?.length > 0) setActiveImage(0);
|
|
298
466
|
|
|
299
|
-
// Payloads y headers
|
|
300
467
|
const data = [
|
|
301
468
|
{
|
|
302
|
-
id_article,
|
|
303
|
-
version: versionSelected ? versionSelected : version,
|
|
469
|
+
id_article: product?.article?.id_article,
|
|
304
470
|
relations: [
|
|
305
471
|
{
|
|
306
|
-
id_retailer,
|
|
307
|
-
id_category,
|
|
472
|
+
id_retailer: retailer_id,
|
|
473
|
+
id_category: category_id,
|
|
308
474
|
},
|
|
309
475
|
],
|
|
476
|
+
version: product.version,
|
|
310
477
|
},
|
|
311
478
|
];
|
|
312
479
|
|
|
313
480
|
const headers = { Authorization: token };
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
await Promise.all([
|
|
317
|
-
getRetailerServices(
|
|
318
|
-
id_article,
|
|
319
|
-
category,
|
|
320
|
-
id_category,
|
|
321
|
-
versionSelected ?? version,
|
|
322
|
-
token,
|
|
323
|
-
id_retailer,
|
|
324
|
-
),
|
|
325
|
-
getPercentage({ data, headers }),
|
|
326
|
-
getServicesData({
|
|
327
|
-
articleId: id_article,
|
|
328
|
-
orderId: id_order,
|
|
329
|
-
end: true,
|
|
330
|
-
token,
|
|
331
|
-
}),
|
|
332
|
-
// Obtener comentarios en paralelo
|
|
333
|
-
Promise.all([
|
|
334
|
-
axios.get(process.env.REACT_APP_COMMENTS_ENDPOINT, {
|
|
335
|
-
params: {
|
|
336
|
-
articleId: id_article,
|
|
337
|
-
concept: "description",
|
|
338
|
-
orderIdColab: id_order,
|
|
339
|
-
version: versionSelected ?? version,
|
|
340
|
-
},
|
|
341
|
-
}),
|
|
342
|
-
axios.get(process.env.REACT_APP_COMMENTS_ENDPOINT, {
|
|
343
|
-
params: {
|
|
344
|
-
articleId: id_article,
|
|
345
|
-
concept: "datasheet",
|
|
346
|
-
orderIdColab: id_order,
|
|
347
|
-
version: versionSelected ?? version,
|
|
348
|
-
},
|
|
349
|
-
}),
|
|
350
|
-
axios.get(process.env.REACT_APP_COMMENTS_ENDPOINT, {
|
|
351
|
-
params: {
|
|
352
|
-
articleId: id_article,
|
|
353
|
-
concept: "images",
|
|
354
|
-
orderIdColab: id_order,
|
|
355
|
-
version: versionSelected ?? version,
|
|
356
|
-
},
|
|
357
|
-
}),
|
|
358
|
-
]),
|
|
359
|
-
]);
|
|
360
|
-
|
|
361
|
-
dispatch({
|
|
362
|
-
type: "SET_RETAILER_STATUS",
|
|
363
|
-
payload: servicesDataRes.map((service) => ({
|
|
364
|
-
retailer_id: service?.id_retailer,
|
|
365
|
-
service: service?.service,
|
|
366
|
-
status: service?.status,
|
|
367
|
-
task_user_group_id: service?.task_user_group_id,
|
|
368
|
-
})),
|
|
481
|
+
getPercentage({ data, headers }).then((res) => {
|
|
482
|
+
setPercentages(JSON.parse(res?.[0]?.body));
|
|
369
483
|
});
|
|
370
484
|
|
|
371
|
-
|
|
372
|
-
const percentages =
|
|
373
|
-
JSON.parse(percentagesRes?.[0]?.body)?.[0]?.relations ?? [];
|
|
374
|
-
|
|
375
|
-
// Procesar comentarios
|
|
376
|
-
let commentsMap = {};
|
|
377
|
-
commentsResponse.forEach((commentRes) => {
|
|
378
|
-
const commentData = JSON.parse(commentRes?.data?.body).data[0];
|
|
379
|
-
if (commentData) {
|
|
380
|
-
const tab = translateConcept(commentData.concept);
|
|
381
|
-
commentsMap[tab] = commentData;
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
dispatch({ type: "SET_COMMENTS", payload: commentsMap });
|
|
385
|
-
|
|
386
|
-
// Ordenamiento de imágenes
|
|
387
|
-
const orderMap = services[2].inputsByRetailer
|
|
388
|
-
.flat()
|
|
389
|
-
.reduce((acc, item) => {
|
|
390
|
-
acc[item.id_image] = item.order;
|
|
391
|
-
return acc;
|
|
392
|
-
}, {});
|
|
393
|
-
|
|
394
|
-
const orderedValues = [...services[2].values].sort((a, b) => {
|
|
395
|
-
const orderA = orderMap[a.image_id] ?? Number.MAX_SAFE_INTEGER;
|
|
396
|
-
const orderB = orderMap[b.image_id] ?? Number.MAX_SAFE_INTEGER;
|
|
397
|
-
return orderA - orderB;
|
|
398
|
-
});
|
|
485
|
+
setImages({ action: "orderImages", retailerId: activeRetailer.id });
|
|
399
486
|
|
|
400
|
-
|
|
401
|
-
const retailerDatasheets = services[0][id_retailer];
|
|
402
|
-
const datasheetsActiveRetailer = {
|
|
403
|
-
...retailerDatasheets,
|
|
404
|
-
data: Object.values(retailerDatasheets.data),
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
const descriptionsActiveRetailer = services[1].filter(
|
|
408
|
-
(item) => item.id === id_retailer,
|
|
409
|
-
);
|
|
410
|
-
|
|
411
|
-
const filteredValues = services[2].values.filter((value) => {
|
|
412
|
-
return services[2].inputsByRetailer.some((retailerInput) =>
|
|
413
|
-
retailerInput.some(
|
|
414
|
-
(input) =>
|
|
415
|
-
input.id_retailer === id_retailer &&
|
|
416
|
-
input.id_image === value.image_id,
|
|
417
|
-
),
|
|
418
|
-
);
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
// Dispatch consolidado
|
|
422
|
-
dispatch({
|
|
423
|
-
type: "SET_SERVICES",
|
|
424
|
-
payload: {
|
|
425
|
-
datasheets: services[0],
|
|
426
|
-
descriptions: services[1],
|
|
427
|
-
images: {
|
|
428
|
-
...services[2],
|
|
429
|
-
values: orderedValues,
|
|
430
|
-
},
|
|
431
|
-
},
|
|
432
|
-
});
|
|
433
|
-
|
|
434
|
-
dispatch({ type: "SET_PERCENTAGES", payload: percentages });
|
|
435
|
-
dispatch({
|
|
436
|
-
type: "SET_ACTIVE_PERCENTAGES",
|
|
437
|
-
payload: percentages.find(
|
|
438
|
-
({ id_retailer: rId }) => rId === id_retailer,
|
|
439
|
-
),
|
|
440
|
-
});
|
|
441
|
-
dispatch({ type: "SET_SERVICES_DATA", payload: servicesDataRes });
|
|
442
|
-
|
|
443
|
-
// Setear inputs del retailer activo directamente (evita cascada)
|
|
444
|
-
dispatch({
|
|
445
|
-
type: "SET_DATASHEETS_INPUTS",
|
|
446
|
-
payload: [datasheetsActiveRetailer, services[0].inputs],
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
dispatch({
|
|
450
|
-
type: "SET_DESCRIPTIONS_INPUTS",
|
|
451
|
-
payload: descriptionsActiveRetailer,
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
dispatch({
|
|
455
|
-
type: "SET_IMAGES_VALUES",
|
|
456
|
-
payload: {
|
|
457
|
-
...services[2],
|
|
458
|
-
values: filteredValues,
|
|
459
|
-
},
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
// Calcular campos requeridos sin valor
|
|
463
|
-
dispatch({
|
|
464
|
-
type: "SET_MISSING_REQUIRED_FIELDS",
|
|
465
|
-
payload: calculateRequiredNull(services, servicesDataRes, id_retailer),
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
// Auditable
|
|
469
|
-
if (auditableVersion && id_retailer) {
|
|
470
|
-
loadAuditableData();
|
|
471
|
-
}
|
|
487
|
+
setLoading(false);
|
|
472
488
|
} catch (error) {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
} finally {
|
|
476
|
-
dispatch({ type: "SET_LOADING", payload: false });
|
|
489
|
+
setLoading(false);
|
|
490
|
+
console.log(error);
|
|
477
491
|
}
|
|
478
492
|
};
|
|
479
493
|
|
|
480
494
|
useEffect(() => {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
495
|
+
setLoading(true);
|
|
496
|
+
loadData();
|
|
497
|
+
}, [activeRetailer]);
|
|
498
|
+
|
|
499
|
+
const getServices = async () => {
|
|
500
|
+
const servicesResponse = await axios.get(
|
|
501
|
+
`${process.env.REACT_APP_SERVICES_ENDPOINT}?articleId=${
|
|
502
|
+
product?.article?.id_article
|
|
503
|
+
}&orderId=${product?.article?.id_order || product.orderId}&end=true`
|
|
504
|
+
);
|
|
505
|
+
const parsedResponse = JSON.parse(servicesResponse?.data?.body).data;
|
|
485
506
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
507
|
+
const retailers = product.retailers || product.retailersAvailable;
|
|
508
|
+
const retailerResponse = parsedResponse?.map((srv) => srv.id_retailer);
|
|
509
|
+
const active = retailers?.find((retailer) =>
|
|
510
|
+
retailerResponse.includes(retailer.id)
|
|
511
|
+
);
|
|
512
|
+
!activeRetailer.id && setActiveRetailer(active ? active : retailers[0]);
|
|
513
|
+
setServicesData(parsedResponse);
|
|
492
514
|
};
|
|
493
515
|
|
|
494
|
-
const
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
516
|
+
const translateConcept = (concept) => {
|
|
517
|
+
const translation = {
|
|
518
|
+
datasheet: "Ficha técnica",
|
|
519
|
+
description: "Descripción",
|
|
520
|
+
images: "Imágenes",
|
|
521
|
+
};
|
|
522
|
+
return translation[concept];
|
|
500
523
|
};
|
|
501
524
|
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
525
|
+
const getComments = async (tab = "Descripción") => {
|
|
526
|
+
const commentsResponse = await Promise.all([
|
|
527
|
+
axios.get(
|
|
528
|
+
`${process.env.REACT_APP_COMMENTS_ENDPOINT}?articleId=${product?.article?.id_article}&concept=description&orderIdColab=${product?.orderId}&version=${version}`
|
|
529
|
+
),
|
|
530
|
+
axios.get(
|
|
531
|
+
`${process.env.REACT_APP_COMMENTS_ENDPOINT}?articleId=${product?.article?.id_article}&concept=datasheet&orderIdColab=${product?.orderId}&version=${version}`
|
|
532
|
+
),
|
|
533
|
+
axios.get(
|
|
534
|
+
`${process.env.REACT_APP_COMMENTS_ENDPOINT}?articleId=${product?.article?.id_article}&concept=images&orderIdColab=${product?.orderId}&version=${version}`
|
|
535
|
+
),
|
|
536
|
+
]);
|
|
537
|
+
|
|
538
|
+
let comments = {};
|
|
539
|
+
commentsResponse.forEach(
|
|
540
|
+
(comment) =>
|
|
541
|
+
JSON.parse(comment?.data?.body).data[0] &&
|
|
542
|
+
(comments[
|
|
543
|
+
translateConcept(JSON.parse(comment?.data?.body)?.data[0]?.concept)
|
|
544
|
+
] = JSON.parse(comment?.data?.body).data[0])
|
|
545
|
+
);
|
|
546
|
+
setComment(comments[tab]);
|
|
547
|
+
setComments(comments);
|
|
507
548
|
};
|
|
508
549
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
550
|
+
useEffect(async () => {
|
|
551
|
+
setLoading(true);
|
|
552
|
+
// loadData();
|
|
553
|
+
getComments();
|
|
554
|
+
setUserGroups(await fetchUsers(token));
|
|
555
|
+
let arr = [];
|
|
556
|
+
switch (user.id_role) {
|
|
557
|
+
case 7:
|
|
558
|
+
case 8:
|
|
559
|
+
arr = ["PA", "AS", "CA", "RC", "RA", "RP", "RCA"];
|
|
560
|
+
break;
|
|
561
|
+
case 4:
|
|
562
|
+
case 5:
|
|
563
|
+
arr = ["RC", "AC", "AA", "AP", "ACA"];
|
|
564
|
+
break;
|
|
565
|
+
case 6:
|
|
566
|
+
arr = ["RP", "RCA", "AC", "RA"];
|
|
567
|
+
break;
|
|
568
|
+
default:
|
|
569
|
+
arr = [];
|
|
570
|
+
break;
|
|
571
|
+
}
|
|
572
|
+
setStatusArray(arr);
|
|
573
|
+
setLoading(false);
|
|
574
|
+
}, [product, version]);
|
|
575
|
+
|
|
576
|
+
const loadAssignations = (currentProduct) => {
|
|
577
|
+
setAssig({
|
|
578
|
+
Descripción: {
|
|
579
|
+
assignations: [
|
|
580
|
+
{
|
|
581
|
+
collaboratorType: "especialist",
|
|
582
|
+
id: currentProduct?.article?.id_description_especialist,
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
collaboratorType: "facilitator",
|
|
586
|
+
id: currentProduct?.article?.id_description_facilitator,
|
|
587
|
+
},
|
|
588
|
+
],
|
|
589
|
+
collaborators: {
|
|
590
|
+
especialist: userGroups[0] || [],
|
|
591
|
+
facilitator: userGroups[2] || [],
|
|
592
|
+
},
|
|
593
|
+
},
|
|
594
|
+
"Ficha técnica": {
|
|
595
|
+
assignations: [
|
|
596
|
+
{
|
|
597
|
+
collaboratorType: "especialist",
|
|
598
|
+
id: currentProduct?.article?.id_datasheet_especialist,
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
collaboratorType: "facilitator",
|
|
602
|
+
id: currentProduct?.article?.id_datasheet_facilitator,
|
|
603
|
+
},
|
|
604
|
+
],
|
|
605
|
+
collaborators: {
|
|
606
|
+
especialist: userGroups[0] || [],
|
|
607
|
+
facilitator: userGroups[2] || [],
|
|
608
|
+
},
|
|
609
|
+
},
|
|
610
|
+
Imágenes: {
|
|
611
|
+
assignations: [
|
|
612
|
+
{
|
|
613
|
+
collaboratorType: "especialist",
|
|
614
|
+
id: currentProduct?.article?.id_images_especialist,
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
collaboratorType: "facilitator",
|
|
618
|
+
id: currentProduct?.article?.id_images_facilitator,
|
|
619
|
+
},
|
|
620
|
+
],
|
|
621
|
+
collaborators: {
|
|
622
|
+
especialist: userGroups[1] || [],
|
|
623
|
+
facilitator: userGroups[3] || [],
|
|
624
|
+
},
|
|
625
|
+
},
|
|
513
626
|
});
|
|
514
627
|
};
|
|
515
628
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
};
|
|
629
|
+
useEffect(() => {
|
|
630
|
+
loadAssignations(product);
|
|
631
|
+
}, [userGroups]);
|
|
519
632
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
633
|
+
useEffect(() => {
|
|
634
|
+
const retailerPercentages =
|
|
635
|
+
percentages?.[0]?.relations?.[0]?.percentagesGeneral;
|
|
636
|
+
|
|
637
|
+
const requiredPercentage = retailerPercentages?.required;
|
|
638
|
+
|
|
639
|
+
setActivePercentage(requiredPercentage);
|
|
640
|
+
|
|
641
|
+
// const retailers = product?.retailersAvailable || product?.retailers;
|
|
642
|
+
// if (
|
|
643
|
+
// Object.keys(percentages[product.article.id_article] ?? {})?.length > 0
|
|
644
|
+
// ) {
|
|
645
|
+
// retailers?.forEach((retailer, index) => {
|
|
646
|
+
// retailer["percentage"] = Number(
|
|
647
|
+
// percentages[product.article.id_article][retailer.id]
|
|
648
|
+
// ?.percentageRequired
|
|
649
|
+
// );
|
|
650
|
+
// });
|
|
651
|
+
// }
|
|
652
|
+
// setActivePercentage(retailers[0]?.percentage);
|
|
653
|
+
}, [percentages]);
|
|
523
654
|
|
|
524
|
-
|
|
525
|
-
|
|
655
|
+
useEffect(() => {
|
|
656
|
+
getInputsData(services, activeRetailer, setDatasheets, setDescriptions);
|
|
657
|
+
auditableVersion && loadAuditableData();
|
|
658
|
+
setActivePercentage(Math.round(activeRetailer?.percentage, 0));
|
|
659
|
+
activeRetailer?.id &&
|
|
660
|
+
setImages({ action: "orderImages", retailerId: activeRetailer.id });
|
|
661
|
+
}, [activeRetailer, services]);
|
|
662
|
+
|
|
663
|
+
const thumbs = () => {
|
|
664
|
+
const imageInputs = socketType?.slice();
|
|
665
|
+
const imageType = images?.imageType?.map((e) => ({
|
|
666
|
+
value: e?.id,
|
|
667
|
+
name: e?.name,
|
|
668
|
+
}));
|
|
669
|
+
const imagePackagingType = images?.imagePackagingType?.map((e) => ({
|
|
670
|
+
value: e?.id,
|
|
671
|
+
name: e?.name,
|
|
672
|
+
}));
|
|
673
|
+
const imageShotType = images?.imageShotType?.map((e) => ({
|
|
674
|
+
value: e?.id,
|
|
675
|
+
name: e?.type_shot,
|
|
676
|
+
}));
|
|
677
|
+
return images?.values?.map((image, index) => (
|
|
678
|
+
<GalleryElement
|
|
679
|
+
setCheckAll={setCheckAll}
|
|
680
|
+
key={index + "-" + image.name}
|
|
681
|
+
image={image}
|
|
682
|
+
gridLayout={imageLayout}
|
|
683
|
+
id={"gallery-element-" + index}
|
|
684
|
+
index={index + "-" + image.name + "-" + compare}
|
|
685
|
+
number={index}
|
|
686
|
+
imageType={imageType}
|
|
687
|
+
imagePackagingType={imagePackagingType}
|
|
688
|
+
imageInputs={imageInputs}
|
|
689
|
+
imageShotType={imageShotType}
|
|
690
|
+
setSocketType={setSocketType}
|
|
691
|
+
changeImage={setImages}
|
|
692
|
+
selectedImages={selectedImages}
|
|
693
|
+
setSelectedImages={setSelectedImages}
|
|
694
|
+
auditImages={auditImages}
|
|
695
|
+
compare={compare}
|
|
696
|
+
/>
|
|
697
|
+
));
|
|
526
698
|
};
|
|
527
699
|
|
|
528
|
-
const
|
|
529
|
-
|
|
700
|
+
const saveDescriptions = async () => {
|
|
701
|
+
const dataClean = updatedDescriptions.filter((f) => f.value !== "");
|
|
702
|
+
if (dataClean.length > 0) {
|
|
703
|
+
setLoading(true);
|
|
704
|
+
const productTemp = product;
|
|
705
|
+
const articleId = product?.article?.id_article;
|
|
706
|
+
const dataObject = {
|
|
707
|
+
articleId,
|
|
708
|
+
articleData: dataClean,
|
|
709
|
+
};
|
|
710
|
+
if (product?.orderId) dataObject["orderId"] = product?.orderId;
|
|
711
|
+
try {
|
|
712
|
+
const res = await axios.put(
|
|
713
|
+
`${process.env.REACT_APP_ARTICLE_DATA_ENDPOINT}?description=true&version=${version}`,
|
|
714
|
+
dataObject,
|
|
715
|
+
{
|
|
716
|
+
headers: {
|
|
717
|
+
Authorization: token,
|
|
718
|
+
},
|
|
719
|
+
}
|
|
720
|
+
);
|
|
721
|
+
if (res.data.statusCode === 200) {
|
|
722
|
+
const { newStatus, newArticleStatus } = JSON.parse(res.data.body);
|
|
723
|
+
if (newArticleStatus)
|
|
724
|
+
productTemp.status = newArticleStatus[articleId];
|
|
725
|
+
if (newStatus) productTemp.description_status = newStatus;
|
|
726
|
+
setProduct(productTemp);
|
|
727
|
+
sessionStorage.setItem(
|
|
728
|
+
"productSelected",
|
|
729
|
+
JSON.stringify(productTemp)
|
|
730
|
+
);
|
|
731
|
+
|
|
732
|
+
setUpdatedDescriptions([]);
|
|
733
|
+
setMessage("Descripciones guardadas con éxito");
|
|
734
|
+
await loadData();
|
|
735
|
+
}
|
|
736
|
+
} catch (error) {
|
|
737
|
+
console.log(error);
|
|
738
|
+
} finally {
|
|
739
|
+
setLoading(false);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
530
742
|
};
|
|
531
743
|
|
|
532
|
-
const
|
|
533
|
-
const
|
|
744
|
+
const saveDatasheets = async () => {
|
|
745
|
+
const dataClean = updatedDatasheets.filter((f) => f.value !== "");
|
|
746
|
+
if (dataClean.length > 0) {
|
|
747
|
+
setLoading(true);
|
|
748
|
+
const productTemp = product;
|
|
749
|
+
const articleId = product?.article?.id_article;
|
|
750
|
+
const dataObject = {
|
|
751
|
+
articleId,
|
|
752
|
+
articleData: dataClean,
|
|
753
|
+
};
|
|
754
|
+
if (product?.orderId) dataObject["orderId"] = product?.orderId;
|
|
755
|
+
try {
|
|
756
|
+
const res = await axios.put(
|
|
757
|
+
`${process.env.REACT_APP_ARTICLE_DATA_ENDPOINT}?datasheet=true&version=${version}`,
|
|
758
|
+
dataObject,
|
|
759
|
+
{
|
|
760
|
+
headers: {
|
|
761
|
+
Authorization: token,
|
|
762
|
+
},
|
|
763
|
+
}
|
|
764
|
+
);
|
|
765
|
+
if (res.data.statusCode === 200) {
|
|
766
|
+
const { newStatus, newArticleStatus } = JSON.parse(res.data.body);
|
|
767
|
+
if (newArticleStatus)
|
|
768
|
+
productTemp.status = newArticleStatus[articleId];
|
|
769
|
+
if (newStatus) productTemp.datasheet_status = newStatus;
|
|
770
|
+
setProduct(productTemp);
|
|
771
|
+
sessionStorage.setItem(
|
|
772
|
+
"productSelected",
|
|
773
|
+
JSON.stringify(productTemp)
|
|
774
|
+
);
|
|
775
|
+
setUpdatedDatasheets([]);
|
|
776
|
+
setMessage("Fichas técnicas guardadas");
|
|
777
|
+
await loadData();
|
|
778
|
+
}
|
|
779
|
+
} catch (error) {
|
|
780
|
+
console.log(error);
|
|
781
|
+
} finally {
|
|
782
|
+
setLoading(false);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
};
|
|
534
786
|
|
|
535
|
-
|
|
536
|
-
const
|
|
787
|
+
useEffect(() => {
|
|
788
|
+
const imageInputs = images?.inputs?.map((e) => ({
|
|
789
|
+
value: e?.id,
|
|
790
|
+
name: e?.name,
|
|
791
|
+
required: e?.required,
|
|
792
|
+
active: images?.values?.some((value) => value?.image_id === e?.id),
|
|
793
|
+
}));
|
|
794
|
+
setSocketType(imageInputs);
|
|
795
|
+
}, [images]);
|
|
796
|
+
|
|
797
|
+
const updateImages = useCallback(async () => {
|
|
798
|
+
const imagesList = images?.values?.slice();
|
|
799
|
+
const imagesListTemp = imagesList?.reduce((acc, image) => {
|
|
800
|
+
acc[image?.image_id] = ++acc[image?.image_id] || 0;
|
|
801
|
+
return acc;
|
|
802
|
+
}, {});
|
|
803
|
+
|
|
804
|
+
const duplicated = imagesList?.filter((image) => {
|
|
805
|
+
return imagesListTemp[image?.image_id];
|
|
806
|
+
});
|
|
537
807
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
808
|
+
const attrForImgs = Object.values(images?.attrForImgs ?? {}).pop();
|
|
809
|
+
const data = {
|
|
810
|
+
articleId: product?.article?.id_article,
|
|
811
|
+
attrReqImgs: attrForImgs?.map((e) => ({
|
|
812
|
+
attrId: e.id,
|
|
813
|
+
value: e.value ?? "-",
|
|
814
|
+
})),
|
|
815
|
+
articleData: imagesList?.filter((e) => !e.id),
|
|
816
|
+
updateImages: imagesList?.filter((e) => e.id),
|
|
817
|
+
};
|
|
818
|
+
if (product?.orderId) data["orderId"] = product?.orderId;
|
|
819
|
+
let valid =
|
|
820
|
+
data?.articleData?.length === 0
|
|
821
|
+
? true
|
|
822
|
+
: data?.articleData?.every((e, i) => {
|
|
823
|
+
// if (e?.image_id && e?.packing_type && e?.image_type) {
|
|
824
|
+
if (e?.image_id) {
|
|
825
|
+
return true;
|
|
826
|
+
}
|
|
827
|
+
return false;
|
|
828
|
+
});
|
|
829
|
+
if (valid && data?.updateImages?.length > 0 && duplicated?.length === 0) {
|
|
830
|
+
valid = data?.updateImages?.every((e, i) => {
|
|
831
|
+
// if (e?.image_id && e?.packing_type && e?.image_type) {
|
|
832
|
+
if (e?.image_id) {
|
|
833
|
+
return true;
|
|
834
|
+
}
|
|
835
|
+
return false;
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
if (valid && duplicated?.length === 0) {
|
|
839
|
+
setLoading(true);
|
|
840
|
+
try {
|
|
841
|
+
data?.articleData?.forEach((e) => {
|
|
842
|
+
e.uuid = uuidv4();
|
|
843
|
+
});
|
|
844
|
+
setDataImages(data);
|
|
845
|
+
if (data?.articleData?.length > 0) {
|
|
846
|
+
setImagesUploaded(false);
|
|
847
|
+
const promiseArray = [];
|
|
848
|
+
data?.articleData?.forEach((e) => {
|
|
849
|
+
let file;
|
|
850
|
+
if (e.ext == "mp4") {
|
|
851
|
+
file = Buffer.from(
|
|
852
|
+
e.video_src.replace(/^data:video\/\w+;base64,/, ""),
|
|
853
|
+
"base64"
|
|
854
|
+
);
|
|
855
|
+
e.video_src = "";
|
|
856
|
+
} else {
|
|
857
|
+
file = Buffer.from(
|
|
858
|
+
e.src.replace(/^data:image\/\w+;base64,/, ""),
|
|
859
|
+
"base64"
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
const params = {
|
|
863
|
+
ACL: "public-read",
|
|
864
|
+
Body: file,
|
|
865
|
+
Bucket: S3_BUCKET,
|
|
866
|
+
Key: `id-${data.articleId}/${version}/${e?.image_id}-${e?.uuid}.${e?.ext}`,
|
|
867
|
+
};
|
|
868
|
+
promiseArray.push(myBucket.putObject(params).promise());
|
|
869
|
+
});
|
|
870
|
+
await Promise.all(promiseArray);
|
|
871
|
+
setImagesUploaded(true);
|
|
872
|
+
} else {
|
|
873
|
+
setImagesUploaded(true);
|
|
874
|
+
}
|
|
875
|
+
} catch (err) {
|
|
876
|
+
console.log(err);
|
|
877
|
+
// setMainLoading(false);
|
|
878
|
+
} finally {
|
|
879
|
+
setLoading(false);
|
|
544
880
|
}
|
|
881
|
+
} else {
|
|
882
|
+
// setMainLoading(false);
|
|
883
|
+
setMessage(
|
|
884
|
+
"Completa los campos que solicita cada una de la imágenes o hay imágenes con el mismo tipo de toma.\nRecuerda hay campos obligatorios y no podras avanzar si no estan completos."
|
|
885
|
+
);
|
|
545
886
|
}
|
|
887
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
888
|
+
}, [images, imagesUploaded]);
|
|
889
|
+
|
|
890
|
+
useEffect(async () => {
|
|
891
|
+
if (imagesUploaded) {
|
|
892
|
+
dataImages.articleData = dataImages?.articleData.map((e) => {
|
|
893
|
+
delete e.src;
|
|
894
|
+
e.imageID = e.image_id;
|
|
895
|
+
// e.packingType = e.packing_type;
|
|
896
|
+
// e.imageType = e.image_type;
|
|
897
|
+
if (product?.orderId) e["orderId"] = product?.orderId;
|
|
898
|
+
return e;
|
|
899
|
+
});
|
|
900
|
+
try {
|
|
901
|
+
const res = await axios.put(
|
|
902
|
+
`${process.env.REACT_APP_ARTICLE_DATA_ENDPOINT}?image=true&version=${version}`,
|
|
903
|
+
dataImages,
|
|
904
|
+
{
|
|
905
|
+
headers: {
|
|
906
|
+
Authorization: token,
|
|
907
|
+
},
|
|
908
|
+
}
|
|
909
|
+
);
|
|
910
|
+
if (res.data.statusCode === 200) {
|
|
911
|
+
let productTemp = product;
|
|
912
|
+
const { newStatus, newArticleStatus } = JSON.parse(res.data.body);
|
|
913
|
+
if (newArticleStatus)
|
|
914
|
+
productTemp.status = newArticleStatus[product?.article?.id_article];
|
|
915
|
+
if (newStatus) productTemp.images_status = newStatus;
|
|
916
|
+
setProduct(productTemp);
|
|
917
|
+
sessionStorage.setItem(
|
|
918
|
+
"productSelected",
|
|
919
|
+
JSON.stringify(productTemp)
|
|
920
|
+
);
|
|
921
|
+
setImages({});
|
|
922
|
+
setMessage("Imágenes guardadas con éxito");
|
|
923
|
+
sessionStorage.removeItem("imagesList");
|
|
924
|
+
}
|
|
925
|
+
await loadData();
|
|
926
|
+
} catch (error) {
|
|
927
|
+
console.log(error);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}, [dataImages, imagesUploaded]);
|
|
546
931
|
|
|
547
|
-
|
|
548
|
-
const
|
|
549
|
-
const
|
|
932
|
+
const evaluationFinished = (userId, tab, statusArray) => {
|
|
933
|
+
const srv = servicesData.filter((serv) => serv.service === getConcept(tab));
|
|
934
|
+
const srvActive = srv
|
|
935
|
+
.find((serv) => serv.id_retailer === activeRetailer?.id)
|
|
936
|
+
?.status?.replace(/.*\//, "");
|
|
937
|
+
const currStatus = product[`${getConcept(tab)}_status`]?.replace(
|
|
938
|
+
/.*\//,
|
|
939
|
+
""
|
|
940
|
+
);
|
|
941
|
+
const unvalidated = ["IE", "CA"].includes(currStatus);
|
|
942
|
+
|
|
943
|
+
const auditorUnvalidated = !["RA", "AA", "ACA", "AP"].includes(currStatus);
|
|
944
|
+
|
|
945
|
+
switch (userId) {
|
|
946
|
+
case 7:
|
|
947
|
+
case 8:
|
|
948
|
+
return (
|
|
949
|
+
(statusArray.includes(srvActive) &&
|
|
950
|
+
statusArray.includes(product?.status)) ||
|
|
951
|
+
srv.filter((serv) =>
|
|
952
|
+
statusArray.includes(serv.status?.replace(/.*\//, ""))
|
|
953
|
+
).length === srv.length
|
|
954
|
+
);
|
|
955
|
+
case 4:
|
|
956
|
+
case 5:
|
|
957
|
+
return (
|
|
958
|
+
unvalidated &&
|
|
959
|
+
["CA", "IE"].includes(product.status) && // "RC", "AC", "AA", "AP", "ACA"
|
|
960
|
+
srv.filter((serv) => statusArray.includes(serv.status)).length ===
|
|
961
|
+
srv.length
|
|
962
|
+
);
|
|
963
|
+
case 6:
|
|
964
|
+
return (
|
|
965
|
+
statusArray.includes(product.status) && // RP, RCA, AC, RA true
|
|
966
|
+
srv.every((serv) =>
|
|
967
|
+
["RA", "AA", "AP", "ACA"].includes(serv.status)
|
|
968
|
+
) &&
|
|
969
|
+
auditorUnvalidated
|
|
970
|
+
);
|
|
971
|
+
default:
|
|
972
|
+
break;
|
|
973
|
+
}
|
|
974
|
+
};
|
|
550
975
|
|
|
551
|
-
|
|
976
|
+
const getConcept = (tab) => {
|
|
977
|
+
switch (tab) {
|
|
978
|
+
case "Descripción":
|
|
979
|
+
return "description";
|
|
980
|
+
case "Ficha técnica":
|
|
981
|
+
return "datasheet";
|
|
982
|
+
case "Imágenes":
|
|
983
|
+
return "images";
|
|
984
|
+
}
|
|
552
985
|
};
|
|
553
986
|
|
|
554
|
-
const
|
|
555
|
-
let concept =
|
|
987
|
+
const approveRejectButtons = (action) => {
|
|
988
|
+
let concept = getConcept(action || activeTab);
|
|
556
989
|
|
|
557
|
-
const retailerStatus =
|
|
558
|
-
|
|
990
|
+
const retailerStatus = servicesData
|
|
991
|
+
.find(
|
|
559
992
|
(srv) =>
|
|
560
|
-
srv.id_retailer ===
|
|
561
|
-
srv.service === concept,
|
|
993
|
+
srv.id_retailer === activeRetailer?.id && srv.service === concept
|
|
562
994
|
)
|
|
563
995
|
?.status?.replace(/.*\//, "");
|
|
564
996
|
|
|
997
|
+
//sessionStorage product
|
|
565
998
|
const adminFacilitatorCanEvaluate =
|
|
566
999
|
retailerStatus === "IE" && [1, 4, 5].includes(user.id_role);
|
|
567
1000
|
const adminAuditorCanEvaluate =
|
|
568
1001
|
["AC", "RP", "RCA", "SAC"].includes(retailerStatus) &&
|
|
569
1002
|
[1, 6].includes(user.id_role);
|
|
570
|
-
|
|
571
1003
|
return adminFacilitatorCanEvaluate || adminAuditorCanEvaluate;
|
|
572
1004
|
};
|
|
573
1005
|
|
|
574
|
-
const
|
|
575
|
-
|
|
1006
|
+
const approveRejectAllButtons = () => {
|
|
1007
|
+
let concepts = [];
|
|
1008
|
+
switch (user.id_role) {
|
|
1009
|
+
case 4:
|
|
1010
|
+
concepts = ["description", "datasheet"];
|
|
1011
|
+
break;
|
|
1012
|
+
case 5:
|
|
1013
|
+
concepts = ["images"];
|
|
1014
|
+
break;
|
|
576
1015
|
|
|
577
|
-
|
|
578
|
-
|
|
1016
|
+
default:
|
|
1017
|
+
concepts = ["description", "datasheet", "images"];
|
|
1018
|
+
break;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
const services = servicesData.filter(({ service }) =>
|
|
1022
|
+
concepts.includes(service)
|
|
579
1023
|
);
|
|
580
1024
|
|
|
581
1025
|
const adminFacilitatorCanEvaluate =
|
|
582
1026
|
services.every((srv) => srv?.status?.replace(/.*\//, "") === "IE") &&
|
|
583
1027
|
[1, 4, 5].includes(user.id_role);
|
|
584
1028
|
|
|
1029
|
+
//sessionStorage product
|
|
585
1030
|
const adminAuditorCanEvaluate =
|
|
586
|
-
|
|
587
|
-
["AC", "RP", "RCA"].includes(srv?.status?.replace(/.*\//, ""))
|
|
1031
|
+
servicesData.every((srv) =>
|
|
1032
|
+
["AC", "RP", "RCA"].includes(srv?.status?.replace(/.*\//, ""))
|
|
588
1033
|
) && [1, 6].includes(user.id_role);
|
|
589
1034
|
return adminFacilitatorCanEvaluate || adminAuditorCanEvaluate;
|
|
590
1035
|
};
|
|
591
1036
|
|
|
592
|
-
const
|
|
593
|
-
|
|
594
|
-
if (!statusByRetailer) return "-";
|
|
595
|
-
|
|
596
|
-
const currentService = getConceptByTab(state.active_tab);
|
|
597
|
-
const currentRetailer = state.active_retailer.id_retailer;
|
|
598
|
-
const currentStatus =
|
|
599
|
-
statusByRetailer.filter(
|
|
600
|
-
(item) =>
|
|
601
|
-
item.retailer_id === currentRetailer &&
|
|
602
|
-
item.service === currentService,
|
|
603
|
-
)[0]?.status || "-";
|
|
604
|
-
|
|
605
|
-
return currentStatus;
|
|
606
|
-
};
|
|
607
|
-
|
|
608
|
-
const handleOnClickSaveImages = () => {
|
|
609
|
-
if (state.product?.services?.images === 1) {
|
|
610
|
-
saveImageAttrs(token);
|
|
611
|
-
}
|
|
612
|
-
};
|
|
613
|
-
|
|
614
|
-
const handleOnClickSave = async () => {
|
|
615
|
-
if (state.saving) return;
|
|
616
|
-
|
|
617
|
-
switch (state.active_tab) {
|
|
618
|
-
case "Descripción":
|
|
619
|
-
await saveDescriptions(token);
|
|
620
|
-
break;
|
|
1037
|
+
const getSectionIcon = () => {
|
|
1038
|
+
switch (activeTab) {
|
|
621
1039
|
case "Ficha técnica":
|
|
622
|
-
|
|
1040
|
+
setIcon(attributesSent);
|
|
1041
|
+
break;
|
|
1042
|
+
case "Descripción":
|
|
1043
|
+
setIcon(descriptionSent);
|
|
623
1044
|
break;
|
|
624
1045
|
case "Imágenes":
|
|
625
|
-
|
|
1046
|
+
setIcon(imagesSent);
|
|
626
1047
|
break;
|
|
627
1048
|
default:
|
|
628
1049
|
break;
|
|
629
1050
|
}
|
|
630
|
-
|
|
631
|
-
await loadData(false);
|
|
632
|
-
};
|
|
633
|
-
|
|
634
|
-
const handleOnSetUpdatedDescriptions = (items) => {
|
|
635
|
-
dispatch({
|
|
636
|
-
type: "SET_UPDATED_DESCRIPTIONS_INPUTS",
|
|
637
|
-
payload: items,
|
|
638
|
-
});
|
|
639
|
-
};
|
|
640
|
-
|
|
641
|
-
const handleOnSetUpdatedDatasheets = (items) => {
|
|
642
|
-
dispatch({
|
|
643
|
-
type: "SET_UPDATED_DATASHEETS_INPUTS",
|
|
644
|
-
payload: items,
|
|
645
|
-
});
|
|
646
|
-
};
|
|
647
|
-
|
|
648
|
-
const handleOnAskToDeleteImages = () => {
|
|
649
|
-
if (state.selected_images.length === 0) {
|
|
650
|
-
dispatch({
|
|
651
|
-
type: "SET_MODAL",
|
|
652
|
-
payload: {
|
|
653
|
-
show: true,
|
|
654
|
-
title: "Eliminar imágenes",
|
|
655
|
-
message: "No has seleccionado ninguna imagen para eliminar.",
|
|
656
|
-
image: warningIcon,
|
|
657
|
-
},
|
|
658
|
-
});
|
|
659
|
-
return;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
dispatch({
|
|
663
|
-
type: "SET_MODAL",
|
|
664
|
-
payload: {
|
|
665
|
-
show: true,
|
|
666
|
-
title: "Eliminar imágenes",
|
|
667
|
-
message:
|
|
668
|
-
"¿Estás seguro de que deseas eliminar las imágenes seleccionadas?",
|
|
669
|
-
image: warningIcon,
|
|
670
|
-
buttons: [
|
|
671
|
-
{
|
|
672
|
-
text: "Cancelar",
|
|
673
|
-
buttonType: "general-white-button",
|
|
674
|
-
action: () =>
|
|
675
|
-
dispatch({ type: "SET_MODAL", payload: { show: false } }),
|
|
676
|
-
},
|
|
677
|
-
{
|
|
678
|
-
text: "Eliminar",
|
|
679
|
-
buttonType: "general-button-default",
|
|
680
|
-
action: () => {
|
|
681
|
-
dispatch({ type: "SET_MODAL", payload: { show: false } });
|
|
682
|
-
deleteImages(token);
|
|
683
|
-
},
|
|
684
|
-
},
|
|
685
|
-
],
|
|
686
|
-
},
|
|
687
|
-
});
|
|
688
|
-
};
|
|
689
|
-
|
|
690
|
-
const handleOnApproveSingleService = async () => {
|
|
691
|
-
await sendSingleEvaluation("A");
|
|
692
1051
|
};
|
|
693
1052
|
|
|
694
|
-
const
|
|
695
|
-
|
|
696
|
-
};
|
|
697
|
-
|
|
698
|
-
const sendSingleEvaluation = async (result) => {
|
|
699
|
-
if (state.saving) return;
|
|
700
|
-
|
|
701
|
-
dispatch({ type: "SET_SAVING", payload: true });
|
|
702
|
-
|
|
703
|
-
const concept = getConceptByTab(state.active_tab);
|
|
704
|
-
|
|
705
|
-
const articleId = state.product.id_article;
|
|
706
|
-
const orderId = state.product.id_order ?? state.product.orderId;
|
|
707
|
-
const sectionStatusKey = `${concept}_status`;
|
|
708
|
-
const evalStatus = state.product[sectionStatusKey];
|
|
709
|
-
const retailerId = state.active_retailer?.id_retailer;
|
|
710
|
-
|
|
711
|
-
let data = { articleId, orderId, concept, evalStatus, retailerId };
|
|
712
|
-
let res;
|
|
713
|
-
let message;
|
|
714
|
-
let icon;
|
|
715
|
-
|
|
716
|
-
const activeTab = state.active_tab;
|
|
717
|
-
|
|
1053
|
+
const sendToFacilitator = async (result) => {
|
|
1054
|
+
if (!loading) setLoading(true);
|
|
718
1055
|
try {
|
|
719
|
-
|
|
1056
|
+
let concept = getConcept(activeTab);
|
|
1057
|
+
|
|
1058
|
+
const productTemp = { ...product };
|
|
1059
|
+
const evalStatus = retailerStatus;
|
|
1060
|
+
const articleId = product.article.id_article;
|
|
1061
|
+
const orderId = product.orderId;
|
|
1062
|
+
|
|
1063
|
+
let data = {
|
|
1064
|
+
articleId,
|
|
1065
|
+
orderId,
|
|
1066
|
+
concept,
|
|
1067
|
+
evalStatus,
|
|
1068
|
+
retailerId: activeRetailer.id,
|
|
1069
|
+
};
|
|
1070
|
+
let res;
|
|
1071
|
+
let message;
|
|
720
1072
|
if (result) {
|
|
721
1073
|
data.result = result;
|
|
722
|
-
data.retailerId = retailerId;
|
|
723
|
-
|
|
724
1074
|
res = await axios.put(
|
|
725
1075
|
`${process.env.REACT_APP_EVALUATION_ENDPOINT}`,
|
|
726
1076
|
data,
|
|
@@ -728,285 +1078,254 @@ const RetailerProductEditionView = ({
|
|
|
728
1078
|
headers: {
|
|
729
1079
|
Authorization: token,
|
|
730
1080
|
},
|
|
731
|
-
}
|
|
732
|
-
);
|
|
733
|
-
|
|
734
|
-
const newStatuses = JSON.parse(res.data.body);
|
|
735
|
-
const serviceStatus =
|
|
736
|
-
newStatuses.newServiceStatus[articleId][`${concept}Status`];
|
|
737
|
-
|
|
738
|
-
// Actualizar el producto con los nuevos estados
|
|
739
|
-
const updatedStatusByRetailer = state.product.statusByRetailer.map(
|
|
740
|
-
(item) =>
|
|
741
|
-
item.retailer_id === retailerId && item.service === concept
|
|
742
|
-
? { ...item, status: serviceStatus }
|
|
743
|
-
: item,
|
|
1081
|
+
}
|
|
744
1082
|
);
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
...state.product,
|
|
748
|
-
statusByRetailer: updatedStatusByRetailer,
|
|
749
|
-
};
|
|
750
|
-
|
|
751
|
-
dispatch({ type: "SET_PRODUCT", payload: updatedProduct });
|
|
752
|
-
|
|
753
|
-
// Mostrar modal de éxito
|
|
754
|
-
dispatch({
|
|
755
|
-
type: "SET_MODAL",
|
|
756
|
-
payload: {
|
|
757
|
-
show: true,
|
|
758
|
-
title: "",
|
|
759
|
-
message:
|
|
760
|
-
result === "A" ? "Aprobado con éxito" : "Rechazado con éxito",
|
|
761
|
-
image: successIcon,
|
|
762
|
-
},
|
|
763
|
-
});
|
|
764
|
-
} else { //Caso del botón "Enviar evaluación"
|
|
765
|
-
|
|
766
|
-
//Se construye el mensaje y se actualiza el estatus
|
|
767
|
-
|
|
1083
|
+
getServices();
|
|
1084
|
+
} else {
|
|
768
1085
|
const specialistDone = ["RC", "RA", "CA"].includes(evalStatus);
|
|
769
1086
|
|
|
770
1087
|
if (specialistDone) {
|
|
771
1088
|
message = `${activeTab} enviada a facilitador`;
|
|
772
|
-
|
|
773
|
-
activeTab === "Descripción"
|
|
774
|
-
? descriptionSent
|
|
775
|
-
: activeTab === "Ficha técnica"
|
|
776
|
-
? attributesSent
|
|
777
|
-
: imagesSent;
|
|
1089
|
+
getSectionIcon();
|
|
778
1090
|
} else if (["IE", "AC", "RP", "RCA"].includes(evalStatus)) {
|
|
779
1091
|
message = "Evaluación enviada";
|
|
780
|
-
|
|
1092
|
+
getSectionIcon();
|
|
781
1093
|
}
|
|
782
|
-
|
|
783
1094
|
res = await axios.put(`${process.env.REACT_APP_SEND_EVAL}`, data, {
|
|
784
1095
|
headers: {
|
|
785
1096
|
Authorization: token,
|
|
786
1097
|
},
|
|
787
1098
|
});
|
|
788
1099
|
}
|
|
789
|
-
|
|
790
1100
|
if (res.data.statusCode === 200) {
|
|
1101
|
+
const { newStatus, newOrderStatus, newArticleStatus } = JSON.parse(
|
|
1102
|
+
res.data.body
|
|
1103
|
+
);
|
|
1104
|
+
const messageToChat = createMessage(
|
|
1105
|
+
product.retailers,
|
|
1106
|
+
activeRetailer.id,
|
|
1107
|
+
evalStatus,
|
|
1108
|
+
newStatus,
|
|
1109
|
+
activeTab
|
|
1110
|
+
);
|
|
791
1111
|
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
// evalStatus,
|
|
802
|
-
// newStatus,
|
|
803
|
-
// activeTab,
|
|
804
|
-
// );
|
|
805
|
-
|
|
806
|
-
// const messageData = {
|
|
807
|
-
// paramsBody: {
|
|
808
|
-
// id: articleId,
|
|
809
|
-
// version: state.product.version,
|
|
810
|
-
// items: [{ type: "status", value: messageToChat }],
|
|
811
|
-
// retailerId: retailerId,
|
|
812
|
-
// status: state.product.status,
|
|
813
|
-
// },
|
|
814
|
-
// paramsHeader: { Authorization: token },
|
|
815
|
-
// };
|
|
816
|
-
// await sendMessage(messageData);
|
|
817
|
-
|
|
818
|
-
const updatedProduct = {
|
|
819
|
-
...state.product,
|
|
820
|
-
[`${concept}_status`]: newStatus,
|
|
821
|
-
// actualizar el status es statusByRetailer
|
|
822
|
-
statusByRetailer: state.product.statusByRetailer.map((item) => {
|
|
823
|
-
if (item.retailer_id === retailerId && item.service === concept) {
|
|
824
|
-
return { ...item, status: newStatus };
|
|
825
|
-
}
|
|
826
|
-
return item;
|
|
827
|
-
}),
|
|
1112
|
+
const data = {
|
|
1113
|
+
paramsBody: {
|
|
1114
|
+
id: product.article.id_article,
|
|
1115
|
+
version: version,
|
|
1116
|
+
items: [{ type: "status", value: messageToChat }],
|
|
1117
|
+
retailerId: activeRetailer.id,
|
|
1118
|
+
status: product.status,
|
|
1119
|
+
},
|
|
1120
|
+
paramsHeader: { Authorization: token },
|
|
828
1121
|
};
|
|
1122
|
+
await sendMessage(data);
|
|
1123
|
+
if (newOrderStatus) productTemp.status = newArticleStatus[articleId];
|
|
1124
|
+
productTemp[`${concept}_status`] = newStatus;
|
|
1125
|
+
await loadData();
|
|
1126
|
+
if (message) setMessage(message);
|
|
1127
|
+
sessionStorage.setItem("productSelected", JSON.stringify(productTemp));
|
|
1128
|
+
setProduct(productTemp);
|
|
1129
|
+
}
|
|
1130
|
+
} catch (error) {
|
|
1131
|
+
setLoading(false);
|
|
1132
|
+
console.log(error);
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
829
1135
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
const updatedServicesData = state.services_data?.map(service => ({
|
|
833
|
-
...service,
|
|
834
|
-
status: service?.id_retailer === retailerId && service?.service === concept ? newStatus : service?.status
|
|
835
|
-
}));
|
|
836
|
-
|
|
837
|
-
const sessionProduct = sessionStorage.getItem("productSelected");
|
|
838
|
-
|
|
839
|
-
if (sessionProduct) {
|
|
840
|
-
const productInSession = JSON.parse(sessionProduct);
|
|
841
|
-
const updatedProductInSession = {
|
|
842
|
-
...productInSession,
|
|
843
|
-
[`${concept}_status`]: newStatus,
|
|
844
|
-
statusByRetailer: state.product.statusByRetailer.map((item) => {
|
|
845
|
-
if (item.retailer_id === retailerId && item.service === concept) {
|
|
846
|
-
return { ...item, status: newStatus };
|
|
847
|
-
}
|
|
848
|
-
return item;
|
|
849
|
-
}),
|
|
850
|
-
};
|
|
851
|
-
sessionStorage.setItem(
|
|
852
|
-
"productSelected",
|
|
853
|
-
JSON.stringify(updatedProductInSession),
|
|
854
|
-
);
|
|
855
|
-
}
|
|
1136
|
+
const userAssigned = (tab, rol) => {
|
|
1137
|
+
let concept = getConcept(activeTab);
|
|
856
1138
|
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
type: "SET_MODAL",
|
|
860
|
-
payload: {
|
|
861
|
-
show: true,
|
|
862
|
-
title: "",
|
|
863
|
-
message: message,
|
|
864
|
-
image: successIcon,
|
|
865
|
-
},
|
|
866
|
-
});
|
|
867
|
-
}
|
|
1139
|
+
const allowedRoles = [1, 4, 5, 6, 7, 8];
|
|
1140
|
+
const validUser = allowedRoles.includes(user?.id_role);
|
|
868
1141
|
|
|
869
|
-
|
|
870
|
-
|
|
1142
|
+
if (!rol) {
|
|
1143
|
+
switch (user.id_role) {
|
|
1144
|
+
case 4:
|
|
1145
|
+
case 5:
|
|
1146
|
+
rol = "facilitator";
|
|
1147
|
+
break;
|
|
1148
|
+
case 7:
|
|
1149
|
+
case 8:
|
|
1150
|
+
rol = "especialist";
|
|
1151
|
+
break;
|
|
871
1152
|
}
|
|
872
|
-
} catch (error) {
|
|
873
|
-
console.error("Error sending evaluation:", error);
|
|
874
|
-
dispatch({
|
|
875
|
-
type: "SET_MODAL",
|
|
876
|
-
payload: {
|
|
877
|
-
show: true,
|
|
878
|
-
title: "Error",
|
|
879
|
-
message: "Hubo un error al procesar la evaluación",
|
|
880
|
-
image: errorIcon,
|
|
881
|
-
},
|
|
882
|
-
});
|
|
883
|
-
} finally {
|
|
884
|
-
dispatch({ type: "SET_SAVING", payload: false });
|
|
885
1153
|
}
|
|
1154
|
+
|
|
1155
|
+
return (
|
|
1156
|
+
user.id_role === 1 ||
|
|
1157
|
+
(product.article[`id_${concept}_${rol}`] === user.id_user && validUser)
|
|
1158
|
+
);
|
|
886
1159
|
};
|
|
887
1160
|
|
|
888
|
-
const
|
|
889
|
-
|
|
1161
|
+
const auditorAssigned = () => {
|
|
1162
|
+
return product?.article[`id_auditor`] === user.id_user;
|
|
890
1163
|
};
|
|
891
1164
|
|
|
892
|
-
const
|
|
893
|
-
|
|
894
|
-
|
|
1165
|
+
const createComment = async (e, body, tab) => {
|
|
1166
|
+
let concept = "";
|
|
1167
|
+
switch (activeTab) {
|
|
1168
|
+
case "Ficha técnica":
|
|
1169
|
+
concept = "datasheet";
|
|
1170
|
+
break;
|
|
1171
|
+
case "Imágenes":
|
|
1172
|
+
concept = "images";
|
|
1173
|
+
break;
|
|
1174
|
+
|
|
1175
|
+
default:
|
|
1176
|
+
concept = "description";
|
|
1177
|
+
break;
|
|
1178
|
+
}
|
|
1179
|
+
const data = {
|
|
1180
|
+
articleId: product?.article?.id_article,
|
|
1181
|
+
orderId: product?.orderId,
|
|
1182
|
+
message: body?.replace(/<.*?\/?>/gm, ""),
|
|
1183
|
+
concept: concept,
|
|
1184
|
+
version: version,
|
|
1185
|
+
};
|
|
1186
|
+
await axios.post(`${process.env.REACT_APP_COMMENTS_ENDPOINT}`, data, {
|
|
1187
|
+
headers: {
|
|
1188
|
+
Authorization: token,
|
|
1189
|
+
},
|
|
1190
|
+
});
|
|
1191
|
+
await getComments(tab);
|
|
1192
|
+
setMessage("");
|
|
1193
|
+
setComponentsArray([]);
|
|
895
1194
|
};
|
|
896
1195
|
|
|
897
|
-
const
|
|
898
|
-
dispatch({ type: "SET_SAVING", payload: true });
|
|
1196
|
+
const getRequired = (services) => {
|
|
899
1197
|
try {
|
|
900
|
-
const
|
|
1198
|
+
const objetcTemp = {};
|
|
1199
|
+
const datasheetServicesArray = Object.values(services[0]);
|
|
1200
|
+
const allDatasheetInputs = datasheetServicesArray.pop();
|
|
1201
|
+
const descriptionsServicesArray = services[1];
|
|
1202
|
+
|
|
1203
|
+
let dsInputsRequired = [];
|
|
1204
|
+
|
|
1205
|
+
let desInputsRequired = 0;
|
|
1206
|
+
datasheetServicesArray?.forEach((datasheet) => {
|
|
1207
|
+
const [requested] = servicesData?.filter(
|
|
1208
|
+
(srv) =>
|
|
1209
|
+
srv.id_retailer === datasheet.retailer.id &&
|
|
1210
|
+
srv.service === getConcept(activeTab)
|
|
1211
|
+
);
|
|
901
1212
|
|
|
902
|
-
|
|
1213
|
+
requested &&
|
|
1214
|
+
datasheet?.data &&
|
|
1215
|
+
Object.values(datasheet?.data).forEach((dataGroup) => {
|
|
1216
|
+
dsInputsRequired.push(
|
|
1217
|
+
...dataGroup.inputs.filter((input) => {
|
|
1218
|
+
return (
|
|
1219
|
+
allDatasheetInputs[input].required &&
|
|
1220
|
+
allDatasheetInputs[input].id_retailer === activeRetailer.id &&
|
|
1221
|
+
(allDatasheetInputs[input].value === undefined ||
|
|
1222
|
+
!allDatasheetInputs[input].value)
|
|
1223
|
+
);
|
|
1224
|
+
})
|
|
1225
|
+
);
|
|
1226
|
+
});
|
|
1227
|
+
});
|
|
903
1228
|
|
|
904
|
-
|
|
905
|
-
const { service: retailer_service, id_retailer, status: status_retailer_service } = ret;
|
|
1229
|
+
objetcTemp["Ficha técnica"] = dsInputsRequired.length;
|
|
906
1230
|
|
|
907
|
-
|
|
1231
|
+
const regex = /(<\/?p>)|(<\/?strong>)|(<br>)/gm;
|
|
1232
|
+
descriptionsServicesArray.forEach((description) => {
|
|
1233
|
+
if (description.id != activeRetailer.id) return;
|
|
908
1234
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
result,
|
|
915
|
-
evalStatus: status_retailer_service,
|
|
916
|
-
retailerId: id_retailer,
|
|
917
|
-
};
|
|
1235
|
+
const [requested] = servicesData.filter(
|
|
1236
|
+
(srv) =>
|
|
1237
|
+
srv.id_retailer === description.id &&
|
|
1238
|
+
srv.service === getConcept(activeTab)
|
|
1239
|
+
);
|
|
918
1240
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
1241
|
+
if (requested) {
|
|
1242
|
+
description.inputs.forEach((input) => {
|
|
1243
|
+
if (
|
|
1244
|
+
input.required &&
|
|
1245
|
+
(!input.value || input.value?.replace(regex, "") === "")
|
|
1246
|
+
) {
|
|
1247
|
+
desInputsRequired++;
|
|
1248
|
+
}
|
|
1249
|
+
});
|
|
926
1250
|
}
|
|
927
1251
|
});
|
|
928
1252
|
|
|
929
|
-
|
|
1253
|
+
objetcTemp["Descripción"] = desInputsRequired;
|
|
930
1254
|
|
|
931
|
-
const
|
|
1255
|
+
const retailersRequested = [];
|
|
932
1256
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
(item) =>
|
|
936
|
-
conceptArray.includes(item.service) ? { ...item, status } : item,
|
|
1257
|
+
services[2]?.retailerMandatories?.forEach((retMan) =>
|
|
1258
|
+
retMan.forEach((rm) => retailersRequested.push(rm))
|
|
937
1259
|
);
|
|
938
1260
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
statusByRetailer: updatedStatusByRetailer,
|
|
950
|
-
};
|
|
951
|
-
|
|
952
|
-
dispatch({
|
|
953
|
-
type: "SET_PRODUCT",
|
|
954
|
-
payload: updatedProduct,
|
|
955
|
-
});
|
|
956
|
-
|
|
957
|
-
const updatedServicesData = state.services_data.map(service => conceptArray.includes(service.service) ? { ...service, status: status } : service);
|
|
958
|
-
|
|
959
|
-
dispatch({
|
|
960
|
-
type: "SET_SERVICES_DATA",
|
|
961
|
-
payload: updatedServicesData,
|
|
962
|
-
});
|
|
1261
|
+
const requiredImages = services[2]?.inputs?.filter(
|
|
1262
|
+
(e) =>
|
|
1263
|
+
e.required === 1 &&
|
|
1264
|
+
retailersRequested.filter(
|
|
1265
|
+
(ret) =>
|
|
1266
|
+
ret.id_image === e.id &&
|
|
1267
|
+
servicesData.filter((srv) => srv.id_retailer === ret.id_retailer)
|
|
1268
|
+
.length > 0
|
|
1269
|
+
).length > 0
|
|
1270
|
+
);
|
|
963
1271
|
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
// JSON.stringify({
|
|
971
|
-
// ArticleId: updatedProduct.id_article,
|
|
972
|
-
// idCategory: updatedProduct.id_category,
|
|
973
|
-
// product: updatedProduct,
|
|
974
|
-
// }),
|
|
975
|
-
// );
|
|
976
|
-
|
|
977
|
-
// Mostrar modal de éxito
|
|
978
|
-
dispatch({
|
|
979
|
-
type: "SET_MODAL",
|
|
980
|
-
payload: {
|
|
981
|
-
show: true,
|
|
982
|
-
title: "",
|
|
983
|
-
message:
|
|
984
|
-
result === "A"
|
|
985
|
-
? "Todos los servicios aprobados con éxito"
|
|
986
|
-
: "Todos los servicios rechazados con éxito",
|
|
987
|
-
image: successIcon,
|
|
988
|
-
},
|
|
1272
|
+
let requiredCounter = 0;
|
|
1273
|
+
requiredImages?.forEach((req) => {
|
|
1274
|
+
return (
|
|
1275
|
+
services[2].values.filter((img) => img.image_id === req.id).length ===
|
|
1276
|
+
0 && requiredCounter++
|
|
1277
|
+
);
|
|
989
1278
|
});
|
|
1279
|
+
objetcTemp["Imágenes"] = requiredCounter;
|
|
1280
|
+
setRequiredNull(objetcTemp);
|
|
990
1281
|
} catch (error) {
|
|
991
|
-
console.
|
|
992
|
-
} finally {
|
|
993
|
-
dispatch({ type: "SET_SAVING", payload: false });
|
|
1282
|
+
console.log(error);
|
|
994
1283
|
}
|
|
995
1284
|
};
|
|
996
1285
|
|
|
997
|
-
|
|
998
|
-
|
|
1286
|
+
useEffect(() => {
|
|
1287
|
+
setComment(comments[activeTab]);
|
|
1288
|
+
}, [activeTab]);
|
|
1289
|
+
|
|
1290
|
+
const commentRevised = async () => {
|
|
1291
|
+
const data = {
|
|
1292
|
+
commentId: comment.id,
|
|
1293
|
+
};
|
|
1294
|
+
await axios.put(`${process.env.REACT_APP_COMMENTS_ENDPOINT}`, data, {
|
|
1295
|
+
headers: {
|
|
1296
|
+
Authorization: sessionStorage.getItem("jwt"),
|
|
1297
|
+
},
|
|
1298
|
+
});
|
|
1299
|
+
setCrossComment(false);
|
|
1300
|
+
await getComments();
|
|
1301
|
+
};
|
|
1302
|
+
|
|
1303
|
+
const setAssignation = async (assignationType, assignationId) => {
|
|
1304
|
+
let concept = "";
|
|
1305
|
+
switch (activeTab) {
|
|
1306
|
+
case "Ficha técnica":
|
|
1307
|
+
concept = "datasheet";
|
|
1308
|
+
break;
|
|
1309
|
+
case "Imágenes":
|
|
1310
|
+
concept = "images";
|
|
1311
|
+
break;
|
|
1312
|
+
|
|
1313
|
+
default:
|
|
1314
|
+
concept = "description";
|
|
1315
|
+
break;
|
|
1316
|
+
}
|
|
1317
|
+
const productTemp = product;
|
|
1318
|
+
productTemp.article[`id_${concept}_${assignationType}`] = assignationId;
|
|
999
1319
|
const data = {
|
|
1000
1320
|
articleList: [
|
|
1001
1321
|
{
|
|
1002
|
-
orderId:
|
|
1003
|
-
articleId:
|
|
1322
|
+
orderId: product.orderId,
|
|
1323
|
+
articleId: product?.article?.id_article,
|
|
1004
1324
|
},
|
|
1005
1325
|
],
|
|
1006
1326
|
concept: concept,
|
|
1007
1327
|
userId: assignationId,
|
|
1008
1328
|
};
|
|
1009
|
-
|
|
1010
1329
|
await axios({
|
|
1011
1330
|
method: "post",
|
|
1012
1331
|
url: process.env.REACT_APP_ASSIGNATIONS_ENDPOINT,
|
|
@@ -1015,794 +1334,646 @@ const RetailerProductEditionView = ({
|
|
|
1015
1334
|
Authorization: token,
|
|
1016
1335
|
},
|
|
1017
1336
|
});
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
...state.product,
|
|
1021
|
-
[`id_${concept}_${assignationType}`]: assignationId,
|
|
1022
|
-
};
|
|
1023
|
-
|
|
1024
|
-
dispatch({ type: "SET_PRODUCT", payload: updatedProduct });
|
|
1025
|
-
};
|
|
1026
|
-
|
|
1027
|
-
const handleOnSetAssignation = () => {
|
|
1028
|
-
console.log("handleOnSetAssignation - pendiente de implementar");
|
|
1029
|
-
};
|
|
1030
|
-
|
|
1031
|
-
const handleOnSetImages = () => {
|
|
1032
|
-
console.log("handleOnSetImages - pendiente de implementar");
|
|
1033
|
-
};
|
|
1034
|
-
|
|
1035
|
-
const handleOnSetCheckAll = (isChecked) => {
|
|
1036
|
-
dispatch({ type: "TOGGLE_CHECK_ALL_IMAGES", payload: isChecked });
|
|
1037
|
-
};
|
|
1038
|
-
|
|
1039
|
-
const handleOnSetSelectedImages = () => {
|
|
1040
|
-
/*
|
|
1041
|
-
Esta función no se utiliza actualmente.
|
|
1042
|
-
|
|
1043
|
-
En la versión anterior se usaban dos funciones distintas para el checkbox
|
|
1044
|
-
"Seleccionar todo":
|
|
1045
|
-
- Una para cambiar el valor booleano del checkbox.
|
|
1046
|
-
- Otra para actualizar el array de imágenes seleccionadas.
|
|
1047
|
-
|
|
1048
|
-
En la versión actual se unificó la lógica en una sola función,
|
|
1049
|
-
`handleOnSetCheckAll`, que recibe el valor `true` o `false` del checkbox
|
|
1050
|
-
"Seleccionar todo" y, a partir de este, agrega o elimina todas las imágenes
|
|
1051
|
-
del array de imágenes seleccionadas.
|
|
1052
|
-
*/
|
|
1053
|
-
console.log("setSelectedImages");
|
|
1054
|
-
};
|
|
1055
|
-
const handleOnSubmitComment = async (e) => {
|
|
1056
|
-
e.preventDefault();
|
|
1057
|
-
const commentText = document.querySelector(
|
|
1058
|
-
"#commentary-box .ql-container .ql-editor > p",
|
|
1059
|
-
).innerHTML;
|
|
1060
|
-
try {
|
|
1061
|
-
await createComment(commentText, token);
|
|
1062
|
-
|
|
1063
|
-
dispatch({
|
|
1064
|
-
type: "SET_MODAL",
|
|
1065
|
-
payload: {
|
|
1066
|
-
show: true,
|
|
1067
|
-
title: "",
|
|
1068
|
-
message: "Comentario guardado con éxito",
|
|
1069
|
-
image: successIcon,
|
|
1070
|
-
},
|
|
1071
|
-
});
|
|
1072
|
-
} catch (error) {
|
|
1073
|
-
console.error("Error saving comment:", error);
|
|
1074
|
-
dispatch({
|
|
1075
|
-
type: "SET_MODAL",
|
|
1076
|
-
payload: {
|
|
1077
|
-
show: true,
|
|
1078
|
-
title: "Error",
|
|
1079
|
-
message: "Hubo un error al guardar el comentario",
|
|
1080
|
-
image: errorIcon,
|
|
1081
|
-
},
|
|
1082
|
-
});
|
|
1083
|
-
}
|
|
1337
|
+
loadAssignations(productTemp);
|
|
1338
|
+
sessionStorage.setItem("productSelected", JSON.stringify(productTemp));
|
|
1084
1339
|
};
|
|
1085
1340
|
|
|
1086
|
-
const
|
|
1087
|
-
|
|
1341
|
+
const downloadImages = () => {
|
|
1342
|
+
selectedImages.length > 0
|
|
1343
|
+
? selectedImages.forEach((e) => {
|
|
1344
|
+
if (e.id) {
|
|
1345
|
+
saveAs(
|
|
1346
|
+
`https://${process.env.REACT_APP_IMAGES_BUCKET}.s3.amazonaws.com/${e.srcDB}`,
|
|
1347
|
+
`${product.article.upc}_${e.name}.${e.ext}`
|
|
1348
|
+
);
|
|
1349
|
+
}
|
|
1350
|
+
})
|
|
1351
|
+
: images?.values?.forEach((e) => {
|
|
1352
|
+
if (e.id) {
|
|
1353
|
+
saveAs(
|
|
1354
|
+
`https://${process.env.REACT_APP_IMAGES_BUCKET}.s3.amazonaws.com/${e.srcDB}`,
|
|
1355
|
+
`${product.article.upc}_${e.name}.${e.ext}`
|
|
1356
|
+
);
|
|
1357
|
+
}
|
|
1358
|
+
});
|
|
1088
1359
|
};
|
|
1089
1360
|
|
|
1090
|
-
const
|
|
1091
|
-
|
|
1092
|
-
const
|
|
1093
|
-
const
|
|
1094
|
-
const concept = getConceptByTab(tab);
|
|
1095
|
-
|
|
1096
|
-
const servicesByTab = servicesData?.filter(
|
|
1097
|
-
(serv) => serv.service === concept,
|
|
1098
|
-
);
|
|
1099
|
-
|
|
1100
|
-
const statusBySelectedRetailerService = servicesByTab
|
|
1101
|
-
?.find((serv) => serv.id_retailer === activeRetailer?.id_retailer)
|
|
1102
|
-
?.status?.replace(/.*\//, "");
|
|
1361
|
+
const deleteImages = async () => {
|
|
1362
|
+
setLoading(true);
|
|
1363
|
+
const { values } = images;
|
|
1364
|
+
const imgsInBack = [];
|
|
1103
1365
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
);
|
|
1366
|
+
selectedImages.forEach((selectedImg) => {
|
|
1367
|
+
if (selectedImg.id) imgsInBack.push(selectedImg);
|
|
1368
|
+
});
|
|
1108
1369
|
|
|
1109
|
-
const
|
|
1110
|
-
|
|
1111
|
-
currentProducStatus,
|
|
1370
|
+
const imgsLeft = values.filter(
|
|
1371
|
+
(value) => selectedImages.indexOf(value) === -1
|
|
1112
1372
|
);
|
|
1113
1373
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1374
|
+
if (imgsInBack.length > 0) {
|
|
1375
|
+
const data = {
|
|
1376
|
+
articleId: product.article.id_article,
|
|
1377
|
+
deleteImages: imgsInBack,
|
|
1378
|
+
orderId: product.orderId,
|
|
1379
|
+
};
|
|
1380
|
+
try {
|
|
1381
|
+
await axios.put(
|
|
1382
|
+
`${process.env.REACT_APP_ARTICLE_DATA_ENDPOINT}?image=true&version=${version}`,
|
|
1383
|
+
data,
|
|
1384
|
+
{
|
|
1385
|
+
headers: { Authorization: token },
|
|
1386
|
+
}
|
|
1387
|
+
);
|
|
1388
|
+
} catch (err) {
|
|
1389
|
+
console.log(err);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1122
1392
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1393
|
+
setImages({
|
|
1394
|
+
action: "deleteImage",
|
|
1395
|
+
selectedImages,
|
|
1396
|
+
});
|
|
1127
1397
|
|
|
1128
|
-
|
|
1398
|
+
getRequired([
|
|
1399
|
+
services[0],
|
|
1400
|
+
services[1],
|
|
1401
|
+
{ ...services[2], values: imgsLeft },
|
|
1402
|
+
]);
|
|
1129
1403
|
|
|
1130
|
-
|
|
1404
|
+
setLoading(false);
|
|
1131
1405
|
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
const filteredSrv45 = servicesByTab?.filter((serv) =>
|
|
1135
|
-
statusArray.includes(serv?.status),
|
|
1136
|
-
);
|
|
1137
|
-
const condition45 =
|
|
1138
|
-
unvalidated &&
|
|
1139
|
-
["CA", "IE"].includes(product?.status) &&
|
|
1140
|
-
filteredSrv45?.length === servicesByTab?.length;
|
|
1141
|
-
return condition45;
|
|
1142
|
-
case 6:
|
|
1143
|
-
const statusInArray = statusArray.includes(product?.status);
|
|
1144
|
-
const allSrvValid = srv?.every((serv) =>
|
|
1145
|
-
["RA", "AA", "AP", "ACA"].includes(serv?.status),
|
|
1146
|
-
);
|
|
1147
|
-
const condition6 = statusInArray && allSrvValid && auditorUnvalidated;
|
|
1148
|
-
return condition6;
|
|
1149
|
-
default:
|
|
1150
|
-
console.log("Default case - returning false");
|
|
1151
|
-
return false;
|
|
1152
|
-
}
|
|
1406
|
+
setMessage("");
|
|
1407
|
+
setComponentsArray([]);
|
|
1153
1408
|
};
|
|
1154
1409
|
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1410
|
+
const askToDeleteImages = () => {
|
|
1411
|
+
if (selectedImages.length > 0) {
|
|
1412
|
+
setMessage("¿Está seguro de eliminar las imágenes seleccionadas?");
|
|
1413
|
+
setComponentsArray([
|
|
1414
|
+
<ScreenHeader
|
|
1415
|
+
key={"1"}
|
|
1416
|
+
text={"¿Está seguro de eliminar las imágenes seleccionadas?"}
|
|
1417
|
+
headerType="retailer-name-header"
|
|
1418
|
+
color={"white"}
|
|
1419
|
+
/>,
|
|
1420
|
+
<Button
|
|
1421
|
+
key={"2"}
|
|
1422
|
+
buttonType="general-white-button"
|
|
1423
|
+
label={"Cancelar"}
|
|
1424
|
+
onClick={() => setMessage("")}
|
|
1425
|
+
/>,
|
|
1426
|
+
<Button
|
|
1427
|
+
key={"3"}
|
|
1428
|
+
buttonType="general-button-default"
|
|
1429
|
+
label={"Aceptar"}
|
|
1430
|
+
onClick={() => {
|
|
1431
|
+
setMessage("");
|
|
1432
|
+
deleteImages();
|
|
1433
|
+
}}
|
|
1434
|
+
/>,
|
|
1435
|
+
]);
|
|
1436
|
+
}
|
|
1162
1437
|
};
|
|
1163
1438
|
|
|
1164
|
-
const
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
<Box
|
|
1168
|
-
px={1.5}
|
|
1169
|
-
py={1}
|
|
1170
|
-
pb={0}
|
|
1171
|
-
display="flex"
|
|
1172
|
-
alignItems="center"
|
|
1173
|
-
justifyContent="space-between"
|
|
1174
|
-
>
|
|
1175
|
-
<Skeleton variant="text" width={300} height={40} />
|
|
1176
|
-
<Stack direction="row" spacing={2}>
|
|
1177
|
-
<Skeleton variant="circular" width={32} height={32} />
|
|
1178
|
-
</Stack>
|
|
1179
|
-
</Box>
|
|
1180
|
-
|
|
1181
|
-
<div
|
|
1182
|
-
className="data-container"
|
|
1183
|
-
style={{ display: "flex", gap: "8px", padding: "0 12px 12px" }}
|
|
1184
|
-
>
|
|
1185
|
-
<div
|
|
1186
|
-
className="image-data-panel"
|
|
1187
|
-
style={{
|
|
1188
|
-
flex: "0 0 320px",
|
|
1189
|
-
display: "flex",
|
|
1190
|
-
flexDirection: "column",
|
|
1191
|
-
gap: "20px",
|
|
1192
|
-
}}
|
|
1193
|
-
>
|
|
1194
|
-
<Skeleton variant="rounded" width="100%" height={400} />
|
|
1195
|
-
|
|
1196
|
-
<Stack direction="row" spacing={2} justifyContent="center">
|
|
1197
|
-
{[1, 2, 3, 4].map((item) => (
|
|
1198
|
-
<Skeleton key={item} variant="rounded" width={60} height={80} />
|
|
1199
|
-
))}
|
|
1200
|
-
</Stack>
|
|
1201
|
-
|
|
1202
|
-
<Box mt={2}>
|
|
1203
|
-
{[1, 2, 3, 4].map((item) => (
|
|
1204
|
-
<Box
|
|
1205
|
-
key={item}
|
|
1206
|
-
display="flex"
|
|
1207
|
-
justifyContent="space-between"
|
|
1208
|
-
py={1}
|
|
1209
|
-
borderBottom="1px solid #f0f0f0"
|
|
1210
|
-
>
|
|
1211
|
-
<Skeleton variant="text" width="40%" />
|
|
1212
|
-
<Skeleton variant="text" width="20%" />
|
|
1213
|
-
</Box>
|
|
1214
|
-
))}
|
|
1215
|
-
</Box>
|
|
1216
|
-
</div>
|
|
1439
|
+
const getRetailerStatus = (servicesData, tab) => {
|
|
1440
|
+
const arr = servicesData?.slice();
|
|
1441
|
+
let concept = getConcept(tab);
|
|
1217
1442
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
flexDirection: "column",
|
|
1224
|
-
gap: "14px",
|
|
1225
|
-
}}
|
|
1226
|
-
>
|
|
1227
|
-
<Box>
|
|
1228
|
-
<Skeleton variant="text" width="80%" height={50} />
|
|
1229
|
-
<Stack direction="row" spacing={2} alignItems="center">
|
|
1230
|
-
<Skeleton variant="rounded" width={180} height={24} />
|
|
1231
|
-
<Skeleton variant="rounded" width={300} height={24} />
|
|
1232
|
-
</Stack>
|
|
1233
|
-
</Box>
|
|
1234
|
-
|
|
1235
|
-
<Box display="flex" gap={4} pb={1}>
|
|
1236
|
-
<Skeleton variant="text" width={140} height={45} />
|
|
1237
|
-
<Skeleton variant="text" width={140} height={45} />
|
|
1238
|
-
<Skeleton variant="text" width={140} height={45} />
|
|
1239
|
-
</Box>
|
|
1240
|
-
|
|
1241
|
-
<Box display="flex" flexDirection="column" gap={4}>
|
|
1242
|
-
{[1, 2, 3].map((item) => (
|
|
1243
|
-
<Box key={item}>
|
|
1244
|
-
<Box
|
|
1245
|
-
display="flex"
|
|
1246
|
-
justifyContent="space-between"
|
|
1247
|
-
alignItems="center"
|
|
1248
|
-
mb={1}
|
|
1249
|
-
>
|
|
1250
|
-
<Skeleton variant="text" width="30%" height={24} />
|
|
1251
|
-
<Skeleton
|
|
1252
|
-
variant="rounded"
|
|
1253
|
-
width={175}
|
|
1254
|
-
height={25}
|
|
1255
|
-
sx={{ borderRadius: "7.5px" }}
|
|
1256
|
-
/>
|
|
1257
|
-
</Box>
|
|
1258
|
-
<Skeleton variant="rounded" width="100%" height={70} />
|
|
1259
|
-
<Box display="flex" justifyContent="flex-end" mt={0.5}>
|
|
1260
|
-
<Skeleton variant="text" width={60} />
|
|
1261
|
-
</Box>
|
|
1262
|
-
</Box>
|
|
1263
|
-
))}
|
|
1264
|
-
</Box>
|
|
1265
|
-
|
|
1266
|
-
<Box mt="auto" pt={4}>
|
|
1267
|
-
<Skeleton variant="rounded" width="100%" height={120} />
|
|
1268
|
-
<Box display="flex" justifyContent="flex-end" gap={2} mt={2}>
|
|
1269
|
-
<Skeleton
|
|
1270
|
-
variant="rounded"
|
|
1271
|
-
width={180}
|
|
1272
|
-
height={45}
|
|
1273
|
-
sx={{ borderRadius: "24px" }}
|
|
1274
|
-
/>
|
|
1275
|
-
<Skeleton
|
|
1276
|
-
variant="rounded"
|
|
1277
|
-
width={180}
|
|
1278
|
-
height={45}
|
|
1279
|
-
sx={{ borderRadius: "24px" }}
|
|
1280
|
-
/>
|
|
1281
|
-
</Box>
|
|
1282
|
-
</Box>
|
|
1283
|
-
</div>
|
|
1284
|
-
</div>
|
|
1285
|
-
</Container>
|
|
1443
|
+
let retailerService = {};
|
|
1444
|
+
[retailerService] = arr?.filter(
|
|
1445
|
+
(service) =>
|
|
1446
|
+
service.id_retailer === activeRetailer?.id &&
|
|
1447
|
+
service.service === concept
|
|
1286
1448
|
);
|
|
1449
|
+
return retailerService ? retailerService.status : "NS";
|
|
1287
1450
|
};
|
|
1288
1451
|
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
</>
|
|
1294
|
-
);
|
|
1295
|
-
|
|
1296
|
-
return (
|
|
1297
|
-
<AiProductEditionProvider
|
|
1298
|
-
isCreatorsEdition={true}
|
|
1299
|
-
user={user}
|
|
1300
|
-
token={token}
|
|
1301
|
-
state={state}
|
|
1302
|
-
>
|
|
1303
|
-
<Container headerTop={headerTop}>
|
|
1304
|
-
{showRejectModal && (
|
|
1305
|
-
<Modal
|
|
1306
|
-
title={
|
|
1307
|
-
rejectAll
|
|
1308
|
-
? "Agregar mensaje para rechazar todo"
|
|
1309
|
-
: "Agregar mensaje de rechazo"
|
|
1310
|
-
}
|
|
1311
|
-
show={showRejectModal}
|
|
1312
|
-
customComponent={
|
|
1313
|
-
<TagAndInput
|
|
1314
|
-
inputType={"textarea"}
|
|
1315
|
-
inputId={"modal-message-box"}
|
|
1316
|
-
index={0}
|
|
1317
|
-
color={"white"}
|
|
1318
|
-
/>
|
|
1319
|
-
}
|
|
1320
|
-
buttons={[
|
|
1321
|
-
<ButtonV2
|
|
1322
|
-
key={"btn-Cancelar"}
|
|
1323
|
-
type={"white"}
|
|
1324
|
-
label={"Cancelar"}
|
|
1325
|
-
size={12}
|
|
1326
|
-
onClick={() => {
|
|
1327
|
-
setShowRejectModal(false);
|
|
1328
|
-
}}
|
|
1329
|
-
/>,
|
|
1330
|
-
<ButtonV2
|
|
1331
|
-
key={"btn-Aceptar"}
|
|
1332
|
-
type={"pink"}
|
|
1333
|
-
label={"Aceptar"}
|
|
1334
|
-
size={12}
|
|
1335
|
-
onClick={async () => {
|
|
1336
|
-
const elements = document.querySelectorAll(
|
|
1337
|
-
"#modal-message-box .ql-container .ql-editor > p",
|
|
1338
|
-
);
|
|
1452
|
+
useEffect(() => {
|
|
1453
|
+
let status = getRetailerStatus(servicesData, activeTab);
|
|
1454
|
+
setRetailerStatus(status);
|
|
1455
|
+
}, [activeTab, servicesData, activeRetailer]);
|
|
1339
1456
|
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
}
|
|
1457
|
+
useEffect(() => {
|
|
1458
|
+
services.length > 0 && getRequired(services);
|
|
1459
|
+
}, [services, servicesData, activeTab]);
|
|
1344
1460
|
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
!body || body.replace(/<.*?\/?>/gm, "").trim() === ""
|
|
1349
|
-
);
|
|
1350
|
-
});
|
|
1461
|
+
useEffect(() => {
|
|
1462
|
+
setSaving(loading);
|
|
1463
|
+
}, [loading]);
|
|
1351
1464
|
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
font-size: 14px;
|
|
1370
|
-
display: flex;
|
|
1371
|
-
align-items: center;
|
|
1372
|
-
gap: 8px;
|
|
1373
|
-
font-family: 'Roboto', sans-serif;
|
|
1374
|
-
text-align: center;
|
|
1375
|
-
`;
|
|
1376
|
-
alert.innerHTML = `<span>El mensaje no puede estar vacío.</span>`;
|
|
1377
|
-
container.appendChild(alert);
|
|
1378
|
-
}
|
|
1379
|
-
return;
|
|
1380
|
-
}
|
|
1465
|
+
const validateAll = async (result) => {
|
|
1466
|
+
try {
|
|
1467
|
+
setLoading(true);
|
|
1468
|
+
const evaluationArray = [];
|
|
1469
|
+
let conceptArray = [];
|
|
1470
|
+
switch (user.id_role) {
|
|
1471
|
+
case 4:
|
|
1472
|
+
conceptArray = ["description", "datasheet"];
|
|
1473
|
+
break;
|
|
1474
|
+
case 5:
|
|
1475
|
+
conceptArray = ["images"];
|
|
1476
|
+
break;
|
|
1477
|
+
|
|
1478
|
+
default:
|
|
1479
|
+
conceptArray = ["description", "datasheet", "images"];
|
|
1480
|
+
break;
|
|
1481
|
+
}
|
|
1381
1482
|
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1483
|
+
const messages = [];
|
|
1484
|
+
|
|
1485
|
+
servicesData?.forEach((ret) => {
|
|
1486
|
+
if (conceptArray.includes(ret.service)) {
|
|
1487
|
+
let data = {
|
|
1488
|
+
articleId: product.article.id_article,
|
|
1489
|
+
orderId: product.id_order ?? product.orderId,
|
|
1490
|
+
concept: ret.service,
|
|
1491
|
+
result: result,
|
|
1492
|
+
evalStatus: ret.status,
|
|
1493
|
+
retailerId: ret.id_retailer,
|
|
1494
|
+
};
|
|
1495
|
+
evaluationArray.push(
|
|
1496
|
+
axios.put(`${process.env.REACT_APP_EVALUATION_ENDPOINT}`, data, {
|
|
1497
|
+
headers: {
|
|
1498
|
+
Authorization: token,
|
|
1499
|
+
},
|
|
1500
|
+
})
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
});
|
|
1504
|
+
await Promise.all(evaluationArray);
|
|
1386
1505
|
|
|
1387
|
-
|
|
1506
|
+
const productTemp = product;
|
|
1507
|
+
productTemp.status = `${result}A`;
|
|
1508
|
+
productTemp.datasheet_status =
|
|
1509
|
+
productTemp.datasheet_status === "NS" ? "NS" : `${result}A`;
|
|
1510
|
+
productTemp.description_status =
|
|
1511
|
+
productTemp.description_status === "NS" ? "NS" : `${result}A`;
|
|
1512
|
+
productTemp.images_status =
|
|
1513
|
+
productTemp.images_status === "NS" ? "NS" : `${result}A`;
|
|
1514
|
+
sessionStorage.setItem("productSelected", JSON.stringify(productTemp));
|
|
1515
|
+
setProduct(productTemp);
|
|
1516
|
+
const messagesResponse = await Promise.all(messages);
|
|
1517
|
+
|
|
1518
|
+
await loadData();
|
|
1519
|
+
} catch (error) {
|
|
1520
|
+
console.log(error);
|
|
1521
|
+
} finally {
|
|
1522
|
+
setLoading(false);
|
|
1523
|
+
}
|
|
1524
|
+
};
|
|
1388
1525
|
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1526
|
+
const getObservation = async () => {
|
|
1527
|
+
const response = await axios.get(
|
|
1528
|
+
`${process.env.REACT_APP_READ_OBSERVATION}?articleId=${product.article.id_article}&orderId=${product?.orderId}`,
|
|
1529
|
+
{
|
|
1530
|
+
headers: {
|
|
1531
|
+
Authorization: sessionStorage.getItem("jwt"),
|
|
1532
|
+
},
|
|
1533
|
+
}
|
|
1534
|
+
);
|
|
1535
|
+
const parseData = JSON.parse(response.data.body).data[0];
|
|
1536
|
+
setObservation(parseData.observations);
|
|
1537
|
+
};
|
|
1538
|
+
useEffect(() => {
|
|
1539
|
+
getObservation();
|
|
1540
|
+
}, []);
|
|
1541
|
+
return (
|
|
1542
|
+
<Container headerTop={headerTop}>
|
|
1543
|
+
<HeaderTop
|
|
1544
|
+
setHeaderTop={setHeaderTop}
|
|
1545
|
+
auditableVersion={auditableVersion}
|
|
1546
|
+
setCompare={setCompare}
|
|
1547
|
+
isAuditor={[1, 6].includes(user.id_role)}
|
|
1548
|
+
withChat={location?.state?.withChat}
|
|
1549
|
+
chatType={location?.state?.chatType}
|
|
1550
|
+
productSelected={product}
|
|
1551
|
+
token={token}
|
|
1552
|
+
activeRetailer={activeRetailer}
|
|
1553
|
+
/>
|
|
1554
|
+
<div className="data-container">
|
|
1555
|
+
<div className="image-data-panel">
|
|
1556
|
+
<ImagePreviewer
|
|
1557
|
+
activeImage={images?.values ? images?.values[activeImage] : {}}
|
|
1558
|
+
imagesArray={images}
|
|
1559
|
+
setActiveImage={setActiveImage}
|
|
1560
|
+
setShowModal={setShowModal}
|
|
1396
1561
|
/>
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
text={state.modal.title}
|
|
1409
|
-
color={"white"}
|
|
1410
|
-
/>
|
|
1411
|
-
),
|
|
1412
|
-
state.modal.message && (
|
|
1413
|
-
<ScreenHeader
|
|
1414
|
-
key="3"
|
|
1415
|
-
headerType={"retailer-name-header"}
|
|
1416
|
-
text={state.modal.message}
|
|
1417
|
-
color={"white"}
|
|
1418
|
-
/>
|
|
1419
|
-
),
|
|
1420
|
-
state.modal.buttons && (
|
|
1421
|
-
<div key="4" style={{ marginTop: "16px" }}>
|
|
1422
|
-
{state.modal.buttons.map((button, index) => (
|
|
1423
|
-
<Button
|
|
1424
|
-
key={index}
|
|
1425
|
-
buttonType={button.buttonType}
|
|
1426
|
-
label={button.text}
|
|
1427
|
-
onClick={button.action}
|
|
1428
|
-
/>
|
|
1429
|
-
))}
|
|
1430
|
-
</div>
|
|
1431
|
-
),
|
|
1432
|
-
].filter(Boolean)}
|
|
1433
|
-
onClick={() =>
|
|
1434
|
-
dispatch({
|
|
1435
|
-
type: "SET_MODAL",
|
|
1436
|
-
payload: { show: false, title: "", message: "", image: null },
|
|
1437
|
-
})
|
|
1562
|
+
<ImageDataTable
|
|
1563
|
+
lists={images}
|
|
1564
|
+
activeImage={images?.values ? images?.values[activeImage] : {}}
|
|
1565
|
+
retailerSelected={activeRetailer?.id}
|
|
1566
|
+
setImages={setImages}
|
|
1567
|
+
assignationsImages={assig["Imágenes"]}
|
|
1568
|
+
imagesStatus={product?.images_status}
|
|
1569
|
+
setAssignation={setAssignation}
|
|
1570
|
+
isRetailer={isRetailer}
|
|
1571
|
+
onClickSave={() =>
|
|
1572
|
+
product?.services?.images === 1 && updateImages()
|
|
1438
1573
|
}
|
|
1574
|
+
showSaveButton={auditorAssigned() || userAssigned()}
|
|
1575
|
+
setShowVersionSelector={setShowVersionSelector}
|
|
1576
|
+
version={version}
|
|
1577
|
+
shotThd={shotThd}
|
|
1439
1578
|
/>
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
<
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1579
|
+
</div>
|
|
1580
|
+
<div className="product-information">
|
|
1581
|
+
<FullProductNameHeader
|
|
1582
|
+
headerData={product}
|
|
1583
|
+
productObservation={observation}
|
|
1584
|
+
percent={activePercentage}
|
|
1585
|
+
activeRetailer={activeRetailer}
|
|
1586
|
+
servicesData={servicesData}
|
|
1587
|
+
setActiveRetailer={setActiveRetailer}
|
|
1588
|
+
sendToFacilitator={sendToFacilitator}
|
|
1589
|
+
approve={() => {
|
|
1590
|
+
sendToFacilitator("A");
|
|
1591
|
+
}}
|
|
1592
|
+
reject={() => {
|
|
1593
|
+
setShowRejectModal(true);
|
|
1594
|
+
}}
|
|
1595
|
+
showApproveRejectAll={
|
|
1596
|
+
approveRejectAllButtons() && (auditorAssigned() || userAssigned())
|
|
1597
|
+
}
|
|
1598
|
+
showValidationButtons={
|
|
1599
|
+
approveRejectButtons() && (auditorAssigned() || userAssigned())
|
|
1600
|
+
}
|
|
1601
|
+
approveAll={() => validateAll("A")}
|
|
1602
|
+
rejectAll={() => {
|
|
1603
|
+
setShowRejectModal(true);
|
|
1604
|
+
setValRejAll(true);
|
|
1605
|
+
}}
|
|
1606
|
+
isObservationVisible={isObservationVisible}
|
|
1607
|
+
toggleObservation={toggleObservation}
|
|
1608
|
+
// handleClickOutside={handleClickOutside}
|
|
1609
|
+
hideObservation={hideObservation}
|
|
1447
1610
|
/>
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1611
|
+
<FullTabsMenu
|
|
1612
|
+
tabsSections={tabsSections}
|
|
1613
|
+
status={retailerStatus}
|
|
1614
|
+
activeTab={activeTab}
|
|
1615
|
+
setActiveTab={setActiveTab}
|
|
1616
|
+
setImageLayout={setImageLayout}
|
|
1617
|
+
downloadImages={downloadImages}
|
|
1618
|
+
askToDeleteImages={askToDeleteImages}
|
|
1619
|
+
assig={assig[activeTab]}
|
|
1620
|
+
setAssignation={setAssignation}
|
|
1621
|
+
isRetailer={isRetailer}
|
|
1622
|
+
showSaveButton={auditorAssigned() || userAssigned()}
|
|
1623
|
+
version={version}
|
|
1624
|
+
desc={desc}
|
|
1625
|
+
setDesc={setDesc}
|
|
1626
|
+
fich={fich}
|
|
1627
|
+
setFich={setFich}
|
|
1628
|
+
imag={imag}
|
|
1629
|
+
setImag={setImag}
|
|
1630
|
+
updatedDescriptions={updatedDescriptions}
|
|
1631
|
+
setUpdatedDescriptions={setUpdatedDescriptions}
|
|
1632
|
+
updatedDatasheets={updatedDatasheets}
|
|
1633
|
+
setUpdatedDatasheets={setUpdatedDatasheets}
|
|
1634
|
+
images={images}
|
|
1635
|
+
setImages={setImages}
|
|
1636
|
+
selectedImages={selectedImages}
|
|
1637
|
+
setSelectedImages={setSelectedImages}
|
|
1456
1638
|
setShowVersionSelector={setShowVersionSelector}
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
<div className="image-data-panel">
|
|
1476
|
-
<ImagePreviewer
|
|
1477
|
-
activeImage={
|
|
1478
|
-
state.images_values.values[state.current_image] ?? {}
|
|
1639
|
+
onClickSave={() => {
|
|
1640
|
+
switch (activeTab) {
|
|
1641
|
+
case "Descripción":
|
|
1642
|
+
!saving &&
|
|
1643
|
+
product?.description_status !== "NS" &&
|
|
1644
|
+
saveDescriptions();
|
|
1645
|
+
break;
|
|
1646
|
+
case "Ficha técnica":
|
|
1647
|
+
!saving &&
|
|
1648
|
+
product?.datasheet_status !== "NS" &&
|
|
1649
|
+
saveDatasheets();
|
|
1650
|
+
break;
|
|
1651
|
+
case "Imágenes":
|
|
1652
|
+
!saving && product?.images_status !== "NS" && updateImages();
|
|
1653
|
+
break;
|
|
1654
|
+
|
|
1655
|
+
default:
|
|
1656
|
+
break;
|
|
1479
1657
|
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
showSaveButton={isAuditorAssigned() || isUserAssignedToService()}
|
|
1504
|
-
/>
|
|
1505
|
-
</div>
|
|
1658
|
+
}}
|
|
1659
|
+
canAssign={![7, 8].includes(user.id_role)}
|
|
1660
|
+
/>
|
|
1661
|
+
<div
|
|
1662
|
+
className={
|
|
1663
|
+
"services-information-container " +
|
|
1664
|
+
(imageLayout && activeTab === "Imágenes" ? "image-services" : "")
|
|
1665
|
+
}
|
|
1666
|
+
>
|
|
1667
|
+
{loading ? (
|
|
1668
|
+
<Loading />
|
|
1669
|
+
) : (
|
|
1670
|
+
<>
|
|
1671
|
+
{!imageLayout &&
|
|
1672
|
+
activeTab === "Imágenes" &&
|
|
1673
|
+
product?.services?.images === 1 && (
|
|
1674
|
+
<GalleryHeader
|
|
1675
|
+
setSelectedImages={setSelectedImages}
|
|
1676
|
+
checkAll={checkAll}
|
|
1677
|
+
setCheckAll={setCheckAll}
|
|
1678
|
+
shotThd={shotThd}
|
|
1679
|
+
/>
|
|
1680
|
+
)}
|
|
1506
1681
|
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
headerData={state.product}
|
|
1511
|
-
productObservation={observation}
|
|
1512
|
-
percent={state.active_percentage.percentagesGeneral.required}
|
|
1513
|
-
activeRetailer={{
|
|
1514
|
-
id: state.active_retailer?.id_retailer,
|
|
1515
|
-
name: state.active_retailer?.retailer,
|
|
1516
|
-
image: state.active_retailer?.image,
|
|
1517
|
-
}}
|
|
1518
|
-
servicesData={state.services_data ? state.services_data : null}
|
|
1519
|
-
isObservationVisible={isObservationVisible}
|
|
1520
|
-
// actions
|
|
1521
|
-
setActiveRetailer={handleOnChangeActiveRetailer}
|
|
1522
|
-
approve={handleOnApproveSingleService}
|
|
1523
|
-
approveAll={handleOnApproveAllServices}
|
|
1524
|
-
reject={handleOnRejectSingleService}
|
|
1525
|
-
rejectAll={handleOnRejectAllServices}
|
|
1526
|
-
toggleObservation={handleOnToggleObservation}
|
|
1527
|
-
hideObservation={handleOnHideObservation}
|
|
1528
|
-
// sendToFacilitator={handleOnSendEvaluationToFacilitator} // No se usa?
|
|
1529
|
-
// validations
|
|
1530
|
-
showApproveRejectAll={
|
|
1531
|
-
canShowBulkEvaluationButtons() ||
|
|
1532
|
-
isAuditorAssigned() ||
|
|
1533
|
-
isUserAssignedToService()
|
|
1534
|
-
}
|
|
1535
|
-
showValidationButtons={
|
|
1536
|
-
canShowSingleEvaluationButtons() &&
|
|
1537
|
-
(isAuditorAssigned() || isUserAssignedToService())
|
|
1538
|
-
}
|
|
1539
|
-
/>
|
|
1540
|
-
<FullTabsMenu
|
|
1541
|
-
tabsSections={tabsSections}
|
|
1542
|
-
status={getStatusByCurrentServiceAndRetailer()}
|
|
1543
|
-
activeTab={state.active_tab}
|
|
1544
|
-
isRetailer={isRetailer}
|
|
1545
|
-
assig={state.collaborator_assignations[state.active_tab]}
|
|
1546
|
-
version={state.product.version}
|
|
1547
|
-
updatedDescriptions={state.updated_descriptions_inputs}
|
|
1548
|
-
updatedDatasheets={state.updated_datasheets_inputs}
|
|
1549
|
-
updatedImages={state.updated_images_values}
|
|
1550
|
-
images={state.services.images}
|
|
1551
|
-
// selectedImages={selectedImages} prop pasada asi: FullTabsMenu -> TabsMenu Pero en TabsMenu no se espera ninguna prop setSelectedImages
|
|
1552
|
-
// setters
|
|
1553
|
-
setActiveTab={handleOnChangeActiveTab}
|
|
1554
|
-
setImageLayout={handleOnToggleImageLayout}
|
|
1555
|
-
setUpdatedDescriptions={handleOnSetUpdatedDescriptions}
|
|
1556
|
-
setUpdatedDatasheets={handleOnSetUpdatedDatasheets}
|
|
1557
|
-
setAssignation={handleOnSetAssignation} // No se usa?
|
|
1558
|
-
setImages={handleOnSetImages} // No se usa?
|
|
1559
|
-
setShowVersionSelector={setShowVersionSelector}
|
|
1560
|
-
// setSelectedImages={setSelectedImages} prop pasada asi: FullTabsMenu -> TabsMenu Pero en TabsMenu no se espera ninguna prop setSelectedImages
|
|
1561
|
-
// actions
|
|
1562
|
-
downloadImages={handleOnDownloadImages}
|
|
1563
|
-
askToDeleteImages={handleOnAskToDeleteImages}
|
|
1564
|
-
showSaveButton={isAuditorAssigned() || isUserAssignedToService()}
|
|
1565
|
-
onClickSave={handleOnClickSave}
|
|
1566
|
-
// validations
|
|
1567
|
-
canAssign={![7, 8].includes(user.id_role)}
|
|
1568
|
-
/>
|
|
1569
|
-
<div
|
|
1570
|
-
className={
|
|
1571
|
-
"services-information-container " +
|
|
1572
|
-
(imageLayout && state.active_tab === "Imágenes"
|
|
1573
|
-
? "image-services"
|
|
1574
|
-
: "")
|
|
1575
|
-
}
|
|
1576
|
-
id="services-information-container"
|
|
1577
|
-
>
|
|
1578
|
-
{state.saving ? (
|
|
1579
|
-
<Loading />
|
|
1580
|
-
) : (
|
|
1581
|
-
<>
|
|
1582
|
-
{state.active_tab === "Descripción" &&
|
|
1583
|
-
(state.product?.description_status !== "NS" ? (
|
|
1682
|
+
{activeTab === "Ficha técnica" &&
|
|
1683
|
+
(product?.datasheet_status !== "NS" ? (
|
|
1684
|
+
datasheets[0]?.data?.map((dataGroup, index) => (
|
|
1584
1685
|
<InputGroup
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1686
|
+
key={index + "-" + activeRetailer.name}
|
|
1687
|
+
articleId={product.article.id_article}
|
|
1688
|
+
version={version}
|
|
1689
|
+
activeSection={activeTab}
|
|
1690
|
+
inputGroup={dataGroup}
|
|
1691
|
+
dataInputs={datasheets[1]}
|
|
1692
|
+
auditInputs={auditDatasheets[1]}
|
|
1693
|
+
updatedDatasheets={updatedDatasheets}
|
|
1694
|
+
setUpdatedDatasheets={setUpdatedDatasheets}
|
|
1593
1695
|
compare={compare}
|
|
1594
1696
|
/>
|
|
1595
|
-
)
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
headerType={"input-name-header"}
|
|
1629
|
-
/>
|
|
1630
|
-
))}
|
|
1631
|
-
{state.active_tab === "Imágenes" &&
|
|
1632
|
-
(state.product?.images_status !== "NS" ? (
|
|
1633
|
-
<>
|
|
1634
|
-
{!imageLayout && (
|
|
1635
|
-
<GalleryHeader
|
|
1636
|
-
checkAll={state.all_image_checked} // Determina si el checkbox "Seleccionar todo" está marcado
|
|
1637
|
-
setCheckAll={handleOnSetCheckAll} // Toggler de true o false para el checkbox "Seleccionar todo"
|
|
1638
|
-
setSelectedImages={handleOnSetSelectedImages}
|
|
1639
|
-
// shotThd={shotThd} // No se usa?
|
|
1640
|
-
/>
|
|
1641
|
-
)}
|
|
1642
|
-
<section
|
|
1643
|
-
className="container"
|
|
1644
|
-
style={{ position: "relative" }}
|
|
1645
|
-
>
|
|
1646
|
-
<div
|
|
1647
|
-
{...getRootProps({
|
|
1648
|
-
className: `dropzone ${
|
|
1649
|
-
isDragActive ? "drag-active" : ""
|
|
1650
|
-
}`,
|
|
1651
|
-
})}
|
|
1652
|
-
>
|
|
1653
|
-
<input {...getInputProps()} />
|
|
1654
|
-
{isDragActive && (
|
|
1655
|
-
<div className="drag-overlay">
|
|
1656
|
-
<p>Suelta las imágenes aquí</p>
|
|
1657
|
-
</div>
|
|
1658
|
-
)}
|
|
1659
|
-
<aside>{thumbs()}</aside>
|
|
1660
|
-
</div>
|
|
1661
|
-
{state.images_values?.values.length === 0 && (
|
|
1662
|
-
<div
|
|
1663
|
-
style={{
|
|
1664
|
-
position: "absolute",
|
|
1665
|
-
top: "50%",
|
|
1666
|
-
left: "50%",
|
|
1667
|
-
transform: "translate(-50%, -50%)",
|
|
1668
|
-
textAlign: "center",
|
|
1669
|
-
padding: "40px",
|
|
1670
|
-
width: "80%",
|
|
1671
|
-
maxWidth: "500px",
|
|
1672
|
-
fontFamily: "Arial, sans-serif",
|
|
1673
|
-
}}
|
|
1674
|
-
>
|
|
1675
|
-
<p
|
|
1676
|
-
style={{
|
|
1677
|
-
fontSize: "18px",
|
|
1678
|
-
color: "#666",
|
|
1679
|
-
marginBottom: "16px",
|
|
1680
|
-
}}
|
|
1681
|
-
>
|
|
1682
|
-
Este producto no tiene imágenes
|
|
1683
|
-
</p>
|
|
1684
|
-
{isAuditorAssigned() ||
|
|
1685
|
-
isUserAssignedToService() ? (
|
|
1686
|
-
<p
|
|
1687
|
-
style={{
|
|
1688
|
-
fontSize: "14px",
|
|
1689
|
-
color: "#999",
|
|
1690
|
-
marginBottom: "20px",
|
|
1691
|
-
}}
|
|
1692
|
-
>
|
|
1693
|
-
Arrastra las imágenes aquí o{" "}
|
|
1694
|
-
<span
|
|
1695
|
-
onClick={open}
|
|
1696
|
-
style={{
|
|
1697
|
-
color: "#007bff",
|
|
1698
|
-
cursor: "pointer",
|
|
1699
|
-
textDecoration: "underline",
|
|
1700
|
-
}}
|
|
1701
|
-
>
|
|
1702
|
-
haz clic para abrir el explorador de
|
|
1703
|
-
archivos
|
|
1704
|
-
</span>
|
|
1705
|
-
</p>
|
|
1706
|
-
) : null}
|
|
1707
|
-
</div>
|
|
1708
|
-
)}
|
|
1709
|
-
</section>
|
|
1710
|
-
</>
|
|
1711
|
-
) : (
|
|
1712
|
-
<ScreenHeader
|
|
1713
|
-
text={"No cuentas con este servicio"}
|
|
1714
|
-
headerType={"input-name-header"}
|
|
1715
|
-
/>
|
|
1716
|
-
))}
|
|
1717
|
-
</>
|
|
1718
|
-
)}
|
|
1719
|
-
</div>
|
|
1720
|
-
{(isUserAssignedToService(state.active_tab) ||
|
|
1721
|
-
isAuditorAssigned()) &&
|
|
1722
|
-
state.product[`${getConceptByTab(state.active_tab)}_status`] !==
|
|
1723
|
-
"NS" && (
|
|
1724
|
-
<div className="commentary-box">
|
|
1725
|
-
{!state.comment ? (
|
|
1726
|
-
<div className="commentary">
|
|
1727
|
-
<TagAndInput
|
|
1728
|
-
label={"Caja de Comentario"}
|
|
1729
|
-
inputType={"textarea"}
|
|
1730
|
-
inputCols={80}
|
|
1731
|
-
inputRows={4}
|
|
1732
|
-
inputId={"commentary-box"}
|
|
1733
|
-
index={0}
|
|
1734
|
-
/>
|
|
1735
|
-
<div className="buttons-box">
|
|
1736
|
-
<Button
|
|
1737
|
-
buttonType={"general-transparent-button"}
|
|
1738
|
-
label={"Enviar comentario"}
|
|
1739
|
-
onClick={handleOnSubmitComment}
|
|
1740
|
-
/>
|
|
1697
|
+
))
|
|
1698
|
+
) : (
|
|
1699
|
+
<ScreenHeader
|
|
1700
|
+
text={"No cuentas con este servicio"}
|
|
1701
|
+
headerType={"input-name-header"}
|
|
1702
|
+
/>
|
|
1703
|
+
))}
|
|
1704
|
+
{activeTab === "Descripción" &&
|
|
1705
|
+
(product?.description_status !== "NS" ? (
|
|
1706
|
+
<InputGroup
|
|
1707
|
+
activeSection={activeTab}
|
|
1708
|
+
inputGroup={descriptions[0]}
|
|
1709
|
+
auditInputGroup={auditDescriptions[0]}
|
|
1710
|
+
updatedDescriptions={updatedDescriptions}
|
|
1711
|
+
setUpdatedDescriptions={setUpdatedDescriptions}
|
|
1712
|
+
articleId={product?.article?.id_article}
|
|
1713
|
+
version={version}
|
|
1714
|
+
dinamicHeight={true}
|
|
1715
|
+
compare={compare}
|
|
1716
|
+
/>
|
|
1717
|
+
) : (
|
|
1718
|
+
<ScreenHeader
|
|
1719
|
+
text={"No cuentas con este servicio"}
|
|
1720
|
+
headerType={"input-name-header"}
|
|
1721
|
+
/>
|
|
1722
|
+
))}
|
|
1723
|
+
|
|
1724
|
+
{activeTab === "Imágenes" &&
|
|
1725
|
+
(product?.images_status !== "NS" ? (
|
|
1726
|
+
<section className="container">
|
|
1727
|
+
<div {...getRootProps({ className: "dropzone" })}>
|
|
1728
|
+
<input {...getInputProps()} />
|
|
1729
|
+
<aside>{thumbs()}</aside>
|
|
1741
1730
|
</div>
|
|
1742
|
-
</
|
|
1731
|
+
</section>
|
|
1743
1732
|
) : (
|
|
1744
|
-
<
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1733
|
+
<ScreenHeader
|
|
1734
|
+
text={"No cuentas con este servicio"}
|
|
1735
|
+
headerType={"input-name-header"}
|
|
1736
|
+
/>
|
|
1737
|
+
))}
|
|
1738
|
+
</>
|
|
1739
|
+
)}
|
|
1740
|
+
</div>
|
|
1741
|
+
{/* {(userAssigned(activeTab) || auditorAssigned()) &&
|
|
1742
|
+
product[`${getConcept(activeTab)}_status`] !== "NS" && (
|
|
1743
|
+
<div className="commentary-box">
|
|
1744
|
+
{[7, 8].includes(user.id_role) && (
|
|
1745
|
+
<Button
|
|
1746
|
+
buttonType={
|
|
1747
|
+
evaluationFinished(
|
|
1748
|
+
user.id_role,
|
|
1749
|
+
activeTab,
|
|
1750
|
+
statusArray
|
|
1751
|
+
) && requiredNull[activeTab] === 0
|
|
1752
|
+
? "general-green-button"
|
|
1753
|
+
: "general-button-disabled"
|
|
1754
|
+
}
|
|
1755
|
+
label={"Enviar evaluación"}
|
|
1756
|
+
onClick={() => sendToFacilitator()}
|
|
1757
|
+
/>
|
|
1758
|
+
)}
|
|
1759
|
+
</div>
|
|
1760
|
+
)} */}
|
|
1761
|
+
|
|
1762
|
+
{(userAssigned(activeTab) || auditorAssigned()) &&
|
|
1763
|
+
product[`${getConcept(activeTab)}_status`] !== "NS" && (
|
|
1764
|
+
<div className="commentary-box">
|
|
1765
|
+
{!comment ? (
|
|
1766
|
+
<div className="commentary">
|
|
1767
|
+
<TagAndInput
|
|
1768
|
+
label={"Caja de Comentario"}
|
|
1769
|
+
inputType={"textarea"}
|
|
1770
|
+
inputCols={80}
|
|
1771
|
+
inputRows={4}
|
|
1772
|
+
inputId={"commentary-box"}
|
|
1773
|
+
index={0}
|
|
1774
|
+
/>
|
|
1775
|
+
<div className="buttons-box">
|
|
1749
1776
|
<Button
|
|
1750
|
-
buttonType={"
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
commentRevised();
|
|
1754
|
-
}}
|
|
1777
|
+
buttonType={"general-transparent-button"}
|
|
1778
|
+
label={"Enviar comentario"}
|
|
1779
|
+
onClick={handleCommentSubmit}
|
|
1755
1780
|
/>
|
|
1756
1781
|
</div>
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
<div className="
|
|
1782
|
+
</div>
|
|
1783
|
+
) : (
|
|
1784
|
+
<div className="feedback-box">
|
|
1785
|
+
<Commentary
|
|
1786
|
+
comment={comment?.message}
|
|
1787
|
+
reviewed={crossComment}
|
|
1788
|
+
/>
|
|
1760
1789
|
<Button
|
|
1761
|
-
buttonType={"
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1790
|
+
buttonType={"circular-button accept-button"}
|
|
1791
|
+
onClick={async () => {
|
|
1792
|
+
setCrossComment(true);
|
|
1793
|
+
commentRevised();
|
|
1794
|
+
}}
|
|
1765
1795
|
/>
|
|
1766
|
-
{[7, 8].includes(user.id_role) && (
|
|
1767
|
-
<Button
|
|
1768
|
-
buttonType={
|
|
1769
|
-
isEvaluationFinished(
|
|
1770
|
-
user.id_role,
|
|
1771
|
-
state.active_tab,
|
|
1772
|
-
statusArray,
|
|
1773
|
-
) &&
|
|
1774
|
-
state.missing_required_fields[state.active_tab] === 0
|
|
1775
|
-
? "general-green-button"
|
|
1776
|
-
: "general-button-disabled"
|
|
1777
|
-
}
|
|
1778
|
-
label={"Enviar evaluación"}
|
|
1779
|
-
onClick={handleOnSendEvaluationToFacilitator}
|
|
1780
|
-
/>
|
|
1781
|
-
)}
|
|
1782
1796
|
</div>
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1797
|
+
)}
|
|
1798
|
+
{[7, 8].includes(user.id_role) && (
|
|
1799
|
+
<Button
|
|
1800
|
+
buttonType={
|
|
1801
|
+
evaluationFinished(
|
|
1802
|
+
user.id_role,
|
|
1803
|
+
activeTab,
|
|
1804
|
+
statusArray
|
|
1805
|
+
) && requiredNull[activeTab] === 0
|
|
1806
|
+
? "general-green-button"
|
|
1807
|
+
: "general-button-disabled"
|
|
1808
|
+
}
|
|
1809
|
+
label={"Enviar evaluación"}
|
|
1810
|
+
onClick={() => sendToFacilitator()}
|
|
1811
|
+
/>
|
|
1812
|
+
)}
|
|
1813
|
+
</div>
|
|
1814
|
+
)}
|
|
1786
1815
|
</div>
|
|
1787
|
-
</
|
|
1816
|
+
</div>
|
|
1817
|
+
{showModal && (
|
|
1818
|
+
<ProductImageModal
|
|
1819
|
+
images={images}
|
|
1820
|
+
setShowModal={setShowModal}
|
|
1821
|
+
sendToFacilitator={sendToFacilitator}
|
|
1822
|
+
approveRejectButtons={approveRejectButtons()}
|
|
1823
|
+
/>
|
|
1824
|
+
)}
|
|
1825
|
+
{message.length > 0 && (
|
|
1826
|
+
<GenericModal
|
|
1827
|
+
buttonType={componentsArray.length > 0 && "delete-product"}
|
|
1828
|
+
componentsArray={
|
|
1829
|
+
componentsArray.length > 0
|
|
1830
|
+
? componentsArray
|
|
1831
|
+
: [
|
|
1832
|
+
<img key="1" src={succes} alt="success icon" />,
|
|
1833
|
+
<ScreenHeader
|
|
1834
|
+
key="2"
|
|
1835
|
+
headerType={"retailer-name-header"}
|
|
1836
|
+
text={message}
|
|
1837
|
+
color={"white"}
|
|
1838
|
+
/>,
|
|
1839
|
+
]
|
|
1840
|
+
}
|
|
1841
|
+
onClick={() => setMessage("")}
|
|
1842
|
+
/>
|
|
1843
|
+
)}
|
|
1844
|
+
{showVersionSelector && (
|
|
1845
|
+
<VersionSelector
|
|
1846
|
+
modalId={"version-selector"}
|
|
1847
|
+
articleId={product.article.id_article}
|
|
1848
|
+
setVersion={setVersion}
|
|
1849
|
+
companyName={product.article.company_name}
|
|
1850
|
+
currentVersion={version}
|
|
1851
|
+
setShowVersionSelector={setShowVersionSelector}
|
|
1852
|
+
jwt={token}
|
|
1853
|
+
/>
|
|
1854
|
+
)}
|
|
1855
|
+
{showRejectModal && (
|
|
1856
|
+
<Modal
|
|
1857
|
+
title={`Agregar mensaje de rechazo para ${activeTab?.toLowerCase()}`}
|
|
1858
|
+
show={showRejectModal}
|
|
1859
|
+
customComponent={
|
|
1860
|
+
<TagAndInput
|
|
1861
|
+
inputType={"textarea"}
|
|
1862
|
+
inputId={"modal-message-box"}
|
|
1863
|
+
index={0}
|
|
1864
|
+
color={"white"}
|
|
1865
|
+
/>
|
|
1866
|
+
}
|
|
1867
|
+
buttons={[
|
|
1868
|
+
<ButtonV2
|
|
1869
|
+
key={"btn-Cancelar"}
|
|
1870
|
+
type={"white"}
|
|
1871
|
+
label={"Cancelar"}
|
|
1872
|
+
size={12}
|
|
1873
|
+
onClick={() => {
|
|
1874
|
+
setShowRejectModal(false);
|
|
1875
|
+
}}
|
|
1876
|
+
/>,
|
|
1877
|
+
<ButtonV2
|
|
1878
|
+
key={"btn-Aceptar"}
|
|
1879
|
+
type={"pink"}
|
|
1880
|
+
label={"Aceptar"}
|
|
1881
|
+
size={12}
|
|
1882
|
+
onClick={async (e) => {
|
|
1883
|
+
const elements = document.querySelectorAll(
|
|
1884
|
+
"#modal-message-box .ql-container .ql-editor > p"
|
|
1885
|
+
);
|
|
1886
|
+
|
|
1887
|
+
if (!elements || elements.length === 0) {
|
|
1888
|
+
console.error("Elemento no encontrado");
|
|
1889
|
+
return;
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
let brCounter = 0;
|
|
1893
|
+
|
|
1894
|
+
elements.forEach((el) => {
|
|
1895
|
+
const body = el.innerHTML;
|
|
1896
|
+
|
|
1897
|
+
if (typeof body !== "string") {
|
|
1898
|
+
console.log("El contenido de body no es una cadena", body);
|
|
1899
|
+
isMessageEmpty = true;
|
|
1900
|
+
return;
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
if (!body || body.replace(/<.*?\/?>/gm, "").trim() === "") {
|
|
1904
|
+
brCounter++;
|
|
1905
|
+
}
|
|
1906
|
+
});
|
|
1907
|
+
|
|
1908
|
+
if (brCounter === elements.length) {
|
|
1909
|
+
const container = document.querySelector(
|
|
1910
|
+
".container-customComponent"
|
|
1911
|
+
);
|
|
1912
|
+
|
|
1913
|
+
const existingAlert = container.querySelector(".alert-error");
|
|
1914
|
+
if (existingAlert) {
|
|
1915
|
+
return; // Si ya existe, no crear otra
|
|
1916
|
+
}
|
|
1788
1917
|
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1918
|
+
// Crear alerta con estilos
|
|
1919
|
+
const alert = document.createElement("div");
|
|
1920
|
+
alert.className = "alert-error";
|
|
1921
|
+
alert.style.cssText = `
|
|
1922
|
+
color: #d32f2f;
|
|
1923
|
+
background-color: #ffebee;
|
|
1924
|
+
border: 1px solid #ef5350;
|
|
1925
|
+
border-radius: 4px;
|
|
1926
|
+
padding: 12px 16px;
|
|
1927
|
+
margin-top: 10px;
|
|
1928
|
+
font-size: 14px;
|
|
1929
|
+
display: flex;
|
|
1930
|
+
align-items: center;
|
|
1931
|
+
gap: 8px;
|
|
1932
|
+
font-family: 'Roboto', sans-serif;
|
|
1933
|
+
text-align: center;
|
|
1934
|
+
`;
|
|
1935
|
+
|
|
1936
|
+
alert.innerHTML = `
|
|
1937
|
+
<span>El mensaje no puede estar vacío.</span>
|
|
1938
|
+
`;
|
|
1939
|
+
|
|
1940
|
+
container.appendChild(alert);
|
|
1941
|
+
return;
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
let fullMessage = "";
|
|
1945
|
+
|
|
1946
|
+
elements.forEach((element) => {
|
|
1947
|
+
const body = element.innerHTML;
|
|
1948
|
+
|
|
1949
|
+
fullMessage += body;
|
|
1950
|
+
});
|
|
1951
|
+
|
|
1952
|
+
fullMessage = fullMessage.replace(/<br\s*\/?>/gi, "\n");
|
|
1953
|
+
|
|
1954
|
+
await createComment(e, fullMessage, activeTab);
|
|
1955
|
+
valRejAll ? validateAll("R") : sendToFacilitator("R");
|
|
1956
|
+
setMessage("Rechazado");
|
|
1957
|
+
setShowRejectModal(false);
|
|
1958
|
+
}}
|
|
1959
|
+
/>,
|
|
1960
|
+
]}
|
|
1961
|
+
/>
|
|
1962
|
+
)}
|
|
1963
|
+
<Modal
|
|
1964
|
+
className="container-modalAlert"
|
|
1965
|
+
show={modalAlert.show}
|
|
1966
|
+
title={modalAlert.title}
|
|
1967
|
+
message={modalAlert.message}
|
|
1968
|
+
icon={"info"}
|
|
1969
|
+
onClickBtnDefault={(event) => {
|
|
1970
|
+
setModalAlert((prev) => ({
|
|
1971
|
+
...prev,
|
|
1972
|
+
show: false,
|
|
1973
|
+
errorInputMessage: false,
|
|
1974
|
+
}));
|
|
1794
1975
|
}}
|
|
1795
|
-
reloadData={loadData}
|
|
1796
|
-
token={token}
|
|
1797
1976
|
/>
|
|
1798
|
-
</
|
|
1799
|
-
);
|
|
1800
|
-
};
|
|
1801
|
-
|
|
1802
|
-
export const RetailerProductEdition = (props) => {
|
|
1803
|
-
return (
|
|
1804
|
-
<ProviderProductEditionProvider>
|
|
1805
|
-
<RetailerProductEditionView {...props} />
|
|
1806
|
-
</ProviderProductEditionProvider>
|
|
1977
|
+
</Container>
|
|
1807
1978
|
);
|
|
1808
1979
|
};
|