contentoh-components-library 21.5.91 → 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.
Files changed (66) hide show
  1. package/dist/components/atoms/GeneralButton/styles.js +1 -1
  2. package/dist/components/atoms/GeneralInput/index.js +54 -245
  3. package/dist/components/atoms/GeneralInput/styles.js +3 -7
  4. package/dist/components/atoms/InputFormatter/index.js +68 -223
  5. package/dist/components/atoms/InputFormatter/styles.js +4 -20
  6. package/dist/components/molecules/StatusAsignationInfo/index.js +1 -11
  7. package/dist/components/molecules/TabsMenu/index.js +12 -13
  8. package/dist/components/molecules/TagAndInput/index.js +24 -361
  9. package/dist/components/molecules/TagAndInput/styles.js +2 -2
  10. package/dist/components/organisms/FullProductNameHeader/index.js +22 -6
  11. package/dist/components/organisms/InputGroup/index.js +18 -22
  12. package/dist/components/pages/ProviderProductEdition/index.js +47 -34
  13. package/dist/components/pages/ProviderProductEdition/utils.js +0 -1
  14. package/dist/components/pages/RetailerProductEdition/RetailerProductEdition.stories.js +196 -179
  15. package/dist/components/pages/RetailerProductEdition/context/provider-product-edition.context.js +260 -59
  16. package/dist/components/pages/RetailerProductEdition/context/reducers/product.js +38 -50
  17. package/dist/components/pages/RetailerProductEdition/index.js +2234 -1715
  18. package/dist/components/pages/RetailerProductEdition/styles.js +2 -4
  19. package/dist/components/pages/RetailerProductEdition/utils.js +2 -251
  20. package/dist/contexts/AiProductEdition.js +157 -234
  21. package/package.json +2 -4
  22. package/src/components/atoms/GeneralButton/styles.js +0 -4
  23. package/src/components/atoms/GeneralInput/index.js +60 -237
  24. package/src/components/atoms/GeneralInput/styles.js +0 -81
  25. package/src/components/atoms/InputFormatter/index.js +51 -200
  26. package/src/components/atoms/InputFormatter/styles.js +0 -284
  27. package/src/components/molecules/StatusAsignationInfo/index.js +1 -9
  28. package/src/components/molecules/TabsMenu/index.js +11 -12
  29. package/src/components/molecules/TagAndInput/index.js +21 -286
  30. package/src/components/molecules/TagAndInput/styles.js +17 -59
  31. package/src/components/organisms/FullProductNameHeader/index.js +28 -4
  32. package/src/components/organisms/FullTabsMenu/index.js +1 -1
  33. package/src/components/organisms/InputGroup/index.js +4 -12
  34. package/src/components/pages/ProviderProductEdition/index.js +69 -51
  35. package/src/components/pages/ProviderProductEdition/utils.js +2 -2
  36. package/src/components/pages/RetailerProductEdition/RetailerProductEdition.stories.js +224 -201
  37. package/src/components/pages/RetailerProductEdition/index.js +1718 -1546
  38. package/src/components/pages/RetailerProductEdition/styles.js +2 -67
  39. package/src/components/pages/RetailerProductEdition/utils.js +0 -240
  40. package/dist/ai/utils/compare-strings.js +0 -45
  41. package/dist/components/organisms/ChangeStatusModal/index.js +0 -531
  42. package/dist/components/organisms/ChangeStatusModal/styles.js +0 -85
  43. package/dist/global-files/statusDictionary.js +0 -103
  44. package/src/ai/utils/compare-strings.js +0 -45
  45. package/src/assets/images/Icons/arrow.png +0 -0
  46. package/src/assets/images/Icons/cancel.png +0 -0
  47. package/src/assets/images/Icons/ia-icon.png +0 -0
  48. package/src/assets/images/Icons/loading.svg +0 -5
  49. package/src/assets/images/Icons/reload.png +0 -0
  50. package/src/components/atoms/RetailerSelector/RetailerSelector.stories.js +0 -10
  51. package/src/components/atoms/RetailerSelector/index.js +0 -3
  52. package/src/components/atoms/RetailerSelector/styles.js +0 -0
  53. package/src/components/organisms/ChangeStatusModal/index.jsx +0 -488
  54. package/src/components/organisms/ChangeStatusModal/styles.js +0 -333
  55. package/src/components/pages/RetailerProductEdition/context/provider-product-edition.context.jsx +0 -575
  56. package/src/components/pages/RetailerProductEdition/context/provider-product-edition.reducer.js +0 -62
  57. package/src/components/pages/RetailerProductEdition/context/reducers/active-state.js +0 -344
  58. package/src/components/pages/RetailerProductEdition/context/reducers/inputs.js +0 -155
  59. package/src/components/pages/RetailerProductEdition/context/reducers/product.js +0 -114
  60. package/src/components/pages/RetailerProductEdition/context/reducers/system.js +0 -60
  61. package/src/components/pages/RetailerProductEdition/index_old.js +0 -1979
  62. package/src/components/pages/RetailerProductEdition/stories/Auditor.stories.js +0 -101
  63. package/src/components/pages/RetailerProductEdition/stories/ImageEditor.stories.js +0 -115
  64. package/src/components/pages/RetailerProductEdition/stories/TextEditor.stories.js +0 -174
  65. package/src/contexts/AiProductEdition.jsx +0 -344
  66. package/src/global-files/statusDictionary.js +0 -103
@@ -1,344 +0,0 @@
1
- import { useContext, useEffect, useState } from "react";
2
- import { createContext } from "react";
3
- import axios from "axios";
4
-
5
- import { useProviderProductEdition } from "../components/pages/RetailerProductEdition/context/provider-product-edition.context";
6
-
7
- export const AiProductEdition = createContext();
8
-
9
- export const useAiProductEdition = () => {
10
- const context = useContext(AiProductEdition);
11
-
12
- if (!context) throw new Error("El contexto debe tener un provider");
13
-
14
- return context;
15
- };
16
-
17
- export const AiProductEditionProvider = ({
18
- children,
19
- isCreatorsEdition = false,
20
- user = {},
21
- token = ""
22
- }) => {
23
-
24
- const isCreators = isCreatorsEdition;
25
-
26
- const {
27
- state,
28
- } = useProviderProductEdition();
29
-
30
- const productSelected = state.product;
31
- const activeRetailer = state.active_retailer;
32
- const datasheetInputs = state.datasheets_inputs?.[1];
33
- const imagesData = state.images_values;
34
-
35
- const [product, setProduct] = useState(null);
36
-
37
- const [parsedDatasheet, setParsedDatasheet] = useState([]);
38
- const [parsedImages, setParsedImages] = useState([]);
39
-
40
- const [suggestions, setSuggestions] = useState({});
41
- const [currentSuggestion, setCurrentSuggestion] = useState({});
42
-
43
- const [isAiAvailable, setIsAiAvailable] = useState(false);
44
-
45
- const [inputsGeneratedWithAi, setInputsGeneratedWithAi] = useState({});
46
- const [inputsUsingAi, setInputsUsingAi] = useState({});
47
-
48
- const MAX_CREDITS = 10;
49
- const COOLDOWN_MS = 5 * 60 * 1000;
50
- const RATE_LIMIT_KEY = "ai_generation_limit_data";
51
-
52
- const checkAndManageRateLimit = (currentArticleId) => {
53
- const now = Date.now();
54
- const storedData = localStorage.getItem(RATE_LIMIT_KEY);
55
-
56
- let allRateData = storedData ? JSON.parse(storedData) : {};
57
-
58
- let productTimestamps = allRateData[currentArticleId] || [];
59
-
60
- productTimestamps = productTimestamps.filter(timestamp => (now - timestamp) < COOLDOWN_MS);
61
-
62
- if (productTimestamps.length >= MAX_CREDITS) {
63
-
64
- allRateData[currentArticleId] = productTimestamps;
65
- localStorage.setItem(RATE_LIMIT_KEY, JSON.stringify(allRateData));
66
-
67
- return {
68
- allowed: false,
69
- message: "Has alcanzado el limite de intentos frecuentes para este producto. Por favor, espera unos minutos."
70
- };
71
- }
72
-
73
-
74
- productTimestamps.push(now);
75
- allRateData[currentArticleId] = productTimestamps;
76
-
77
- localStorage.setItem(RATE_LIMIT_KEY, JSON.stringify(allRateData));
78
-
79
- return { allowed: true };
80
- };
81
-
82
- function setCurrentSuggestionValue({
83
- inputId,
84
- index,
85
- value
86
- }) {
87
- setCurrentSuggestion(prev => ({
88
- ...prev,
89
- [inputId]: {
90
- index,
91
- value
92
- }
93
- }));
94
- }
95
-
96
- function clearCurrentSuggestions() {
97
- setCurrentSuggestion({});
98
- }
99
-
100
- async function regenerateProductSuggestions ({
101
- inputName,
102
- currentValue,
103
- description,
104
- maxChar,
105
- type,
106
-
107
- articleId,
108
- versionId,
109
- descriptionId,
110
- attributeId
111
- }) {
112
-
113
- if(!description || !maxChar || !type) return console.log("Error: No se obtuvieron los parametros obligatorios");
114
-
115
- const newSuggestions = await generateProductSuggestions({
116
- inputName,
117
- currentValue,
118
- description,
119
- maxChar,
120
- type,
121
-
122
- articleId,
123
- versionId,
124
- descriptionId,
125
- attributeId
126
- });
127
-
128
- if(newSuggestions?.error) return {
129
- error: newSuggestions.error
130
- }
131
-
132
- if(!Array.isArray(newSuggestions) || newSuggestions.length === 0)
133
- return console.log("Error: No se obtuvieron nuevas sugerencias");
134
-
135
- if(!newSuggestions) return console.log("Error: No exiten resultados nuevos");
136
-
137
- return newSuggestions;
138
-
139
- }
140
-
141
- async function generateProductSuggestions ({
142
- inputName = "",
143
- currentValue = "",
144
- description = "",
145
- maxChar = 100,
146
- type = 'description',
147
-
148
- articleId,
149
- versionId,
150
- descriptionId,
151
- attributeId
152
- }) {
153
-
154
- try {
155
-
156
- if(!isAiAvailable) return;
157
-
158
- const rateLimitStatus = checkAndManageRateLimit(articleId);
159
-
160
- if (!rateLimitStatus.allowed) {
161
- return {
162
- error: rateLimitStatus.message,
163
- isRateLimitInfo: true
164
- };
165
- }
166
-
167
- if(!product)
168
- throw new Error("El producto no está definido");
169
-
170
- if(!Array.isArray(parsedDatasheet) || parsedDatasheet.length === 0)
171
- throw new Error("No es encontró la ficha técnica");
172
-
173
- if(!Array.isArray(parsedImages) || parsedImages.length === 0)
174
- throw new Error("No se encontraron imágenes para la cadena seleccionada");
175
-
176
- const {
177
- upc,
178
- productName,
179
- retailer,
180
- category
181
- } = product;
182
-
183
- const version = state?.product?.version;
184
-
185
- if (!upc || !description || !productName || !category || !retailer || !articleId || !version || (!descriptionId && !attributeId))
186
- throw new Error("Faltan parámetros obligatorios para generar sugerencias de IA");
187
-
188
- const payload = {
189
- upc,
190
- attributeTitle: inputName,
191
- attributeDescription: description,
192
- productName,
193
- currentValue,
194
- categoryName: category,
195
- retailerName: retailer,
196
- datasheet: parsedDatasheet,
197
- images: parsedImages,
198
- maxChar: maxChar,
199
-
200
- articleId,
201
- retailerId: activeRetailer?.id_retailer,
202
- versionId: version,
203
- descriptionId,
204
- attributeId
205
- }
206
-
207
- const { data } = await axios.post(process.env.REACT_APP_GENERATE_AI_ATTRIBUTES, payload, {
208
- headers: {
209
- Authorization: token
210
- }
211
- });
212
-
213
- const results = JSON.parse(data?.body)?.data ?? [];
214
-
215
- if(!results)
216
- throw new Error("No se encontraron resultados");
217
-
218
- return results;
219
-
220
- } catch (error) {
221
- console.log("Error generating AI suggestions:", error);
222
- return {
223
- error: error?.message ?? "Error generating AI suggestions"
224
- }
225
- }
226
-
227
- }
228
-
229
- // Verificamos si los servicios de ficha técnica e imágenes estan completos
230
- useEffect(() => {
231
-
232
- if (!productSelected) return;
233
-
234
- const {
235
- name: productName,
236
- upc: upc,
237
- categoryRetailer
238
- } = productSelected;
239
-
240
- if(!Array.isArray(categoryRetailer)) return console.log("Error: categoryRetailer no es un array");
241
-
242
- const currentCategory = categoryRetailer.find(retailer => retailer?.id_retailer === activeRetailer?.id_retailer);
243
-
244
- if(!currentCategory) return console.log("Error: No se encontro la categoría");
245
-
246
- const {
247
- retailer,
248
- category
249
- } = currentCategory;
250
-
251
- //Checamos si el servicio de ficha técnica e imagenes esta completo
252
-
253
- const currentRetailerPercentages = productSelected?.percentages?.find(retailer => retailer?.id_retailer === activeRetailer?.id_retailer);
254
-
255
- if(!currentRetailerPercentages) return console.log("Error: No hay porcentajes disponibles");
256
-
257
- const {
258
- required: datasheetRequiredPercent,
259
- } = currentRetailerPercentages?.datasheet;
260
-
261
- const {
262
- required: imagesRequiredPercent,
263
- } = currentRetailerPercentages?.images;
264
-
265
- const aiServiceAvailable = (datasheetRequiredPercent >= 100) && (imagesRequiredPercent >= 100) && [1,4,6,7].some(allowed => allowed = user?.id_role);
266
-
267
- setIsAiAvailable(aiServiceAvailable);
268
-
269
- setProduct({
270
- upc,
271
- productName,
272
- retailer,
273
- category,
274
- });
275
-
276
- }, [productSelected]);
277
-
278
- // Inicializamos la ficha técnica con el objetivo de posteriormente pasarlo a la generación con IA
279
- useEffect(() => {
280
-
281
- if (!datasheetInputs) return;
282
-
283
- const datasheetToArray = Object.values(datasheetInputs);
284
-
285
- const normalizedDatasheet = datasheetToArray.map(attribute => ({
286
- description: attribute?.description,
287
- name: attribute?.name,
288
- type: attribute?.type,
289
- value: attribute?.value
290
- }));
291
-
292
- setParsedDatasheet(normalizedDatasheet);
293
-
294
- }, [datasheetInputs]);
295
-
296
- // Inicializamos las imágenes con el objetivo de posteriormente pasarlo a la generación con IA
297
- useEffect(() => {
298
-
299
- const currentRetailerImageInputs = imagesData?.inputsByRetailer?.[0]?.filter(input => input?.id_retailer === activeRetailer?.id_retailer);
300
-
301
- if(!Array.isArray(currentRetailerImageInputs) || currentRetailerImageInputs.length === 0) return console.log('No existen imágenes para la cadena seleccionada')
302
-
303
- const allProductImages = imagesData?.values;
304
-
305
- if(!Array.isArray(allProductImages) || allProductImages.length === 0) return console.log("No existen imágenes para el producto");
306
-
307
- //Obtenemos las imágenes para el retailer seleccionado
308
- const currentParsedImages = allProductImages.filter(image => {
309
-
310
- const imageId = image?.image_id;
311
- const foundedImage = currentRetailerImageInputs.some(retailerImage => retailerImage?.id_image === imageId);
312
-
313
- return foundedImage;
314
- });
315
-
316
- setParsedImages(currentParsedImages);
317
-
318
- }, [imagesData]);
319
-
320
- return (
321
- <AiProductEdition.Provider
322
- value={{
323
- isCreators: isCreators,
324
- suggestions,
325
- currentSuggestion,
326
- isAiAvailable,
327
- inputsGeneratedWithAi,
328
- inputsUsingAi,
329
-
330
- setInputsUsingAi,
331
- setInputsGeneratedWithAi,
332
- setSuggestions,
333
- setCurrentSuggestionValue,
334
- generateProductSuggestions,
335
- regenerateProductSuggestions,
336
- clearCurrentSuggestions,
337
-
338
- }}
339
- >
340
- { children }
341
- </AiProductEdition.Provider>
342
- )
343
-
344
- }
@@ -1,103 +0,0 @@
1
- const STATUS_DICTIONARY = {
2
- // R: {
3
- // status: "R",
4
- // name: "Recepción",
5
- // weight: 1
6
- // },
7
- PA: {
8
- status: "PA",
9
- name: "Por Asignar",
10
- weight: 2
11
- },
12
- AS: {
13
- status: "AS",
14
- name: "Asignado",
15
- weight: 3
16
- },
17
- CA: {
18
- status: "CA",
19
- name: "Capturando",
20
- weight: 4
21
- },
22
- // IE: {
23
- // status: "IE",
24
- // name: "Información Enviada",
25
- // weight: 5
26
- // },
27
- RCA: {
28
- status: "RCA",
29
- name: "Rechazado Cadena",
30
- weight: 6
31
- },
32
- RP: {
33
- status: "RP",
34
- name: "Rechazado Proveedor",
35
- weight: 7
36
- },
37
- RA: {
38
- status: "RA",
39
- name: "Rechazado Auditor",
40
- weight: 8
41
- },
42
- RC: {
43
- status: "RC",
44
- name: "Rechazo Coordinador",
45
- weight: 9
46
- },
47
- AC: {
48
- status: "AC",
49
- name: "Aprobado Coordinador",
50
- weight: 10
51
- },
52
- AA: {
53
- status: "AA",
54
- name: "Aprobado Auditor",
55
- weight: 11
56
- },
57
- AP: {
58
- status: "AP",
59
- name: "Aprobado Proveedor",
60
- weight: 12
61
- },
62
- ACA: {
63
- status: "ACA",
64
- name: "Aprobado Cadena",
65
- weight: 13
66
- },
67
- Ex: {
68
- status: "Ex",
69
- name: "Exportado",
70
- weight: 14
71
- },
72
- // RAC: {
73
- // status: "RAC",
74
- // name: "Rechazo de Auditoría Content-oh!",
75
- // weight: 15
76
- // },
77
- // SAC: {
78
- // status: "SAC",
79
- // name: "Solicitud de Auditoría Content-oh!",
80
- // weight: 16
81
- // },
82
- // AAC: {
83
- // status: "AAC",
84
- // name: "Aprobado Auditoría Content-oh!",
85
- // weight: 17
86
- // },
87
- // FAP: {
88
- // status: "FAP",
89
- // name: "Finalización de Auditoría por Proveedor",
90
- // weight: 18
91
- // },
92
-
93
- //El status NS necesita ser el mayor de todos
94
- NS: {
95
- status: "NS",
96
- name: "No Solicitado",
97
- weight: 100
98
- },
99
- };
100
-
101
- module.exports = {
102
- STATUS_DICTIONARY
103
- }