feat: hook useReservationForm com estado consolidado em cascata
This commit is contained in:
parent
9ab3b13948
commit
9e13bc4556
138
src/hooks/useReservationForm.ts
Normal file
138
src/hooks/useReservationForm.ts
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
import { useEffect, useState, useCallback } from 'react'
|
||||||
|
import { catalogoService } from '@/services/catalogoService'
|
||||||
|
import type { Database } from '@/types/database'
|
||||||
|
|
||||||
|
type Marca = Database['reserva_hotel']['Tables']['marcas']['Row']
|
||||||
|
type Unidade = Database['reserva_hotel']['Tables']['unidades']['Row']
|
||||||
|
type Preco = Database['reserva_hotel']['Tables']['precos']['Row']
|
||||||
|
type Foto = Database['reserva_hotel']['Tables']['fotos_categoria']['Row']
|
||||||
|
|
||||||
|
export interface ReservationFormState {
|
||||||
|
marcaId: string
|
||||||
|
unidadeId: string
|
||||||
|
permanencia: string
|
||||||
|
categoria: string
|
||||||
|
checkinAt: string // datetime-local format
|
||||||
|
nome: string
|
||||||
|
telefone: string
|
||||||
|
cpf: string
|
||||||
|
email: string
|
||||||
|
observacao: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const empty: ReservationFormState = {
|
||||||
|
marcaId: '',
|
||||||
|
unidadeId: '',
|
||||||
|
permanencia: '',
|
||||||
|
categoria: '',
|
||||||
|
checkinAt: '',
|
||||||
|
nome: '',
|
||||||
|
telefone: '',
|
||||||
|
cpf: '',
|
||||||
|
email: '',
|
||||||
|
observacao: '',
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useReservationForm() {
|
||||||
|
const [form, setForm] = useState<ReservationFormState>(empty)
|
||||||
|
const [marcas, setMarcas] = useState<Marca[]>([])
|
||||||
|
const [unidades, setUnidades] = useState<Unidade[]>([])
|
||||||
|
const [preco, setPreco] = useState<Preco | null>(null)
|
||||||
|
const [fotos, setFotos] = useState<Foto[]>([])
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [error, setError] = useState<string | null>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
catalogoService
|
||||||
|
.listMarcas()
|
||||||
|
.then(setMarcas)
|
||||||
|
.catch((err: Error) => setError(err.message))
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!form.marcaId) {
|
||||||
|
setUnidades([])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
catalogoService
|
||||||
|
.listUnidades(form.marcaId)
|
||||||
|
.then(setUnidades)
|
||||||
|
.catch((err: Error) => setError(err.message))
|
||||||
|
}, [form.marcaId])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!form.marcaId || !form.categoria || !form.permanencia) {
|
||||||
|
setPreco(null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
catalogoService
|
||||||
|
.findPreco(form.marcaId, form.categoria, form.permanencia)
|
||||||
|
.then(setPreco)
|
||||||
|
.catch((err: Error) => setError(err.message))
|
||||||
|
}, [form.marcaId, form.categoria, form.permanencia])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!form.unidadeId || !form.categoria) {
|
||||||
|
setFotos([])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
catalogoService
|
||||||
|
.listFotos(form.unidadeId, form.categoria)
|
||||||
|
.then(setFotos)
|
||||||
|
.catch((err: Error) => setError(err.message))
|
||||||
|
}, [form.unidadeId, form.categoria])
|
||||||
|
|
||||||
|
const update = useCallback(<K extends keyof ReservationFormState>(
|
||||||
|
key: K,
|
||||||
|
value: ReservationFormState[K]
|
||||||
|
) => {
|
||||||
|
setForm((prev) => {
|
||||||
|
const next = { ...prev, [key]: value }
|
||||||
|
if (key === 'marcaId') {
|
||||||
|
next.unidadeId = ''
|
||||||
|
next.categoria = ''
|
||||||
|
next.permanencia = ''
|
||||||
|
}
|
||||||
|
if (key === 'unidadeId') {
|
||||||
|
next.categoria = ''
|
||||||
|
}
|
||||||
|
return next
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const marcaSelecionada = marcas.find((m) => m.id === form.marcaId) ?? null
|
||||||
|
const unidadeSelecionada = unidades.find((u) => u.id === form.unidadeId) ?? null
|
||||||
|
|
||||||
|
const precoTotalCents = preco ? Math.round(Number(preco.valor) * 100) : 0
|
||||||
|
const depositCents = Math.round(precoTotalCents / 2)
|
||||||
|
|
||||||
|
const canSubmit =
|
||||||
|
form.marcaId !== '' &&
|
||||||
|
form.unidadeId !== '' &&
|
||||||
|
form.categoria !== '' &&
|
||||||
|
form.permanencia !== '' &&
|
||||||
|
form.checkinAt !== '' &&
|
||||||
|
form.nome.trim() !== '' &&
|
||||||
|
form.telefone.replace(/\D/g, '').length >= 10 &&
|
||||||
|
form.cpf.replace(/\D/g, '').length === 11 &&
|
||||||
|
preco !== null
|
||||||
|
|
||||||
|
return {
|
||||||
|
form,
|
||||||
|
update,
|
||||||
|
marcas,
|
||||||
|
unidades,
|
||||||
|
marcaSelecionada,
|
||||||
|
unidadeSelecionada,
|
||||||
|
preco,
|
||||||
|
precoTotalCents,
|
||||||
|
depositCents,
|
||||||
|
fotos,
|
||||||
|
loading,
|
||||||
|
setLoading,
|
||||||
|
error,
|
||||||
|
setError,
|
||||||
|
canSubmit,
|
||||||
|
reset: () => setForm(empty),
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user