| 3719 |
stevensc |
1 |
import React, { useState } from 'react';
|
|
|
2 |
import { useForm } from 'react-hook-form';
|
|
|
3 |
import { useDispatch } from 'react-redux';
|
|
|
4 |
import { Button, styled, Tab, Tabs } from '@mui/material';
|
|
|
5 |
|
|
|
6 |
import { useFetch } from '@hooks';
|
|
|
7 |
import { getTemplate } from '@services/habits/habits';
|
|
|
8 |
import { INTELLIGENCES, WEEK_DAYS } from '@constants/habits';
|
|
|
9 |
import { addNotification } from '@store/notification/notification.actions';
|
|
|
10 |
|
|
|
11 |
import Row from '@components/common/Row';
|
|
|
12 |
import Form from '@components/common/form';
|
|
|
13 |
import Input from '@components/UI/inputs/Input';
|
|
|
14 |
import Widget from '@components/UI/Widget';
|
|
|
15 |
import TabPanel from '@components/common/tab-panel';
|
|
|
16 |
import Ckeditor from '@components/common/ckeditor/Ckeditor';
|
|
|
17 |
import Select from '@components/UI/inputs/Select';
|
|
|
18 |
import CheckboxInput from '@components/UI/inputs/Checkbox';
|
|
|
19 |
import LoadingWrapper from '@components/common/loading-wrapper';
|
|
|
20 |
|
|
|
21 |
const FormTabPanel = styled(TabPanel)(({ theme }) => ({
|
|
|
22 |
display: 'flex',
|
|
|
23 |
flexDirection: 'column',
|
|
|
24 |
width: '100%',
|
|
|
25 |
gap: theme.spacing(0.5)
|
|
|
26 |
}));
|
|
|
27 |
|
|
|
28 |
export default function HabitForm({
|
|
|
29 |
onSubmit = () => {},
|
|
|
30 |
defaultValues = {
|
|
|
31 |
name: '',
|
|
|
32 |
description: '',
|
|
|
33 |
monday_active: false,
|
|
|
34 |
tuesday_active: false,
|
|
|
35 |
wednesday_active: false,
|
|
|
36 |
thursday_active: false,
|
|
|
37 |
friday_active: false,
|
|
|
38 |
saturday_active: false,
|
|
|
39 |
sunday_active: false,
|
|
|
40 |
monday_time: undefined,
|
|
|
41 |
tuesday_time: undefined,
|
|
|
42 |
wednesday_time: undefined,
|
|
|
43 |
thursday_time: undefined,
|
|
|
44 |
friday_time: undefined,
|
|
|
45 |
saturday_time: undefined,
|
|
|
46 |
sunday_time: undefined,
|
|
|
47 |
quantitative_value: false,
|
|
|
48 |
qualitative_description: '',
|
|
|
49 |
notification_10min_before: false,
|
|
|
50 |
notification_30min_before: false,
|
|
|
51 |
intelligence: ''
|
|
|
52 |
},
|
|
|
53 |
values = {}
|
|
|
54 |
}) {
|
|
|
55 |
const { data: templates } = useFetch('/helpers/habits-and-skills', []);
|
|
|
56 |
const [currentTemplate, setCurrentTemplate] = useState(null);
|
|
|
57 |
const [currentTab, setCurrentTab] = useState(0);
|
|
|
58 |
const dispatch = useDispatch();
|
|
|
59 |
|
|
|
60 |
const {
|
|
|
61 |
handleSubmit,
|
|
|
62 |
control,
|
|
|
63 |
formState: { errors, isSubmitting },
|
|
|
64 |
trigger
|
|
|
65 |
} = useForm({
|
|
|
66 |
defaultValues,
|
|
|
67 |
values: currentTemplate ?? values
|
|
|
68 |
});
|
|
|
69 |
|
|
|
70 |
const getHabitTemplate = async (url) => {
|
|
|
71 |
try {
|
|
|
72 |
const response = await getTemplate(url);
|
|
|
73 |
setCurrentTemplate(response);
|
|
|
74 |
} catch (error) {
|
|
|
75 |
dispatch(addNotification({ style: 'danger', msg: error.message }));
|
|
|
76 |
}
|
|
|
77 |
};
|
|
|
78 |
|
|
|
79 |
const handleChange = async (event, newValue) => {
|
|
|
80 |
const valid = await trigger();
|
|
|
81 |
if (valid) setCurrentTab(newValue);
|
|
|
82 |
};
|
|
|
83 |
|
|
|
84 |
const nextStep = async () => {
|
|
|
85 |
const valid = await trigger();
|
|
|
86 |
if (valid) setCurrentTab(currentTab + 1);
|
|
|
87 |
};
|
|
|
88 |
|
|
|
89 |
const formatHabit = (habit) => {
|
|
|
90 |
const dataArray = Object.entries(habit);
|
|
|
91 |
const formatedData = dataArray.map(([key, value]) => {
|
|
|
92 |
if (key.includes('active')) return [key, value ? 1 : 0];
|
|
|
93 |
if (key.includes('time')) return [key, value.padEnd(8, ':00')];
|
|
|
94 |
return [key, value];
|
|
|
95 |
});
|
|
|
96 |
return Object.fromEntries(formatedData);
|
|
|
97 |
};
|
|
|
98 |
|
|
|
99 |
const dataAdapter = (habit) => {
|
|
|
100 |
const formatedHabit = formatHabit(habit);
|
|
|
101 |
onSubmit(formatedHabit);
|
|
|
102 |
};
|
|
|
103 |
|
|
|
104 |
return (
|
|
|
105 |
<Widget>
|
|
|
106 |
<Tabs value={currentTab} onChange={handleChange}>
|
|
|
107 |
<Tab label='Detalles' />
|
|
|
108 |
<Tab label='Frecuencia' />
|
|
|
109 |
<Tab label='Valor' />
|
|
|
110 |
<Tab label='Notificaciones' />
|
|
|
111 |
</Tabs>
|
|
|
112 |
<Widget.Body>
|
|
|
113 |
<Form onSubmit={handleSubmit(dataAdapter)}>
|
|
|
114 |
<LoadingWrapper loading={isSubmitting} displayChildren>
|
|
|
115 |
{/* Detalles */}
|
|
|
116 |
<FormTabPanel value={0} index={currentTab}>
|
|
|
117 |
<Select
|
|
|
118 |
label='Plantilla:'
|
|
|
119 |
options={templates.map((template) => ({
|
|
|
120 |
label: template.name,
|
|
|
121 |
value: template.link
|
|
|
122 |
}))}
|
|
|
123 |
onChange={(e) => getHabitTemplate(e.target.value)}
|
|
|
124 |
/>
|
|
|
125 |
|
|
|
126 |
<Input
|
|
|
127 |
label='Nombre del hábito o competencia:'
|
|
|
128 |
name='name'
|
|
|
129 |
placeholder='Escribe el nombre del hábito o competencia'
|
|
|
130 |
control={control}
|
|
|
131 |
rules={{ required: 'El nombre es requerido' }}
|
|
|
132 |
error={errors.name?.message}
|
|
|
133 |
/>
|
|
|
134 |
|
|
|
135 |
<Select
|
|
|
136 |
label='Inteligencias:'
|
|
|
137 |
name='intelligence'
|
|
|
138 |
options={INTELLIGENCES}
|
|
|
139 |
control={control}
|
|
|
140 |
rules={{ required: 'Este campo es requerido' }}
|
|
|
141 |
error={errors.intelligence?.message}
|
|
|
142 |
/>
|
|
|
143 |
|
|
|
144 |
<Ckeditor
|
|
|
145 |
control={control}
|
|
|
146 |
name='description'
|
|
|
147 |
error={errors.description?.message}
|
|
|
148 |
rules={{ required: 'La descripción es requerida' }}
|
|
|
149 |
label='Descripción:'
|
|
|
150 |
/>
|
|
|
151 |
|
|
|
152 |
<Button color='primary' onClick={nextStep}>
|
|
|
153 |
Continuar
|
|
|
154 |
</Button>
|
|
|
155 |
</FormTabPanel>
|
|
|
156 |
|
|
|
157 |
{/* Frecuencia */}
|
|
|
158 |
<FormTabPanel value={1} index={currentTab}>
|
|
|
159 |
{WEEK_DAYS.map(({ label, value, time }) => {
|
|
|
160 |
return (
|
|
|
161 |
<Row
|
|
|
162 |
key={value}
|
|
|
163 |
styles={{
|
|
|
164 |
flexFlow: 'nowrap',
|
|
|
165 |
justifyContent: 'space-between'
|
|
|
166 |
}}
|
|
|
167 |
>
|
|
|
168 |
{/* Campos de días activos */}
|
|
|
169 |
<CheckboxInput label={label} control={control} name={value} />
|
|
|
170 |
{/* Puedes repetir los campos de días activos y sus horas para cada día de la semana */}
|
|
|
171 |
<Input
|
|
|
172 |
type='time'
|
|
|
173 |
control={control}
|
|
|
174 |
name={time}
|
|
|
175 |
rules={{
|
|
|
176 |
validate: (time, formValues) => {
|
|
|
177 |
if (!formValues[value]) return true;
|
|
|
178 |
if (formValues[value] && time) return true;
|
|
|
179 |
return 'La hora es requerida si el día está activo';
|
|
|
180 |
}
|
|
|
181 |
}}
|
|
|
182 |
style={{ width: 'auto' }}
|
|
|
183 |
error={errors[time]?.message}
|
|
|
184 |
/>
|
|
|
185 |
</Row>
|
|
|
186 |
);
|
|
|
187 |
})}
|
|
|
188 |
|
|
|
189 |
<Button color='primary' onClick={nextStep}>
|
|
|
190 |
Continuar
|
|
|
191 |
</Button>
|
|
|
192 |
</FormTabPanel>
|
|
|
193 |
|
|
|
194 |
{/* Valor */}
|
|
|
195 |
<FormTabPanel value={2} index={currentTab}>
|
|
|
196 |
<Input
|
|
|
197 |
control={control}
|
|
|
198 |
label='Valor cuantitativo:'
|
|
|
199 |
name='quantitative_value'
|
|
|
200 |
type='number'
|
|
|
201 |
rules={{ required: 'El valor es requerido' }}
|
|
|
202 |
error={errors.quantitative_value?.message}
|
|
|
203 |
/>
|
|
|
204 |
|
|
|
205 |
<Ckeditor
|
|
|
206 |
control={control}
|
|
|
207 |
name='qualitative_description'
|
|
|
208 |
error={errors.qualitative_description?.message}
|
|
|
209 |
rules={{ required: 'La descripción es requerida' }}
|
|
|
210 |
label='Descripción cualitativa:'
|
|
|
211 |
/>
|
|
|
212 |
|
|
|
213 |
<Button color='primary' onClick={nextStep}>
|
|
|
214 |
Continuar
|
|
|
215 |
</Button>
|
|
|
216 |
</FormTabPanel>
|
|
|
217 |
|
|
|
218 |
{/* Notificaciones */}
|
|
|
219 |
<FormTabPanel value={3} index={currentTab}>
|
|
|
220 |
<CheckboxInput
|
|
|
221 |
label='Notificación 10 min antes'
|
|
|
222 |
name='notification_10min_before'
|
|
|
223 |
control={control}
|
|
|
224 |
/>
|
|
|
225 |
<CheckboxInput
|
|
|
226 |
label='Notificación 30 min antes'
|
|
|
227 |
name='notification_30min_before'
|
|
|
228 |
control={control}
|
|
|
229 |
rules={{
|
|
|
230 |
validate: (value, formValues) => {
|
|
|
231 |
if (!value && !formValues.notification_10min_before) {
|
|
|
232 |
return 'Debe seleccionar al menos una opción';
|
|
|
233 |
}
|
|
|
234 |
if (value && formValues.notification_10min_before) {
|
|
|
235 |
return 'No se puede seleccionar ambas opciones simultáneamente';
|
|
|
236 |
}
|
|
|
237 |
return true;
|
|
|
238 |
}
|
|
|
239 |
}}
|
|
|
240 |
/>
|
|
|
241 |
<Button color='primary' type='submit' disabled={isSubmitting}>
|
|
|
242 |
Crear
|
|
|
243 |
</Button>
|
|
|
244 |
</FormTabPanel>
|
|
|
245 |
</LoadingWrapper>
|
|
|
246 |
</Form>
|
|
|
247 |
</Widget.Body>
|
|
|
248 |
</Widget>
|
|
|
249 |
);
|
|
|
250 |
}
|