feat(ui): add error boundary fallback page with retry and recovery actions
All checks were successful
Deploy Flowstate to VPS / deploy (push) Successful in 48s
All checks were successful
Deploy Flowstate to VPS / deploy (push) Successful in 48s
This commit is contained in:
parent
730649d809
commit
5ba906cf84
1 changed files with 77 additions and 0 deletions
77
app/(app)/error.tsx
Normal file
77
app/(app)/error.tsx
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* @file app/(app)/error.tsx
|
||||
* @description Client-side error boundary component that renders an error fallback UI with recovery and navigation actions.
|
||||
*/
|
||||
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { AlertTriangle, RefreshCw, ArrowLeft } from "lucide-react";
|
||||
|
||||
/**
|
||||
* Properties for the ErrorBoundary component.
|
||||
*
|
||||
* @interface ErrorBoundaryProps
|
||||
* @property {Error & { digest?: string }} error - The error object caught by the Next.js error boundary.
|
||||
* @property {() => void} reset - Function to reset the error boundary and attempt to re-render the segment.
|
||||
*/
|
||||
interface ErrorBoundaryProps {
|
||||
error: Error & { digest?: string };
|
||||
reset: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an error boundary fallback UI displaying error details, a retry button, and navigation back to the summary page.
|
||||
*
|
||||
* @param {ErrorBoundaryProps} props - The component props.
|
||||
* @returns {JSX.Element} The rendered error boundary fallback component.
|
||||
*/
|
||||
export default function ErrorBoundary({ error, reset }: ErrorBoundaryProps) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full w-full text-center my-auto">
|
||||
<div className="max-w-md w-full space-y-6">
|
||||
{/* Icon Badge */}
|
||||
<div className="mx-auto w-16 h-16 rounded-2xl bg-destructive-bg border border-destructive-border flex items-center justify-center text-destructive shadow-sm">
|
||||
<AlertTriangle size={36} />
|
||||
</div>
|
||||
|
||||
{/* Text Content */}
|
||||
<div className="space-y-2">
|
||||
<h1 className="text-2xl font-bold tracking-tight">
|
||||
Something went wrong!
|
||||
</h1>
|
||||
<p className="text-sm text-foreground-muted leading-relaxed">
|
||||
An unexpected error occurred while processing your request. You can
|
||||
try reloading this section or head back to your summary.
|
||||
</p>
|
||||
{error?.message && (
|
||||
<div className="mt-4 p-3 rounded-lg bg-card border border-border text-xs text-foreground-muted font-mono text-center w-full max-w-sm mx-auto overflow-x-auto max-h-24">
|
||||
{error.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="flex flex-col sm:flex-row items-center justify-center gap-3 pt-2">
|
||||
{/* Try Again Button */}
|
||||
<button
|
||||
onClick={() => reset()}
|
||||
className="w-full sm:w-auto inline-flex items-center justify-center gap-2 py-2.5 px-4 rounded-xl bg-primary text-black font-medium hover:bg-primary-hover transition-colors shadow-sm cursor-pointer"
|
||||
>
|
||||
<RefreshCw size={16} />
|
||||
Try again
|
||||
</button>
|
||||
|
||||
{/* Back to Summary Link */}
|
||||
<Link
|
||||
href="/summary"
|
||||
className="w-full sm:w-auto inline-flex items-center justify-center gap-2 py-2.5 px-4 rounded-xl bg-card border border-border text-white font-medium hover:bg-card/80 transition-colors shadow-sm cursor-pointer"
|
||||
>
|
||||
<ArrowLeft size={16} />
|
||||
Back to Summary
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue