fix(patients): prevent $.map crash in AgendamentoModal and AutocompleteField

- Fix agendamentos?.filter(...).map(...) — optional chain didn't protect .map, crashing when agendamentos is null on first render
- Add Array.isArray guard in AutocompleteField before setResults to prevent non-array from backend error responses breaking subsequent .map
- Add array guard in getGruposFamiliares to return [] on backend error instead of propagating error object

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Builder
2026-05-14 07:50:22 +02:00
parent 4c39a04654
commit e0be095055
2 changed files with 6 additions and 5 deletions
+3 -2
View File
@@ -239,10 +239,11 @@ export const HybridBackend = {
return await res.json();
},
getGruposFamiliares: async (q?: string) => {
getGruposFamiliares: async (q?: string): Promise<import('../types.ts').GrupoFamiliar[]> => {
const url = q?.trim() ? `${API_URL}/grupos-familiares?q=${encodeURIComponent(q)}` : `${API_URL}/grupos-familiares`;
const res = await apiFetch(url);
return res.json();
const data = await res.json();
return Array.isArray(data) ? data : [];
},
criarGrupoFamiliar: async (nome: string, responsavel_id?: string) => {
+3 -3
View File
@@ -36,7 +36,7 @@ function AutocompleteField<T extends { id: string; nome: string }>({
useEffect(() => {
if (!debounced.trim() || value) { setResults([]); setOpen(false); return; }
setLoading(true);
fetchFn(debounced).then(r => { setResults(r); setOpen(r.length > 0); }).finally(() => setLoading(false));
fetchFn(debounced).then(r => { const arr = Array.isArray(r) ? r : []; setResults(arr); setOpen(arr.length > 0); }).finally(() => setLoading(false));
}, [debounced]);
useEffect(() => {
@@ -167,13 +167,13 @@ const AgendamentoModal: React.FC<{ patient: Paciente, onClose: () => void }> = (
const slots: { time: string, available: boolean }[] = [];
if (!selectedDentistId || !selectedDate) return slots;
const startTime = 8 * 60, endTime = 18 * 60, lunchStart = 12 * 60, lunchEnd = 14 * 60;
const existingAppointments = agendamentos?.filter(ag =>
const existingAppointments = (agendamentos ?? []).filter(ag =>
ag.dentistaId === selectedDentistId &&
new Date(ag.start).toISOString().split('T')[0] === selectedDate
).map(ag => ({
start: new Date(ag.start).getHours() * 60 + new Date(ag.start).getMinutes(),
end: new Date(ag.end).getHours() * 60 + new Date(ag.end).getMinutes(),
})) || [];
}));
for (let time = startTime; time < endTime; time += duration) {
const slotStart = time, slotEnd = time + duration;