refactor: defer shop validation in Booking pages to allow optional chaining of shop properties

This commit is contained in:
2026-05-04 10:03:56 +01:00
parent 1dc64579bb
commit 05714a8d7b
2 changed files with 40 additions and 40 deletions

View File

@@ -45,17 +45,6 @@ export default function Booking() {
{ label: '24 horas', value: 1440 },
];
if (!shop) {
return (
<SafeAreaView style={styles.container}>
<Text>Barbearia não encontrada</Text>
</SafeAreaView>
);
}
const selectedService = shop.services.find((s) => s.id === serviceId);
const selectedBarber = shop.barbers.find((b) => b.id === barberId);
// Geração de datas (próximos 14 dias)
const availableDates = useMemo(() => {
const dates = [];
@@ -72,6 +61,9 @@ export default function Booking() {
return dates;
}, []);
const selectedService = shop?.services.find((s) => s.id === serviceId);
const selectedBarber = shop?.barbers.find((b) => b.id === barberId);
const generateDefaultSlots = (): string[] => {
const slots: string[] = [];
for (let hour = 9; hour <= 18; hour++) {
@@ -103,6 +95,14 @@ export default function Booking() {
});
}, [selectedBarber, date, barberId, appointments, slot]);
if (!shop) {
return (
<SafeAreaView style={styles.container}>
<Text>Barbearia não encontrada</Text>
</SafeAreaView>
);
}
const canNext = () => {
if (step === 1) return !!serviceId;
if (step === 2) return !!barberId;

View File

@@ -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;