contentoh-components-library 21.4.92 → 21.4.94

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.
@@ -10,27 +10,26 @@ import { TextField } from "@mui/material/TextField";
10
10
  import { GroupSelect } from "../../molecules/GroupSelect";
11
11
  import { CustomChip } from "../../atoms/CustomChip";
12
12
  import { CustomSelect } from "../../molecules/CustomSelect";
13
+ import { ButtonV2 } from "../../atoms/ButtonV2";
13
14
 
14
15
  //svg
15
16
  import options from "../../../assets/images/Icons/options.svg";
16
17
  import add from "../../../assets/images/Icons/addv2.svg";
17
18
 
18
19
  export const Phase = ({
20
+ key,
19
21
  id,
22
+ phaseId,
20
23
  phases,
21
24
  phaseName,
22
25
  nextPhase,
23
26
  groups,
24
27
  onDeletePhase,
25
- onDragStart,
26
- onDragOver,
27
- onDragEnd,
28
- token
28
+ token,
29
29
  }) => {
30
- const [selectedValue, setSelectedValue] = useState("");
30
+ const [selectedValue, setSelectedValue] = useState([]);
31
31
  const [chips, setChips] = useState([]);
32
32
  const [groupsSelected, setGroupsSelected] = useState([]);
33
- const [showCustomSelect, setShowCustomSelect] = useState(false);
34
33
  const [anchorEl, setAnchorEl] = React.useState(null);
35
34
  const [nextPhaseState, setNextPhaseState] = useState("");
36
35
  const open = Boolean(anchorEl);
@@ -41,88 +40,190 @@ export const Phase = ({
41
40
  icon: "success",
42
41
  });
43
42
 
44
- const idPhase = id + 1;
45
- const [tempItems, setTempItems] = useState([]);
43
+ const ITEM_HEIGHT = 48;
44
+ const ITEM_PADDING_TOP = 8;
45
+ const MenuProps = {
46
+ PaperProps: {
47
+ style: {
48
+ maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
49
+ width: 250,
50
+ },
51
+ },
52
+ };
46
53
 
47
- useEffect(() => {
54
+ const loadData = async() => {
48
55
  const activeGroups = groups.filter((group) => group.groupActive === 1);
49
56
  const initialChips = activeGroups.map((group) => ({
50
57
  id: group.groupId,
51
58
  label: group.groupName,
52
59
  }));
53
-
54
60
  setChips(initialChips);
55
- }, [groups]);
56
61
 
57
- useEffect(() => {
58
62
  const nextPhaseObject = phases.find((phase) => phase.phaseId === nextPhase);
59
63
  if (nextPhaseObject) {
60
64
  setNextPhaseState(nextPhaseObject.phaseName);
61
- } else {
62
- console.log("Aún no se asigna siguiente fase");
63
65
  }
66
+ };
67
+
68
+ useEffect(() => {
69
+ loadData();
70
+ }, [groups]);
71
+
72
+ useEffect(() => {
73
+ loadData();
64
74
  }, [nextPhase, phases]);
65
75
 
66
- const onAdd = async (idPhase) => {
76
+ useEffect(() => {
77
+ handleGroupSelect();
78
+ }, [groupsSelected]);
79
+
80
+
81
+ useEffect(() => {
82
+ handleNextPhaseSelect();
83
+ }, [selectedValue]);
84
+
85
+ //agregar fase
86
+ const onAdd = async (phaseId) => {
67
87
  if (selectedValue && !groupsSelected.includes(selectedValue)) {
68
88
  const updatedGroups = groups.map((group) =>
69
- group.groupName === selectedValue
70
- ? { ...group, groupActive: 1 }
71
- : group
89
+ group.groupName === selectedValue ? { ...group, groupActive: 1 } : group
72
90
  );
73
-
74
- setGroups(updatedGroups);
75
-
91
+
76
92
  // Actualizar el estado de chips y groupsSelected
77
93
  setChips((prevChips) => [
78
94
  ...prevChips,
79
- { id: idPhase, label: selectedValue },
95
+ { id: phaseId, label: selectedValue },
80
96
  ]);
81
-
97
+
82
98
  setGroupsSelected((prevGroups) => [...prevGroups, selectedValue]);
83
99
  setSelectedValue("");
84
-
85
- console.log("update",updatedGroups)
86
- await addGroup(idPhase, updatedGroups);
100
+
101
+ console.log("update", updatedGroups);
102
+ loadData();
87
103
  }
88
104
  };
89
-
90
105
 
91
- const addGroup = async(phaseId, groups) => {
106
+ //agregar grupo a fase
107
+ const addGroup = async (phaseId, groups) => {
92
108
  try {
93
- console.log("fase y grupos",{phaseId, groups});
94
109
  const response = await axios.post(
95
110
  `${process.env.REACT_APP_PHASES_ENDPOINT}/update`,
96
111
  {
97
- retailerGroupsIds: {
98
- groups
112
+ retailerGroupsIds: groups,
113
+ phaseId,
114
+ },
115
+ {
116
+ headers: {
117
+ Authorization: token,
99
118
  },
100
- phaseId
119
+ }
120
+ );
121
+ console.log("response", response.data.body)
122
+ console.log("grupo agregado correctamente");
123
+ loadData();
124
+ } catch (error) {
125
+ console.error("Error al agregar grupo a fase:", error);
126
+ }
127
+ };
128
+
129
+ //actualiza siguiente fase
130
+ const updateNextPhase = async (phaseId, newNextPhase) => {
131
+ try {
132
+ console.log("fase y grupos", { phaseId, newNextPhase });
133
+ const response = await axios.post(
134
+ `${process.env.REACT_APP_PHASES_ENDPOINT}/update`,
135
+ {
136
+ nextPhaseId: newNextPhase,
137
+ phaseId,
101
138
  },
102
139
  {
103
140
  headers: {
104
141
  Authorization: token,
105
142
  },
106
143
  }
107
- )
108
- console.log("grupo eliminado correctamente")
144
+ );
145
+ console.log("response", response.data.body);
146
+ console.log("grupo agregado correctamente");
109
147
  } catch (error) {
110
- console.error("Error al eliminar grupo de fase:", error);
111
- }
112
- }
148
+ console.error("Error al actualizar grupo de fase:", error);
149
+ }
150
+ };
113
151
 
114
- const handleGroupSelect = (selectedGroup) => {
115
- if (!chips.find((chip) => chip.label === selectedGroup)) {
116
- setChips((prevChips) => [
117
- ...prevChips,
118
- { id: prevChips.length, label: selectedGroup },
119
- ]);
152
+ const handleGroupSelect = () => {
153
+ groupsSelected.forEach((groupId) => {
154
+ const matchingGroup = groups.find((group) => group.groupId === groupId);
155
+ if (matchingGroup) {
156
+ if (!chips.find((chip) => chip.key === matchingGroup.groupId)) {
157
+ setChips((prevChips) => [
158
+ ...prevChips,
159
+ { id: matchingGroup.groupId,
160
+ label: matchingGroup.groupName },
161
+ ]);
162
+ }
163
+ addGroup(phaseId,groupsSelected)
164
+ }
165
+ });
166
+ };
167
+
168
+
169
+ const handleNextPhaseSelect = () => {
170
+ if (selectedValue.length > 0) {
171
+ const Id = selectedValue[0];
172
+ console.log("phaseId",Id)
173
+ const matchingPhase = phases.find((phase) => phase.phaseId === Id);
174
+ console.log("matchingPhase",matchingPhase)
175
+ if (matchingPhase) {
176
+ checkAvailablePhase(phaseId, matchingPhase.phaseId);
177
+ }
120
178
  }
121
- console.log("Se agrego el grupo", selectedGroup);
122
- setSelectedValue(selectedGroup);
123
179
  };
124
180
 
125
- const handleChipDelete = (phaseId,chipToRemove) => {
181
+
182
+ //checa si llega una fase que se tiene en otro lado
183
+ const checkAvailablePhase = (phaseId, newNextPhase) => {
184
+ const isNextPhaseUsed = phases.some(phase => phase.nextPhaseIfApproved === newNextPhase);
185
+
186
+ if (isNextPhaseUsed) {
187
+ setModalData({
188
+ show: true,
189
+ className: "modal-next-phase",
190
+ message: `La fase ${newNextPhase} ya está siendo utilizada como siguiente fase en otra fase.`,
191
+ icon: "info",
192
+ customComponent: (
193
+ <div className="container-input-name">
194
+ <p>La fase anterior se borrará</p>
195
+ <p>¿Estás seguro?</p>
196
+ </div>
197
+ ),
198
+ buttons: [
199
+ <ButtonV2
200
+ key="btn-Cancelar"
201
+ type="white"
202
+ label="Cancelar"
203
+ size={12}
204
+ onClick={() => {
205
+ setModalData((prev) => ({ ...prev, show: false }))
206
+ }}
207
+ />,
208
+ <ButtonV2
209
+ key="btn-Aceptar"
210
+ type="pink"
211
+ label="Aceptar"
212
+ size={12}
213
+ onClick={() => {
214
+ setModalData((prev) => ({ ...prev, show: false }));
215
+ }}
216
+ />,
217
+ ],
218
+ })
219
+ } else {
220
+ // Si la fase no está siendo utilizada, se actualizar la siguiente fase
221
+ updateNextPhase(phaseId, newNextPhase);
222
+ }
223
+ };
224
+
225
+ //eliminar chip
226
+ const handleChipDelete = (phaseId, chipToRemove) => {
126
227
  setGroupsSelected((prevGroups) =>
127
228
  prevGroups.filter((chip) => chip.id !== chipToRemove.id)
128
229
  );
@@ -133,16 +234,17 @@ export const Phase = ({
133
234
  deleteGroup(phaseId, chipToRemove.id);
134
235
  };
135
236
 
136
- const deleteGroup = async(phaseId, groupId) => {
237
+ //eliminar grupo de fase
238
+ const deleteGroup = async (phaseId, groupId) => {
137
239
  try {
138
- console.log("grupo de fase",{phaseId, groupId});
240
+ console.log("grupo de fase", { phaseId, groupId });
139
241
  const response = await axios.post(
140
242
  `${process.env.REACT_APP_PHASES_ENDPOINT}/delete`,
141
243
  {
142
- deleteGroupOfPhase: {
143
- phaseId,
144
- groupId
145
- }
244
+ deleteGroupOfPhase: {
245
+ phaseId,
246
+ groupId,
247
+ },
146
248
  },
147
249
  {
148
250
  headers: {
@@ -151,11 +253,11 @@ export const Phase = ({
151
253
  },
152
254
  }
153
255
  );
154
- console.log("grupo eliminado correctamente")
256
+ console.log("grupo eliminado correctamente");
155
257
  } catch (error) {
156
258
  console.error("Error al eliminar grupo de fase:", error);
157
- }
158
- }
259
+ }
260
+ };
159
261
 
160
262
  const handleClick = (event) => {
161
263
  setAnchorEl(event.currentTarget);
@@ -165,89 +267,90 @@ export const Phase = ({
165
267
  };
166
268
 
167
269
  return (
168
- <Container
169
- onDragStart={onDragStart}
170
- onDragOver={onDragOver}
171
- onDragEnd={onDragEnd}
172
- draggable
173
- >
174
- <div key={idPhase} className="header-phase">
270
+ <Container>
271
+ <div key={key} className="header-phase">
175
272
  <h2>
176
- Fase {idPhase} - {phaseName}
273
+ Fase {phaseId} - {phaseName}
177
274
  </h2>
178
275
  <div className="text-button-container">
179
- <div className="phase-sel">
180
- <p className="text-phase">Siguiente Fase </p>
181
- <Select
182
- value={selectedValue !== "" ? selectedValue : nextPhaseState}
183
- placeholder={`Fase`}
184
- onChange={(e) => {
185
- const selectedPhase = phases.find(
186
- (phase) => phase.phaseName === e.target.value
187
- );
188
- setSelectedValue(selectedPhase.nextPhaseIfApproved);
189
- }}
190
- sx={{
191
- minWidth: "100px",
192
- height: "24px",
193
- background: "#F7F7FC",
194
- borderRadius: "5px",
195
- fontSize:"12px",
196
- }}
197
- MenuProps={{
198
- PaperProps: {
199
- style: {
200
- background: "#F7F7FC",
201
- },
202
- },
203
- }}
204
- >
205
- {phases.map((phase) => (
206
- <MenuItem
207
- key={phase.phaseId}
208
- value={phase.phaseName}
209
- sx={{
210
- fontSize: "12px",
211
- color: "#262626",
212
- minHeight: "auto",
213
- }}
214
- >
215
- {phase.phaseName}
216
- </MenuItem>
217
- ))}
218
- </Select>
219
- <Button
220
- id="basic-button"
221
- aria-controls={open ? "basic-menu" : undefined}
222
- aria-haspopup="true"
223
- aria-expanded={open ? "true" : undefined}
224
- onClick={(e) => handleClick(e)}
225
- >
226
- <img src={options} alt="" />
227
- </Button>
228
- <Menu
229
- id="basic-menu"
230
- anchorEl={anchorEl}
231
- open={open}
232
- onClose={handleClose}
233
- MenuListProps={{
234
- "aria-labelledby": "basic-button",
235
- }}
236
- sx={{
237
- ul: {
238
- paddingTop: "0px",
239
- paddingBottom: "0px",
276
+ <div className="phase-sel">
277
+ <p className="text-phase">Siguiente Fase </p>
278
+ <Select
279
+ value={
280
+ selectedValue.length > 0
281
+ ? selectedValue[0]
282
+ : nextPhaseState
283
+ ? nextPhaseState
284
+ : ""
285
+ }
286
+ placeholder={`Fase`}
287
+ onChange={(e) => {
288
+ const selectedPhase = phases.find(
289
+ (phase) => phase.phaseName === e.target.value
290
+ );
291
+ setSelectedValue(selectedPhase ? [selectedPhase.phaseId] : []);
292
+ }}
293
+ sx={{
294
+ minWidth: "100px",
295
+ height: "24px",
296
+ background: "#F7F7FC",
297
+ borderRadius: "5px",
298
+ fontSize: "12px",
299
+ }}
300
+ MenuProps={{
301
+ PaperProps: {
302
+ style: {
303
+ background: "#F7F7FC",
240
304
  },
241
- }}
242
- >
305
+ },
306
+ }}
307
+ >
308
+ {phases.map((phase) => (
243
309
  <MenuItem
244
- onClick={() => onDeletePhase(id)}
245
- sx={{ fontSize: "12px", color: "#262626", minHeight: "auto" }}
310
+ key={phase.phaseId}
311
+ value={phase.phaseName}
312
+ sx={{
313
+ fontSize: "12px",
314
+ color: "#262626",
315
+ minHeight: "auto",
316
+ }}
246
317
  >
247
- Eliminar Fase
318
+ {phase.phaseName}
248
319
  </MenuItem>
249
- </Menu>
250
- </div>
320
+ ))}
321
+ </Select>
322
+ <Button
323
+ id="basic-button"
324
+ aria-controls={open ? "basic-menu" : undefined}
325
+ aria-haspopup="true"
326
+ aria-expanded={open ? "true" : undefined}
327
+ onClick={(e) => handleClick(e)}
328
+ >
329
+ <img src={options} alt="" />
330
+ </Button>
331
+ <Menu
332
+ id="basic-menu"
333
+ anchorEl={anchorEl}
334
+ open={open}
335
+ onClose={handleClose}
336
+ MenuListProps={{
337
+ "aria-labelledby": "basic-button",
338
+ }}
339
+ sx={{
340
+ ul: {
341
+ paddingTop: "0px",
342
+ paddingBottom: "0px",
343
+ },
344
+ }}
345
+ >
346
+ <MenuItem
347
+ onClick={() => onDeletePhase(id)}
348
+ sx={{ fontSize: "12px", color: "#262626", minHeight: "auto" }}
349
+ >
350
+ Eliminar Fase
351
+ </MenuItem>
352
+ </Menu>
353
+ </div>
251
354
  </div>
252
355
  </div>
253
356
  <div className="attributes-container">
@@ -255,14 +358,15 @@ export const Phase = ({
255
358
  <CustomChip
256
359
  key={chip.id}
257
360
  label={chip.label}
258
- onDelete={() => handleChipDelete(idPhase,chip)}
361
+ onDelete={() => handleChipDelete(phaseId, chip)}
259
362
  />
260
363
  ))}
261
- {/*<GroupSelect
364
+
365
+ <GroupSelect
262
366
  options={groups
263
367
  .filter((group) => group.groupActive === 0)
264
- .map((group, index) => ({
265
- id: index,
368
+ .map((group) => ({
369
+ id: group.groupId,
266
370
  name: group.groupName,
267
371
  }))}
268
372
  showSearchBar
@@ -273,25 +377,9 @@ export const Phase = ({
273
377
  defaultOption={"Todos los grupos"}
274
378
  parameterArray={groupsSelected}
275
379
  setParameterArray={setGroupsSelected}
276
- onSelect={handleGroupSelect}
277
- onClickItem={()=>onAdd(idPhase)}
278
- />*/}
279
-
280
- {/* <CustomSelect
281
- options={groups
282
- .filter((group) => group.groupActive === 0)
283
- .map((group, index) => ({
284
- id: index,
285
- name: group.groupName,
286
- }))}
287
- showSearchBar
288
- icon={add}
289
- placeHolder={"Buscar grupo"}
290
- customSelectId={"group-select"}
291
- defaultOption={"Todos los grupos"}
292
- parameterArray={groupsSelected}
293
- setParameterArray={setGroupsSelected}
294
- />*/}
380
+ onClickItem={()=>{
381
+ handleGroupSelect()}}
382
+ />
295
383
  </div>
296
384
  <Modal
297
385
  {...modalData}
@@ -64,6 +64,12 @@ export const Container = styled.div`
64
64
  cursor: pointer;
65
65
  }
66
66
  }
67
+ .modal-next-phase .contentModal {
68
+ max-width: 250px;
69
+ .container-input-name p{
70
+ text-align:center;
71
+ }
72
+ }
67
73
  `;
68
74
 
69
75
  export const ContainerIcon = styled.div`
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect } from "react";
1
+ import React, { useState, useEffect, useRef } from "react";
2
2
  import { Container, Header } from "./styles";
3
3
  import { Phase } from "../../molecules/Phase";
4
4
  import { ButtonV2 } from "../../atoms/ButtonV2";
@@ -11,6 +11,7 @@ export const DragAndDropPhases = ({ token}) => {
11
11
  const [draggedItem, setDraggedItem] = useState(null);
12
12
  const [listPhases, setListPhases]= useState([]);
13
13
  const [tempListPhases, setTempListPhases] = useState([]);
14
+ const [newPhaseName, setNewPhaseName] = useState("");
14
15
  const [inputValue, setInputValue] = useState("");
15
16
  const [modalData, setModalData] = useState({
16
17
  show: false,
@@ -21,8 +22,14 @@ export const DragAndDropPhases = ({ token}) => {
21
22
 
22
23
  useEffect(() => loadData(),[]);
23
24
 
25
+ const newPhaseNameRef = useRef("");
26
+
27
+ useEffect(() => {
28
+ newPhaseNameRef.current = newPhaseName;
29
+ }, [newPhaseName]);
30
+
24
31
  useEffect(() => {
25
- console.log(inputValue)
32
+ setNewPhaseName((prev) => prev + inputValue);
26
33
  }, [inputValue]);
27
34
 
28
35
  const onDragStart = (e, id) => {
@@ -50,10 +57,6 @@ export const DragAndDropPhases = ({ token}) => {
50
57
  setDraggedItem(null);
51
58
  };
52
59
 
53
- // useEffect(() => {console.log("nuevo",newPhaseName)},[newPhaseName]);
54
-
55
-
56
-
57
60
  const updatePhases = async () => {
58
61
  try {
59
62
  console.log("listPhases:", listPhases);
@@ -85,16 +88,11 @@ export const DragAndDropPhases = ({ token}) => {
85
88
  }
86
89
  };
87
90
 
88
-
89
- const handleInputChange = (value) => {
90
- setInputValue((prevInputValue) => {
91
- const newValue = prevInputValue + value;
92
- console.log("currentInputValue", newValue);
93
- return newValue;
94
- });
91
+ const handleInputChange = (e) => {
92
+ setInputValue(e.target.value);
95
93
  };
96
94
 
97
- const AddPhase = async(phaseName) => {
95
+ const addPhase = async(phaseName) => {
98
96
  console.log("fase nueva", phaseName);
99
97
  try {
100
98
  const body = {
@@ -111,9 +109,11 @@ export const DragAndDropPhases = ({ token}) => {
111
109
  },
112
110
  }
113
111
  );
112
+ console.log("body", body)
114
113
  const createdPhase = response.data.body;
115
114
  console.log(createdPhase)
116
115
  setInputValue("");
116
+ loadData();
117
117
  } catch (error) {
118
118
  console.error("Error al agregar fase:", error);
119
119
  }
@@ -163,27 +163,29 @@ export const DragAndDropPhases = ({ token}) => {
163
163
  size={12}
164
164
  onClick={() => {
165
165
  setModalData((prev) => ({ ...prev, show: false }));
166
- setInputValue((prevInputValue) => {
167
- AddPhase(prevInputValue);
168
- return prevInputValue;
169
- });
166
+ handleSavePhase();
170
167
  }}
171
168
  />
172
169
  ],
173
170
  customComponent: (
174
171
  <div className="container-input-name">
175
172
  <p>Las fases nuevas siempre se agregan al final.<br/>Puedes ordenar las fases arrastrándolas.</p>
176
- <input
173
+ <input
177
174
  className={`input-phases`}
178
175
  placeholder="Nombre de fase"
179
176
  value={inputValue}
180
- onChange={(e)=>handleInputChange(e.target.value)}
177
+ onChange={(e) => handleInputChange(e)}
181
178
  />
182
179
  </div>
183
180
  ),
184
181
  });
185
182
  };
186
183
 
184
+ const handleSavePhase = () => {
185
+ addPhase(newPhaseNameRef.current);
186
+ setInputValue("");
187
+ };
188
+
187
189
  const loadData = async () => {
188
190
  try {
189
191
  const response = await axios.post(
@@ -258,16 +260,17 @@ const handleDeletePhase = (id) => {
258
260
  const renderPhase = (phase, idx) => {
259
261
  return (
260
262
  <Phase
261
- key={idx}
263
+ key={phase.phaseId}
262
264
  id={idx}
265
+ phaseId={phase.phaseId}
263
266
  phases={listPhases}
264
267
  phaseName={phase.phaseName}
265
268
  nextPhase={phase.nextPhaseIfApproved}
266
269
  groups={phase.groupsAssigned}
267
270
  onDeletePhase={() => handleDeletePhase(phase.phaseId)}
268
- onDragStart={(e) => onDragStart(e, idx)}
269
- onDragOver={() => onDragOver(idx)}
270
- onDragEnd={onDragEnd}
271
+ // onDragStart={(e) => onDragStart(e, idx)}
272
+ // onDragOver={() => onDragOver(idx)}
273
+ // onDragEnd={onDragEnd}
271
274
  token={token}
272
275
  />
273
276
  );
@@ -309,9 +312,13 @@ const renderPhase = (phase, idx) => {
309
312
  }}
310
313
  ></ButtonV2>
311
314
  </Header>
312
- <ul>
313
- {listPhases.map((phase, idx) => renderPhase(phase, idx))}
314
- </ul>
315
+ {listPhases.length > 0 ? (
316
+ <ul>{listPhases.map((phase, idx) => renderPhase(phase, idx))}</ul>
317
+ ) : (
318
+ <div className="no-phases-container">
319
+ <p>Parece que aun no tienes fases disponibles.</p>
320
+ </div>
321
+ )}
315
322
  <Modal
316
323
  {...modalData}
317
324
  onClickBtnDefault={() =>
@@ -58,6 +58,17 @@ ul{
58
58
  justify-content: flex-end;
59
59
  }
60
60
  }
61
+ .no-phases-container {
62
+ display: flex;
63
+ flex-direction:column;
64
+ gap:10px;
65
+ align-items: center;
66
+ border-radius:10px;
67
+ border:1px solid ${GlobalColors.gray_light};
68
+ padding:10px 15px;
69
+ font-family:${FontFamily.Roboto}, sans-serif;
70
+ font-size:12px;
71
+ }
61
72
  `;
62
73
 
63
74
  export const Header = styled.div`