Skip to content

Commit 8eee667

Browse files
committed
Configuring avaliability2
1 parent 538a739 commit 8eee667

File tree

4 files changed

+143
-23
lines changed

4 files changed

+143
-23
lines changed

src/pages/register/time-intervals/index.page.tsx

+125-22
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,96 @@ import {
88
} from '@ignite-ui/react'
99
import { Container, Header } from '../styles'
1010
import {
11+
FormError,
1112
IntervalBox,
1213
IntervalDay,
1314
IntervalInputs,
1415
IntervalItem,
1516
IntervalsContainer,
1617
} from './styles'
1718
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>
1865

1966
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+
20101
return (
21102
<Container>
22103
<Header>
@@ -27,30 +108,52 @@ export default function TimeIntervals() {
27108
</Text>
28109
<MultiStep size={4} currentStep={3} />
29110
</Header>
30-
<IntervalBox as="form">
111+
<IntervalBox as="form" onSubmit={handleSubmit(handleSetTimeIntervals)}>
31112
<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+
})}
52152
</IntervalsContainer>
53-
<Button type="submit">
153+
{errors.intervals && (
154+
<FormError size={'sm'}>{errors.intervals.message}</FormError>
155+
)}
156+
<Button type="submit" disabled={isSubmitting}>
54157
Próximo passo
55158
<ArrowRight />
56159
</Button>

src/pages/register/time-intervals/styles.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Box, styled } from '@ignite-ui/react'
1+
import { Box, Text, styled } from '@ignite-ui/react'
22

33
export const IntervalBox = styled(Box, {
44
marginTop: '$6',
@@ -38,3 +38,8 @@ export const IntervalInputs = styled('div', {
3838
filter: 'invert(100%) brightness(40%)',
3939
},
4040
})
41+
42+
export const FormError = styled(Text, {
43+
color: '#f75a68',
44+
marginBottom: '$4',
45+
})

src/utils/convert-time-in-minutes.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export function convertTimeStringToMinutes(timeString: string) {
2+
const [hours, minutes] = timeString.split(':').map(Number)
3+
return hours * 60 + minutes
4+
}

src/utils/get-week-days.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function getWeekDays() {
2+
const formatter = new Intl.DateTimeFormat('pt-BR', { weekday: 'long' })
3+
return Array.from(Array(7).keys())
4+
.map((day) => formatter.format(new Date(Date.UTC(2021, 5, day))))
5+
.map((weekDay) => {
6+
return weekDay.substring(0, 1).toUpperCase().concat(weekDay.substring(1))
7+
})
8+
}

0 commit comments

Comments
 (0)