@@ -8,15 +8,96 @@ import {
8
8
} from '@ignite-ui/react'
9
9
import { Container , Header } from '../styles'
10
10
import {
11
+ FormError ,
11
12
IntervalBox ,
12
13
IntervalDay ,
13
14
IntervalInputs ,
14
15
IntervalItem ,
15
16
IntervalsContainer ,
16
17
} from './styles'
17
18
import { ArrowRight } from 'phosphor-react'
19
+ import { Controller , useFieldArray , useForm } from 'react-hook-form'
20
+ import { z } from 'zod'
21
+ import { getWeekDays } from '@/utils/get-week-days'
22
+ import { zodResolver } from '@hookform/resolvers/zod'
23
+ import { convertTimeStringToMinutes } from '@/utils/convert-time-in-minutes'
24
+
25
+ const timeIntervalsFormSchema = z . object ( {
26
+ intervals : z
27
+ . array (
28
+ z . object ( {
29
+ weekDay : z . number ( ) . min ( 0 ) . max ( 6 ) ,
30
+ enabled : z . boolean ( ) ,
31
+ startTime : z . string ( ) ,
32
+ endTime : z . string ( ) ,
33
+ } ) ,
34
+ )
35
+ . length ( 7 )
36
+ . transform ( ( intervals ) => intervals . filter ( ( interval ) => interval . enabled ) )
37
+ . refine ( ( intervals ) => intervals . length > 0 , {
38
+ message : 'Você precisa selecionar pelo menos um dia da semana!' ,
39
+ } )
40
+ . transform ( ( intervals ) => {
41
+ return intervals . map ( ( interval ) => {
42
+ return {
43
+ weekDay : interval . weekDay ,
44
+ startTimeInMinutes : convertTimeStringToMinutes ( interval . startTime ) ,
45
+ endTimeInMinutes : convertTimeStringToMinutes ( interval . endTime ) ,
46
+ }
47
+ } )
48
+ } )
49
+ . refine (
50
+ ( intervals ) => {
51
+ return intervals . every (
52
+ ( interval ) =>
53
+ interval . endTimeInMinutes - 60 >= interval . startTimeInMinutes ,
54
+ )
55
+ } ,
56
+ {
57
+ message :
58
+ 'O horário de término deve ser pelo menos 1h distante do início.' ,
59
+ } ,
60
+ ) ,
61
+ } )
62
+
63
+ type TimeIntervalsFormInput = z . input < typeof timeIntervalsFormSchema >
64
+ type TimeIntervalsFormOutput = z . output < typeof timeIntervalsFormSchema >
18
65
19
66
export default function TimeIntervals ( ) {
67
+ const {
68
+ register,
69
+ handleSubmit,
70
+ control,
71
+ watch,
72
+ formState : { isSubmitting, errors } ,
73
+ } = useForm < TimeIntervalsFormInput > ( {
74
+ resolver : zodResolver ( timeIntervalsFormSchema ) ,
75
+ defaultValues : {
76
+ intervals : [
77
+ { weekDay : 0 , enabled : false , startTime : '08:00' , endTime : '18:00' } ,
78
+ { weekDay : 1 , enabled : true , startTime : '08:00' , endTime : '18:00' } ,
79
+ { weekDay : 2 , enabled : true , startTime : '08:00' , endTime : '18:00' } ,
80
+ { weekDay : 3 , enabled : true , startTime : '08:00' , endTime : '18:00' } ,
81
+ { weekDay : 4 , enabled : true , startTime : '08:00' , endTime : '18:00' } ,
82
+ { weekDay : 5 , enabled : true , startTime : '08:00' , endTime : '18:00' } ,
83
+ { weekDay : 6 , enabled : false , startTime : '08:00' , endTime : '18:00' } ,
84
+ ] ,
85
+ } ,
86
+ } )
87
+
88
+ const weekDays = getWeekDays ( )
89
+
90
+ const { fields } = useFieldArray ( {
91
+ control,
92
+ name : 'intervals' ,
93
+ } )
94
+
95
+ const intervals = watch ( 'intervals' )
96
+
97
+ async function handleSetTimeIntervals ( data : TimeIntervalsFormOutput ) {
98
+ console . log ( data )
99
+ }
100
+
20
101
return (
21
102
< Container >
22
103
< Header >
@@ -27,30 +108,52 @@ export default function TimeIntervals() {
27
108
</ Text >
28
109
< MultiStep size = { 4 } currentStep = { 3 } />
29
110
</ Header >
30
- < IntervalBox as = "form" >
111
+ < IntervalBox as = "form" onSubmit = { handleSubmit ( handleSetTimeIntervals ) } >
31
112
< IntervalsContainer >
32
- < IntervalItem >
33
- < IntervalDay >
34
- < Checkbox />
35
- < Text > Segunda-feira</ Text >
36
- </ IntervalDay >
37
- < IntervalInputs >
38
- < TextInput size = "sm" type = "time" step = { 60 } />
39
- < TextInput size = "sm" type = "time" step = { 60 } />
40
- </ IntervalInputs >
41
- </ IntervalItem >
42
- < IntervalItem >
43
- < IntervalDay >
44
- < Checkbox />
45
- < Text > Terça-feira</ Text >
46
- </ IntervalDay >
47
- < IntervalInputs >
48
- < TextInput size = "sm" type = "time" step = { 60 } />
49
- < TextInput size = "sm" type = "time" step = { 60 } />
50
- </ IntervalInputs >
51
- </ IntervalItem >
113
+ { fields . map ( ( field , index ) => {
114
+ return (
115
+ < IntervalItem key = { field . id } >
116
+ < IntervalDay >
117
+ < Controller
118
+ name = { `intervals.${ index } .enabled` }
119
+ control = { control }
120
+ render = { ( { field } ) => {
121
+ return (
122
+ < Checkbox
123
+ onCheckedChange = { ( checked ) => {
124
+ field . onChange ( checked === true )
125
+ } }
126
+ checked = { field . value }
127
+ />
128
+ )
129
+ } }
130
+ />
131
+ < Text > { weekDays [ field . weekDay ] } </ Text >
132
+ </ IntervalDay >
133
+ < IntervalInputs >
134
+ < TextInput
135
+ size = "sm"
136
+ type = "time"
137
+ step = { 60 }
138
+ disabled = { intervals [ index ] . enabled === false }
139
+ { ...register ( `intervals.${ index } .startTime` ) }
140
+ />
141
+ < TextInput
142
+ size = "sm"
143
+ type = "time"
144
+ step = { 60 }
145
+ disabled = { intervals [ index ] . enabled === false }
146
+ { ...register ( `intervals.${ index } .endTime` ) }
147
+ />
148
+ </ IntervalInputs >
149
+ </ IntervalItem >
150
+ )
151
+ } ) }
52
152
</ IntervalsContainer >
53
- < Button type = "submit" >
153
+ { errors . intervals && (
154
+ < FormError size = { 'sm' } > { errors . intervals . message } </ FormError >
155
+ ) }
156
+ < Button type = "submit" disabled = { isSubmitting } >
54
157
Próximo passo
55
158
< ArrowRight />
56
159
</ Button >
0 commit comments