No error.tsx existed anywhere in the app - an uncaught render error on any page (a beekeeper's most field-critical moment: mid-inspection, no signal, nowhere to go) showed nothing recoverable, not even a message, let alone a way back to a working page. Two boundaries, matching Next.js App Router's error-boundary scoping: - (app)/error.tsx covers every authenticated page. It only replaces the crashed page's content - the sidebar/header/bottom nav stay mounted and usable, so the user can navigate to a different page without a full reload. - app/error.tsx is the outer fallback (login, the public Herkunft page, or a crash in (app)/layout.tsx itself, which only a strictly higher boundary can catch). Its "Zum Dashboard" action is a plain <a> reload rather than client-side navigation, since a crash this high may have left client state corrupted. Both are in German, matching the app's existing card/honeycomb visual language, and explicitly reassure the user that already-saved data is unaffected. Co-Authored-By: Claude Sonnet 5 <[email protected]>
49 lines
1.8 KiB
TypeScript
49 lines
1.8 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
import { AlertTriangle } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { HoneycombPattern } from "@/components/honeycomb-pattern";
|
|
|
|
export default function RootError({
|
|
error,
|
|
reset,
|
|
}: {
|
|
error: Error & { digest?: string };
|
|
reset: () => void;
|
|
}) {
|
|
useEffect(() => {
|
|
console.error(error);
|
|
}, [error]);
|
|
|
|
return (
|
|
<main className="relative flex min-h-screen items-center justify-center overflow-hidden bg-background p-4">
|
|
<HoneycombPattern />
|
|
<Card className="relative w-full max-w-md shadow-[var(--shadow-elevated)]">
|
|
<CardHeader>
|
|
<div className="flex items-center gap-2.5">
|
|
<span className="flex size-9 items-center justify-center rounded-xl bg-destructive/10 text-destructive">
|
|
<AlertTriangle className="size-5" />
|
|
</span>
|
|
<CardTitle className="text-lg">Etwas ist schiefgelaufen</CardTitle>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent className="flex flex-col gap-4">
|
|
<p className="text-sm text-muted-foreground">
|
|
Es ist ein unerwarteter Fehler aufgetreten. Bereits gespeicherte Daten sind davon nicht
|
|
betroffen.
|
|
</p>
|
|
<div className="flex flex-wrap gap-2">
|
|
<Button onClick={() => reset()}>Erneut versuchen</Button>
|
|
{/* Plain reload, not client-side navigation - a crash here may
|
|
have left the app's client state corrupted, so this must
|
|
guarantee a fully clean slate rather than route through it. */}
|
|
<Button variant="outline" render={<a href="/dashboard">Zum Dashboard</a>} />
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</main>
|
|
);
|
|
}
|