refactor: defer shop validation in Booking pages to allow optional chaining of shop properties
This commit is contained in:
@@ -19,31 +19,6 @@ export default function Booking() {
|
||||
const shop = useMemo(() => shops.find((s) => s.id === id), [shops, id]);
|
||||
|
||||
|
||||
if (!shopsReady || (shops.length === 0 && !shop)) {
|
||||
return (
|
||||
<div className="py-32 text-center animate-pulse">
|
||||
<div className="inline-block w-10 h-10 border-4 border-slate-200 border-t-indigo-600 rounded-full animate-spin mb-4" />
|
||||
<p className="text-sm font-black text-slate-500 uppercase tracking-widest italic">A preparar reserva...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!shop) {
|
||||
return (
|
||||
<div className="py-32 text-center space-y-6">
|
||||
<div className="w-20 h-20 bg-slate-100 rounded-[2rem] flex items-center justify-center mx-auto text-slate-300">
|
||||
<Calendar size={40} />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-2xl font-black text-slate-900 uppercase italic tracking-tighter">Espaço não encontrado</h2>
|
||||
<p className="text-slate-500 font-medium italic">Não foi possível iniciar o agendamento para este estabelecimento.</p>
|
||||
</div>
|
||||
<Button asChild className="h-12 px-8 bg-slate-900 text-indigo-400 font-black rounded-2xl uppercase tracking-widest text-[10px] italic">
|
||||
<Link to="/explorar">Voltar ao Explorar</Link>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// Estados para as escolhas parciais do utilizador
|
||||
const [serviceId, setService] = useState(searchParams.get('service') || '');
|
||||
const [barberId, setBarber] = useState('');
|
||||
@@ -63,10 +38,6 @@ export default function Booking() {
|
||||
const selectedService = shop?.services.find((s) => s.id === serviceId);
|
||||
const selectedBarber = shop?.barbers.find((b) => b.id === barberId);
|
||||
|
||||
// Avanço automático por efeito colateral (opcional, mas vamos fazer por clique para ser mais explícito)
|
||||
const nextStep = () => setStep((s) => Math.min(s + 1, 4));
|
||||
const prevStep = () => setStep((s) => Math.max(s - 1, 1));
|
||||
|
||||
const generateDefaultSlots = (): string[] => {
|
||||
const slots: string[] = [];
|
||||
for (let hour = 9; hour <= 18; hour++) {
|
||||
@@ -101,6 +72,35 @@ export default function Booking() {
|
||||
});
|
||||
}, [selectedBarber, date, barberId, appointments, user, waitlists]);
|
||||
|
||||
if (!shopsReady || (shops.length === 0 && !shop)) {
|
||||
return (
|
||||
<div className="py-32 text-center animate-pulse">
|
||||
<div className="inline-block w-10 h-10 border-4 border-slate-200 border-t-indigo-600 rounded-full animate-spin mb-4" />
|
||||
<p className="text-sm font-black text-slate-500 uppercase tracking-widest italic">A preparar reserva...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!shop) {
|
||||
return (
|
||||
<div className="py-32 text-center space-y-6">
|
||||
<div className="w-20 h-20 bg-slate-100 rounded-[2rem] flex items-center justify-center mx-auto text-slate-300">
|
||||
<Calendar size={40} />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-2xl font-black text-slate-900 uppercase italic tracking-tighter">Espaço não encontrado</h2>
|
||||
<p className="text-slate-500 font-medium italic">Não foi possível iniciar o agendamento para este estabelecimento.</p>
|
||||
</div>
|
||||
<Button asChild className="h-12 px-8 bg-slate-900 text-indigo-400 font-black rounded-2xl uppercase tracking-widest text-[10px] italic">
|
||||
<Link to="/explorar">Voltar ao Explorar</Link>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Avanço automático por efeito colateral (opcional, mas vamos fazer por clique para ser mais explícito)
|
||||
const nextStep = () => setStep((s) => Math.min(s + 1, 4));
|
||||
const prevStep = () => setStep((s) => Math.max(s - 1, 1));
|
||||
|
||||
const canSubmit = serviceId && barberId && date && slot;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user