66 lines
1.6 KiB
TypeScript
66 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { useEffect } from "react";
|
|
|
|
/**
|
|
* Route-segment error boundary. Renders inside the root layout (so the shell
|
|
* stays), shows a friendly card, and offers a reset. The raw error is logged to
|
|
* the console, never shown to the user.
|
|
*/
|
|
export default function ErrorPage({
|
|
error,
|
|
reset,
|
|
}: {
|
|
error: Error & { digest?: string };
|
|
reset: () => void;
|
|
}) {
|
|
useEffect(() => {
|
|
console.error(error);
|
|
}, [error]);
|
|
|
|
return (
|
|
<main style={{ display: "grid", gap: "1.5rem" }}>
|
|
<div className="content-card">
|
|
<div className="content-card-head">
|
|
<span className="content-card-icon" aria-hidden>
|
|
⚠️
|
|
</span>
|
|
<div className="content-card-head-text">
|
|
<p className="content-card-title">Something went wrong</p>
|
|
<p className="content-card-subtitle">
|
|
An unexpected error occurred
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div className="content-card-body">
|
|
<p className="muted" style={{ marginTop: 0 }}>
|
|
Try again — if the problem persists, please contact a member of
|
|
staff.
|
|
</p>
|
|
<div style={{ display: "flex", gap: "0.6rem", flexWrap: "wrap" }}>
|
|
<button
|
|
type="button"
|
|
className="btn btn-primary"
|
|
onClick={() => reset()}
|
|
>
|
|
Try again
|
|
</button>
|
|
<Link className="btn btn-outline" href="/">
|
|
Back home
|
|
</Link>
|
|
</div>
|
|
{error.digest ? (
|
|
<p
|
|
className="muted"
|
|
style={{ marginTop: "0.75rem", fontSize: "0.75rem" }}
|
|
>
|
|
Reference: {error.digest}
|
|
</p>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|