contentoh-components-library 21.6.12 → 21.6.14

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.
@@ -238,8 +238,12 @@ const ProviderProductEditionView = ({
238
238
  }),
239
239
  ]);
240
240
 
241
- const percentages =
242
- JSON.parse(percentageRes?.[0]?.body)?.[0]?.relations ?? [];
241
+ const percentageRaw = percentageRes?.[0];
242
+ const percentages = (
243
+ Array.isArray(percentageRaw)
244
+ ? percentageRaw[0]?.relations
245
+ : JSON.parse(percentageRaw?.body ?? "null")?.[0]?.relations
246
+ ) ?? [];
243
247
 
244
248
  const orderMap =
245
249
  services[2].inputsByRetailer ??
@@ -307,11 +311,15 @@ const ProviderProductEditionView = ({
307
311
 
308
312
  dispatch({ type: "SET_PERCENTAGES", payload: percentages });
309
313
 
314
+ const activePercentage =
315
+ percentages.find(({ id_retailer: rId }) => rId === id_retailer) ||
316
+ state.product.percentages?.find(
317
+ ({ id_retailer: rId }) => rId === id_retailer,
318
+ );
319
+
310
320
  dispatch({
311
321
  type: "SET_ACTIVE_PERCENTAGES",
312
- payload: percentages.find(
313
- ({ id_retailer: rId }) => rId === id_retailer,
314
- ),
322
+ payload: activePercentage,
315
323
  });
316
324
  } catch (error) {
317
325
  console.error("Error fetching data:", error);
@@ -343,14 +351,18 @@ const ProviderProductEditionView = ({
343
351
  if (state.services.datasheets) {
344
352
  const retailerDatasheets =
345
353
  state.services.datasheets[state.active_retailer.id_retailer];
346
- const datasheetsActiveRetailer = {
347
- ...retailerDatasheets,
348
- data: Object.values(retailerDatasheets.data),
349
- };
350
- dispatch({
351
- type: "SET_DATASHEETS_INPUTS",
352
- payload: [datasheetsActiveRetailer, state.services.datasheets.inputs],
353
- });
354
+ if (retailerDatasheets) {
355
+ const datasheetsActiveRetailer = {
356
+ ...retailerDatasheets,
357
+ data: Object.values(retailerDatasheets.data),
358
+ };
359
+ dispatch({
360
+ type: "SET_DATASHEETS_INPUTS",
361
+ payload: [datasheetsActiveRetailer, state.services.datasheets.inputs],
362
+ });
363
+ } else {
364
+ dispatch({ type: "SET_DATASHEETS_INPUTS", payload: [] });
365
+ }
354
366
  }
355
367
 
356
368
  if (state.services.descriptions) {
@@ -1319,7 +1331,7 @@ const ProviderProductEditionView = ({
1319
1331
  <div className="product-information">
1320
1332
  <FullProductNameHeader
1321
1333
  headerData={state.product}
1322
- percent={state.active_percentage.percentagesGeneral.required}
1334
+ percent={state.active_percentage?.percentagesGeneral?.required}
1323
1335
  activeRetailer={{
1324
1336
  id: state.active_retailer?.id_retailer,
1325
1337
  name: state.active_retailer?.retailer,
@@ -1333,6 +1345,7 @@ const ProviderProductEditionView = ({
1333
1345
  approve={() => handleOnSendEvaluation("A")}
1334
1346
  reject={handleOnReject}
1335
1347
  setActiveRetailer={handleOnChangeActiveRetailer}
1348
+ showStatus={false}
1336
1349
  />
1337
1350
  <FullTabsMenu
1338
1351
  tabsSections={tabsSections}
@@ -1375,21 +1388,28 @@ const ProviderProductEditionView = ({
1375
1388
  <>
1376
1389
  {state.active_tab === "Descripción" &&
1377
1390
  (state.product?.description_status !== "NS" ? (
1378
- <InputGroup
1379
- activeSection={state.active_tab}
1380
- inputGroup={state.descriptions_inputs[0]}
1381
- updatedDescriptions={
1382
- state.updated_descriptions_inputs
1383
- }
1384
- articleId={state.product?.id_article}
1385
- version={state.product.version}
1386
- isShowbox={false}
1387
- dinamicHeight={true}
1388
- setUpdatedDescriptions={
1389
- handleOnSetUpdatedDescriptions
1390
- }
1391
- updateApprovedInputs={handleOnUpdateApprovedInputs} // No se usa?
1392
- />
1391
+ state.descriptions_inputs?.[0] ? (
1392
+ <InputGroup
1393
+ activeSection={state.active_tab}
1394
+ inputGroup={state.descriptions_inputs[0]}
1395
+ updatedDescriptions={
1396
+ state.updated_descriptions_inputs
1397
+ }
1398
+ articleId={state.product?.id_article}
1399
+ version={state.product.version}
1400
+ isShowbox={false}
1401
+ dinamicHeight={true}
1402
+ setUpdatedDescriptions={
1403
+ handleOnSetUpdatedDescriptions
1404
+ }
1405
+ updateApprovedInputs={handleOnUpdateApprovedInputs}
1406
+ />
1407
+ ) : (
1408
+ <ScreenHeader
1409
+ text={"No hay descripción para esta cadena"}
1410
+ headerType={"input-name-header"}
1411
+ />
1412
+ )
1393
1413
  ) : (
1394
1414
  <ScreenHeader
1395
1415
  text={"No cuentas con este servicio"}
@@ -1400,43 +1420,50 @@ const ProviderProductEditionView = ({
1400
1420
  {state.active_tab === "Ficha técnica" &&
1401
1421
  (state.product?.datasheet_status !== "NS" ? (
1402
1422
  <>
1403
- {state.datasheets_inputs[0]?.data?.map(
1404
- (dataGroup, index) => (
1405
- <InputGroup
1406
- index={index}
1407
- key={
1408
- index + "-" + state.active_retailer.retailer
1409
- }
1410
- articleId={state.product.id_article}
1411
- version={state.version}
1412
- activeSection={state.active_tab}
1413
- inputGroup={dataGroup}
1414
- dataInputs={state.datasheets_inputs[1] ?? []}
1415
- activeRetailer={
1416
- state.services.datasheets[
1417
- state.active_retailer.id_retailer
1418
- ]
1419
- }
1420
- groupData={
1421
- state.services.datasheets[
1422
- state.active_retailer.id_retailer
1423
- ].data
1424
- }
1425
- updatedDatasheets={
1426
- state.updated_datasheets_inputs
1427
- }
1428
- setUpdatedDatasheets={
1429
- handleOnSetUpdatedDatasheets
1430
- }
1431
- isShowbox={true}
1432
- setUpdatedBoxData={(e) => {
1433
- setBoxData(e);
1434
- }}
1435
- updateApprovedInputs={
1436
- handleOnUpdateApprovedInputs // No se usa?
1437
- }
1438
- />
1439
- ),
1423
+ {state.datasheets_inputs?.[0]?.data?.length > 0 ? (
1424
+ state.datasheets_inputs[0].data.map(
1425
+ (dataGroup, index) => (
1426
+ <InputGroup
1427
+ index={index}
1428
+ key={
1429
+ index + "-" + state.active_retailer.retailer
1430
+ }
1431
+ articleId={state.product.id_article}
1432
+ version={state.version}
1433
+ activeSection={state.active_tab}
1434
+ inputGroup={dataGroup}
1435
+ dataInputs={state.datasheets_inputs[1] ?? []}
1436
+ activeRetailer={
1437
+ state.services.datasheets[
1438
+ state.active_retailer.id_retailer
1439
+ ]
1440
+ }
1441
+ groupData={
1442
+ state.services.datasheets[
1443
+ state.active_retailer.id_retailer
1444
+ ]?.data
1445
+ }
1446
+ updatedDatasheets={
1447
+ state.updated_datasheets_inputs
1448
+ }
1449
+ setUpdatedDatasheets={
1450
+ handleOnSetUpdatedDatasheets
1451
+ }
1452
+ isShowbox={true}
1453
+ setUpdatedBoxData={(e) => {
1454
+ setBoxData(e);
1455
+ }}
1456
+ updateApprovedInputs={
1457
+ handleOnUpdateApprovedInputs
1458
+ }
1459
+ />
1460
+ ),
1461
+ )
1462
+ ) : (
1463
+ <ScreenHeader
1464
+ text={"No hay ficha técnica para esta cadena"}
1465
+ headerType={"input-name-header"}
1466
+ />
1440
1467
  )}
1441
1468
  </>
1442
1469
  ) : (
@@ -24,9 +24,13 @@ export const normalizeProduct = (product) => {
24
24
  productData.statusByRetailer || {}
25
25
  ).map((id) => parseInt(id, 10));
26
26
 
27
- const categoryRetailerInOrder = categoryRetailerNormalized.filter((rel) =>
28
- retailersIdsFromStatusByRetailer.includes(rel.id_retailer)
29
- );
27
+ const categoryRetailerInOrder = categoryRetailerNormalized
28
+ ? retailersIdsFromStatusByRetailer.length > 0
29
+ ? categoryRetailerNormalized.filter((rel) =>
30
+ retailersIdsFromStatusByRetailer.includes(rel.id_retailer)
31
+ )
32
+ : categoryRetailerNormalized
33
+ : [];
30
34
 
31
35
  return {
32
36
  // from products
@@ -11,6 +11,7 @@ import { v4 as uuidv4 } from "uuid";
11
11
 
12
12
  import successIcon from "../../../../assets/images/genericModal/genericModalCheck.svg";
13
13
  import errorIcon from "../../../../assets/images/genericModal/errorModal.svg";
14
+ import warningIcon from "../../../../assets/images/genericModal/genericModalWarning.svg";
14
15
  import { getConceptByTab } from "../utils";
15
16
 
16
17
  const S3_BUCKET = process.env.REACT_APP_IMAGES_BUCKET;
@@ -230,7 +231,11 @@ export const ProviderProductEditionProvider = ({ children }) => {
230
231
  };
231
232
 
232
233
  const updateImages = async (token) => {
233
- if (state.updated_images_values.length === 0) return;
234
+ // Imágenes/videos recién agregados a la galería (aún sin id en BD).
235
+ const newImages = state.images_values?.values?.filter((e) => !e.id) || [];
236
+ // Salir solo si no hay nada que crear ni que actualizar.
237
+ if (state.updated_images_values.length === 0 && newImages.length === 0)
238
+ return;
234
239
  const updatedImages = state.updated_images_values;
235
240
 
236
241
  const attrForImgs = state.images_values?.attrForImgs || {};
@@ -282,10 +287,16 @@ export const ProviderProductEditionProvider = ({ children }) => {
282
287
 
283
288
  try {
284
289
  const promiseArray = data.articleData.map((e) => {
285
- const file = Buffer.from(
286
- e.src.replace(/^data:image\/\w+;base64,/, ""),
287
- "base64",
288
- );
290
+ const file =
291
+ e.ext === "mp4"
292
+ ? Buffer.from(
293
+ (e.video_src || "").replace(/^data:video\/\w+;base64,/, ""),
294
+ "base64",
295
+ )
296
+ : Buffer.from(
297
+ e.src.replace(/^data:image\/\w+;base64,/, ""),
298
+ "base64",
299
+ );
289
300
  const params = {
290
301
  ACL: "public-read",
291
302
  Body: file,
@@ -298,8 +309,12 @@ export const ProviderProductEditionProvider = ({ children }) => {
298
309
  await Promise.all(promiseArray);
299
310
 
300
311
  // Eliminar el buffer base64 antes de enviar al endpoint para evitar error 413
301
- data.articleData = data.articleData.map(({ src, ...rest }) => rest);
302
- data.updateImages = data.updateImages.map(({ src, ...rest }) => rest);
312
+ data.articleData = data.articleData.map(
313
+ ({ src, video_src, ...rest }) => rest,
314
+ );
315
+ data.updateImages = data.updateImages.map(
316
+ ({ src, video_src, ...rest }) => rest,
317
+ );
303
318
 
304
319
  const res = await axios.put(
305
320
  process.env.REACT_APP_ARTICLE_DATA_ENDPOINT,
@@ -60,6 +60,7 @@ import imagesSent from "../../../assets/images/modalsSVGs/uploadingImages.svg";
60
60
 
61
61
  import { Container } from "./styles";
62
62
  import { Commentary } from "../../atoms/Commentary";
63
+ import generateThumbnail from "./generateThumnail";
63
64
 
64
65
  import { AiProductEditionProvider } from "../../../contexts/AiProductEdition";
65
66
  import ChangeStatusModal from "../../organisms/ChangeStatusModal";
@@ -80,9 +81,69 @@ const allowedAccountsToViewChangeStatus = [
80
81
  "kikije1467@mtlcz.com", //IMÁGENES
81
82
  "karafe3218@mom2kid.com", //TEXTOS
82
83
  "ladiboh785@mi166.com", //QA
83
-
84
84
  ];
85
85
 
86
+ function obtenerDuracionVideoBase64(base64Data) {
87
+ return new Promise((resolve, reject) => {
88
+ const video = document.createElement("video");
89
+ video.src = base64Data;
90
+ video.addEventListener("loadedmetadata", () => {
91
+ resolve(video.duration);
92
+ });
93
+ video.addEventListener("error", reject);
94
+ });
95
+ }
96
+
97
+ function convertirVideoABase64(url) {
98
+ return new Promise((resolve, reject) => {
99
+ const xhr = new XMLHttpRequest();
100
+ xhr.open("GET", url, true);
101
+ xhr.responseType = "blob";
102
+ xhr.onload = function () {
103
+ if (xhr.status === 200) {
104
+ const blob = xhr.response;
105
+ const reader = new FileReader();
106
+ reader.onloadend = function () {
107
+ resolve(reader.result);
108
+ };
109
+ reader.readAsDataURL(blob);
110
+ } else {
111
+ reject(new Error("Error al cargar el video"));
112
+ }
113
+ };
114
+ xhr.onerror = function () {
115
+ reject(new Error("Error de red al cargar el video"));
116
+ };
117
+ xhr.send();
118
+ });
119
+ }
120
+
121
+ // Para videos ya guardados, `getImage` deja en `src` una URL del
122
+ // redimensionador de imágenes que no sirve para mp4. Descargamos el video
123
+ // desde S3 (srcDB) y generamos un thumbnail JPEG para mostrarlo en la galería.
124
+ async function regenerateVideoThumbnails(values) {
125
+ if (!Array.isArray(values)) return values;
126
+ return Promise.all(
127
+ values.map(async (value) => {
128
+ if (value?.ext !== "mp4" || !value?.srcDB) return value;
129
+ try {
130
+ const base64 = await convertirVideoABase64(
131
+ "https://" +
132
+ process.env.REACT_APP_IMAGES_BUCKET +
133
+ ".s3.amazonaws.com/" +
134
+ value.srcDB,
135
+ );
136
+ const videoSrc = "data:video/mp4;base64," + base64.split(",")[1];
137
+ const thumbnail = await generateThumbnail(videoSrc, 2);
138
+ return { ...value, src: thumbnail };
139
+ } catch (error) {
140
+ console.error("Error al generar thumbnail del video:", error);
141
+ return value;
142
+ }
143
+ }),
144
+ );
145
+ }
146
+
86
147
  const RetailerProductEditionView = ({
87
148
  tabsSections,
88
149
  productSelected = {},
@@ -124,7 +185,7 @@ const RetailerProductEditionView = ({
124
185
 
125
186
  const [compare, setCompare] = useState(false);
126
187
  const { getRootProps, getInputProps, isDragActive, open } = useDropzone({
127
- accept: "image/*",
188
+ accept: "image/*, video/mp4",
128
189
  noKeyboard: true,
129
190
  multiple: true,
130
191
  noClick: true,
@@ -139,8 +200,48 @@ const RetailerProductEditionView = ({
139
200
  const fileDataURL = e.target.result;
140
201
 
141
202
  const img = new Image();
142
- img.src = fileDataURL;
143
203
 
204
+ if (fileExtension === "mp4") {
205
+ try {
206
+ const duracion = await obtenerDuracionVideoBase64(fileDataURL);
207
+ if (duracion <= 10 || duracion >= 600) {
208
+ dispatch({
209
+ type: "SET_MODAL",
210
+ payload: {
211
+ show: true,
212
+ title: "Hubo un error al subir el video",
213
+ message:
214
+ "Los videos deben durar entre 15 segundos y 10 minutos",
215
+ image: errorIcon,
216
+ },
217
+ });
218
+ return;
219
+ }
220
+
221
+ img.src = await generateThumbnail(fileDataURL, 2);
222
+ img.onload = function () {
223
+ const newImg = {
224
+ src: img.src,
225
+ name: fileName,
226
+ ext: fileExtension,
227
+ width: img.width,
228
+ height: img.height,
229
+ video_src: fileDataURL,
230
+ isApproved: true, // VALIDAR QUE SOLO SEA PARA RADIOSHACK
231
+ };
232
+
233
+ dispatch({
234
+ type: "ADD_IMAGE_VALUE",
235
+ payload: newImg,
236
+ });
237
+ };
238
+ } catch (error) {
239
+ console.error("Error al obtener la duración del video:", error);
240
+ }
241
+ return;
242
+ }
243
+
244
+ img.src = fileDataURL;
144
245
  img.onload = function () {
145
246
  const width = img.width;
146
247
  const height = img.height;
@@ -150,6 +251,7 @@ const RetailerProductEditionView = ({
150
251
  ext: fileExtension,
151
252
  width: width,
152
253
  height: height,
254
+ video_src: "",
153
255
  isApproved: true, // VALIDAR QUE SOLO SEA PARA RADIOSHACK
154
256
  };
155
257
 
@@ -220,11 +322,13 @@ const RetailerProductEditionView = ({
220
322
 
221
323
  const initializeProduct = async () => {
222
324
  try {
223
- const product = productSelected ? productSelected : JSON.parse(sessionStorage.getItem("productSelected"));
325
+ const product = productSelected
326
+ ? productSelected
327
+ : JSON.parse(sessionStorage.getItem("productSelected"));
224
328
 
225
329
  const productNormalized = normalizeProduct(product);
226
330
 
227
- console.log({productNormalized});
331
+ console.log({ productNormalized });
228
332
 
229
333
  dispatch({
230
334
  type: "SET_PRODUCT",
@@ -401,6 +505,8 @@ const RetailerProductEditionView = ({
401
505
  });
402
506
  dispatch({ type: "SET_COMMENTS", payload: commentsMap });
403
507
 
508
+ console.log("services", services);
509
+
404
510
  // Ordenamiento de imágenes
405
511
  const orderMap = services[2].inputsByRetailer
406
512
  .flat()
@@ -436,6 +542,12 @@ const RetailerProductEditionView = ({
436
542
  );
437
543
  });
438
544
 
545
+ // Regenerar thumbnails de videos guardados para que se muestren.
546
+ const orderedValuesWithThumbs =
547
+ await regenerateVideoThumbnails(orderedValues);
548
+ const filteredValuesWithThumbs =
549
+ await regenerateVideoThumbnails(filteredValues);
550
+
439
551
  // Dispatch consolidado
440
552
  dispatch({
441
553
  type: "SET_SERVICES",
@@ -444,7 +556,7 @@ const RetailerProductEditionView = ({
444
556
  descriptions: services[1],
445
557
  images: {
446
558
  ...services[2],
447
- values: orderedValues,
559
+ values: orderedValuesWithThumbs,
448
560
  },
449
561
  },
450
562
  });
@@ -473,7 +585,7 @@ const RetailerProductEditionView = ({
473
585
  type: "SET_IMAGES_VALUES",
474
586
  payload: {
475
587
  ...services[2],
476
- values: filteredValues,
588
+ values: filteredValuesWithThumbs,
477
589
  },
478
590
  });
479
591
 
@@ -750,10 +862,11 @@ const RetailerProductEditionView = ({
750
862
  );
751
863
 
752
864
  const newStatuses = JSON.parse(res.data.body);
753
- const serviceStatus = newStatuses.newServiceStatus[articleId][`${concept}Status`];
865
+ const serviceStatus =
866
+ newStatuses.newServiceStatus[articleId][`${concept}Status`];
754
867
  const articleStatus = newStatuses.newArticleStatus[articleId];
755
868
 
756
- console.log({newStatuses});
869
+ console.log({ newStatuses });
757
870
 
758
871
  // Actualizar el producto con los nuevos estados
759
872
  const updatedStatusByRetailer = state.product.statusByRetailer.map(
@@ -782,7 +895,8 @@ const RetailerProductEditionView = ({
782
895
  image: successIcon,
783
896
  },
784
897
  });
785
- } else { //Caso del botón "Enviar evaluación"
898
+ } else {
899
+ //Caso del botón "Enviar evaluación"
786
900
 
787
901
  //Se construye el mensaje y se actualiza el estatus
788
902
 
@@ -809,12 +923,13 @@ const RetailerProductEditionView = ({
809
923
  }
810
924
 
811
925
  if (res.data.statusCode === 200) {
812
-
813
- const { newStatus, newOrderStatus, newArticleStatus } = JSON.parse( res.data.body );
926
+ const { newStatus, newOrderStatus, newArticleStatus } = JSON.parse(
927
+ res.data.body,
928
+ );
814
929
 
815
930
  const articleStatus = newArticleStatus[articleId];
816
931
 
817
- console.log({newArticleStatus});
932
+ console.log({ newArticleStatus });
818
933
 
819
934
  // const retailers = state.product.categoryRetailer.map((r) => ({
820
935
  // id: r.id_retailer,
@@ -840,12 +955,13 @@ const RetailerProductEditionView = ({
840
955
  // };
841
956
  // await sendMessage(messageData);
842
957
 
843
- const updatedStatusByRetailerForSend = state.product.statusByRetailer.map((item) => {
844
- if (item.retailer_id === retailerId && item.service === concept) {
845
- return { ...item, status: newStatus };
846
- }
847
- return item;
848
- });
958
+ const updatedStatusByRetailerForSend =
959
+ state.product.statusByRetailer.map((item) => {
960
+ if (item.retailer_id === retailerId && item.service === concept) {
961
+ return { ...item, status: newStatus };
962
+ }
963
+ return item;
964
+ });
849
965
 
850
966
  const updatedProduct = {
851
967
  ...state.product,
@@ -856,9 +972,12 @@ const RetailerProductEditionView = ({
856
972
 
857
973
  //Actualizamos el services_data en el servicio específico del retailer actual
858
974
 
859
- const updatedServicesData = state.services_data?.map(service => ({
975
+ const updatedServicesData = state.services_data?.map((service) => ({
860
976
  ...service,
861
- status: service?.id_retailer === retailerId && service?.service === concept ? newStatus : service?.status
977
+ status:
978
+ service?.id_retailer === retailerId && service?.service === concept
979
+ ? newStatus
980
+ : service?.status,
862
981
  }));
863
982
 
864
983
  const sessionProduct = sessionStorage.getItem("productSelected");
@@ -929,11 +1048,18 @@ const RetailerProductEditionView = ({
929
1048
  const conceptArray = getConceptsByRole(user.id_role);
930
1049
 
931
1050
  state.services_data?.forEach((ret, idx) => {
932
- const { service: retailer_service, id_retailer, status: status_retailer_service } = ret;
1051
+ const {
1052
+ service: retailer_service,
1053
+ id_retailer,
1054
+ status: status_retailer_service,
1055
+ } = ret;
933
1056
 
934
1057
  const lastStatusLevel = status_retailer_service?.replace(/.*\//, "");
935
1058
 
936
- if (conceptArray.includes(retailer_service) && statusArray?.includes(lastStatusLevel)) {
1059
+ if (
1060
+ conceptArray.includes(retailer_service) &&
1061
+ statusArray?.includes(lastStatusLevel)
1062
+ ) {
937
1063
  const data = {
938
1064
  articleId: state.product.id_article,
939
1065
  orderId: state.product.id_order,
@@ -981,7 +1107,11 @@ const RetailerProductEditionView = ({
981
1107
  payload: updatedProduct,
982
1108
  });
983
1109
 
984
- const updatedServicesData = state.services_data.map(service => conceptArray.includes(service.service) ? { ...service, status: status } : service);
1110
+ const updatedServicesData = state.services_data.map((service) =>
1111
+ conceptArray.includes(service.service)
1112
+ ? { ...service, status: status }
1113
+ : service,
1114
+ );
985
1115
 
986
1116
  dispatch({
987
1117
  type: "SET_SERVICES_DATA",
@@ -1142,8 +1272,9 @@ const RetailerProductEditionView = ({
1142
1272
  switch (id_rol) {
1143
1273
  case 7:
1144
1274
  case 8:
1145
-
1146
- const canSendEvaluation = statusArray.includes(statusBySelectedRetailerService);
1275
+ const canSendEvaluation = statusArray.includes(
1276
+ statusBySelectedRetailerService,
1277
+ );
1147
1278
 
1148
1279
  // const conditionTwo = statusArray.includes(product?.status);
1149
1280
 
@@ -1180,7 +1311,7 @@ const RetailerProductEditionView = ({
1180
1311
  };
1181
1312
 
1182
1313
  const handleOnChangeProductVersion = (version) => {
1183
- console.log('se cambia la version')
1314
+ console.log("se cambia la version");
1184
1315
  dispatch({
1185
1316
  type: "SET_PRODUCT_VERSION",
1186
1317
  payload: version,
@@ -1310,12 +1441,12 @@ const RetailerProductEditionView = ({
1310
1441
  </Box>
1311
1442
  </div>
1312
1443
  </div>
1313
- </Container>
1444
+ </Container>
1314
1445
  );
1315
1446
  };
1316
1447
 
1317
1448
  useEffect(() => {
1318
- console.log({stateProduct: state.product})
1449
+ console.log({ stateProduct: state.product });
1319
1450
  }, [state.product]);
1320
1451
 
1321
1452
  if (state.loading || !state.services || !state.product)
@@ -1789,16 +1920,16 @@ const RetailerProductEditionView = ({
1789
1920
  )}
1790
1921
 
1791
1922
  <div className="action-buttons">
1792
- {
1793
- allowedAccountsToViewChangeStatus.includes(user?.email) && (
1794
- <Button
1795
- buttonType={"general-pink-button"}
1796
- label={"Cambio de Estatus"}
1797
- onClick={() => setOpenChangeStatusModal(true)}
1798
- id="button-change-status"
1799
- />
1800
- )
1801
- }
1923
+ {allowedAccountsToViewChangeStatus.includes(
1924
+ user?.email,
1925
+ ) && (
1926
+ <Button
1927
+ buttonType={"general-pink-button"}
1928
+ label={"Cambio de Estatus"}
1929
+ onClick={() => setOpenChangeStatusModal(true)}
1930
+ id="button-change-status"
1931
+ />
1932
+ )}
1802
1933
  {[7, 8].includes(user.id_role) && (
1803
1934
  <Button
1804
1935
  buttonType={
@@ -201,5 +201,6 @@ export const getServicesData = async ({ articleId, orderId, end, token }) => {
201
201
  }
202
202
  );
203
203
 
204
- return JSON.parse(servicesResponse?.data?.body).data;
204
+ const body = servicesResponse?.data?.body;
205
+ return body ? JSON.parse(body).data ?? [] : [];
205
206
  };