fix: add array guards to all frontend components consuming API responses
Prevents "M.forEach is not a function" crashes when API returns error objects or unexpected shapes instead of arrays. Guards all useQuery consumers with Array.isArray checks and safe defaults for object props. Files fixed: DeadlineList, AppointmentList, TenantSwitcher, DeadlineTrafficLights, UpcomingTimeline, CaseOverviewGrid, AISummaryCard, TeamSettings, and all page-level components (dashboard, cases, fristen, termine, ai/extract).
This commit is contained in:
@@ -27,7 +27,7 @@ export default function AIExtractPage() {
|
||||
queryFn: () => api.get<PaginatedResponse<Case>>("/cases"),
|
||||
});
|
||||
|
||||
const cases = casesData?.data ?? [];
|
||||
const cases = Array.isArray(casesData?.data) ? casesData.data : [];
|
||||
|
||||
async function handleExtract(file: File | null, text: string) {
|
||||
setIsExtracting(true);
|
||||
|
||||
@@ -132,8 +132,8 @@ export default function CaseDetailPage() {
|
||||
);
|
||||
}
|
||||
|
||||
const deadlines = deadlinesData?.deadlines ?? [];
|
||||
const documents = documentsData ?? [];
|
||||
const deadlines = Array.isArray(deadlinesData?.deadlines) ? deadlinesData.deadlines : [];
|
||||
const documents = Array.isArray(documentsData) ? documentsData : [];
|
||||
|
||||
return (
|
||||
<div className="animate-fade-in">
|
||||
@@ -205,7 +205,7 @@ export default function CaseDetailPage() {
|
||||
{caseDetail.deadlines_count}
|
||||
</span>
|
||||
)}
|
||||
{tab.key === "parties" && caseDetail.parties.length > 0 && (
|
||||
{tab.key === "parties" && Array.isArray(caseDetail.parties) && caseDetail.parties.length > 0 && (
|
||||
<span className="ml-1 rounded-full bg-neutral-100 px-1.5 py-0.5 text-xs text-neutral-500">
|
||||
{caseDetail.parties.length}
|
||||
</span>
|
||||
@@ -217,7 +217,7 @@ export default function CaseDetailPage() {
|
||||
|
||||
<div className="mt-6">
|
||||
{activeTab === "timeline" && (
|
||||
<CaseTimeline events={caseDetail.recent_events ?? []} />
|
||||
<CaseTimeline events={Array.isArray(caseDetail.recent_events) ? caseDetail.recent_events : []} />
|
||||
)}
|
||||
|
||||
{activeTab === "deadlines" && (
|
||||
@@ -229,7 +229,7 @@ export default function CaseDetailPage() {
|
||||
)}
|
||||
|
||||
{activeTab === "parties" && (
|
||||
<PartyList caseId={id} parties={caseDetail.parties ?? []} />
|
||||
<PartyList caseId={id} parties={Array.isArray(caseDetail.parties) ? caseDetail.parties : []} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -68,7 +68,7 @@ export default function CasesPage() {
|
||||
},
|
||||
});
|
||||
|
||||
const cases = data?.cases ?? [];
|
||||
const cases = Array.isArray(data?.cases) ? data.cases : [];
|
||||
|
||||
return (
|
||||
<div className="animate-fade-in">
|
||||
|
||||
@@ -80,17 +80,17 @@ export default function DashboardPage() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<DeadlineTrafficLights data={data.deadline_summary} />
|
||||
<DeadlineTrafficLights data={data.deadline_summary ?? { overdue_count: 0, due_this_week: 0, due_next_week: 0, ok_count: 0 }} />
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
||||
<div className="lg:col-span-2">
|
||||
<UpcomingTimeline
|
||||
deadlines={data.upcoming_deadlines}
|
||||
appointments={data.upcoming_appointments}
|
||||
deadlines={Array.isArray(data.upcoming_deadlines) ? data.upcoming_deadlines : []}
|
||||
appointments={Array.isArray(data.upcoming_appointments) ? data.upcoming_appointments : []}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-6">
|
||||
<CaseOverviewGrid data={data.case_summary} />
|
||||
<CaseOverviewGrid data={data.case_summary ?? { active_count: 0, new_this_month: 0, closed_count: 0 }} />
|
||||
<AISummaryCard data={data} />
|
||||
<QuickActions />
|
||||
</div>
|
||||
|
||||
@@ -66,7 +66,7 @@ export default function FristenPage() {
|
||||
{view === "list" ? (
|
||||
<DeadlineList />
|
||||
) : (
|
||||
<DeadlineCalendarView deadlines={deadlines || []} />
|
||||
<DeadlineCalendarView deadlines={Array.isArray(deadlines) ? deadlines : []} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -84,7 +84,7 @@ export default function TerminePage() {
|
||||
<AppointmentList onEdit={handleEdit} />
|
||||
) : (
|
||||
<AppointmentCalendar
|
||||
appointments={appointments || []}
|
||||
appointments={Array.isArray(appointments) ? appointments : []}
|
||||
onAppointmentClick={handleEdit}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user