File size: 3,239 Bytes
6111b2b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import Link from "next/link";
import { useTranslations } from "next-intl";

interface PageAction {
  href: string;
  label: string;
}

interface ErrorPageScaffoldProps {
  code: string;
  title: string;
  description: string;
  icon?: string;
  suggestions?: string[];
  primaryAction?: PageAction | null;
  secondaryAction?: PageAction | null;
}

export default function ErrorPageScaffold({

  code,

  title,

  description,

  icon = "error",

  suggestions = [],

  primaryAction,

  secondaryAction,

}: ErrorPageScaffoldProps) {
  const t = useTranslations("common");
  const resolvedPrimary = primaryAction ?? { href: "/dashboard", label: t("goToDashboard") };
  const resolvedSecondary = secondaryAction ?? { href: "/status", label: t("checkSystemStatus") };

  return (
    <main

      className="min-h-screen bg-bg text-text-main flex items-center justify-center px-6 py-12"

      role="main"

      aria-labelledby="error-page-title"

    >

      <section className="w-full max-w-2xl rounded-2xl border border-border bg-surface p-8 sm:p-10 shadow-soft">

        <header className="text-center">

          <span className="material-symbols-outlined text-4xl text-primary mb-3" aria-hidden="true">

            {icon}

          </span>

          <p

            className="text-6xl sm:text-7xl font-bold leading-none bg-gradient-to-br from-primary to-primary-hover bg-clip-text text-transparent"

            aria-hidden="true"

          >

            {code}

          </p>

          <h1 id="error-page-title" className="mt-4 text-2xl sm:text-3xl font-semibold">

            {title}

          </h1>

          <p className="mt-3 text-text-muted leading-relaxed">{description}</p>

        </header>



        {suggestions.length > 0 && (

          <ul

            className="mt-8 rounded-xl border border-border bg-bg-alt p-5 space-y-2 text-sm text-text-muted"

            aria-label="Recommended actions"

          >

            {suggestions.map((item) => (

              <li key={item} className="flex items-start gap-2">

                <span

                  className="material-symbols-outlined text-base text-primary mt-0.5"

                  aria-hidden="true"

                >

                  check_circle

                </span>

                <span>{item}</span>

              </li>

            ))}

          </ul>

        )}



        <div className="mt-8 flex flex-col sm:flex-row gap-3">

          <Link

            href={resolvedPrimary.href}

            className="inline-flex items-center justify-center px-6 py-3 rounded-lg text-white text-sm font-semibold bg-gradient-to-br from-primary to-primary-hover hover:shadow-elevated transition-all duration-200 motion-reduce:transition-none"

          >

            {resolvedPrimary.label}

          </Link>

          <Link

            href={resolvedSecondary.href}

            className="inline-flex items-center justify-center px-6 py-3 rounded-lg text-sm font-semibold border border-border hover:bg-bg-alt transition-colors duration-200 motion-reduce:transition-none"

          >

            {resolvedSecondary.label}

          </Link>

        </div>

      </section>

    </main>
  );
}