import type { ReactNode } from "react";
import { DotDisplay, Well } from "@unlocalhosted/metalui";
/** A 5 × 7 dot face for the digits, row by row ("#" lit). */
const DIGITS: Record<string, string[]> = {
"0": [".###.", "#...#", "#..##", "#.#.#", "##..#", "#...#", ".###."],
"1": ["..#..", ".##..", "..#..", "..#..", "..#..", "..#..", ".###."],
"2": [".###.", "#...#", "....#", "...#.", "..#..", ".#...", "#####"],
"3": ["#####", "...#.", "..#..", "...#.", "....#", "#...#", ".###."],
"4": ["...#.", "..##.", ".#.#.", "#..#.", "#####", "...#.", "...#."],
"5": ["#####", "#....", "####.", "....#", "....#", "#...#", ".###."],
"6": ["..##.", ".#...", "#....", "####.", "#...#", "#...#", ".###."],
"7": ["#####", "....#", "...#.", "..#..", ".#...", ".#...", ".#..."],
"8": [".###.", "#...#", "#...#", ".###.", "#...#", "#...#", ".###."],
"9": [".###.", "#...#", "#...#", ".####", "....#", "...#.", ".##.."],
};
/** A status code printed into a dot display: one unlit dot of margin round 5 × 7 digits, one apart. */
function codeDots(code: string) {
const glyphs = [...code].map((c) => DIGITS[c] ?? DIGITS["0"]);
const cols = glyphs.length * 6 + 1;
const rows = 9;
const dots = new Array<number>(cols * rows).fill(0);
glyphs.forEach((g, i) =>
g.forEach((line, y) =>
[...line].forEach((cell, x) => {
if (cell === "#") dots[(y + 1) * cols + 1 + i * 6 + x] = 1;
}),
),
);
return { cols, rows, dots };
}
/**
* A page that can't be shown (404, 403): MetalUI's empty state composition, centred, with the status
* code on a dot display sunk in a well, an engraved name for it, what happened and the way out.
*/
export function StatusPage({
code,
label,
title,
description,
actions,
}: {
code: string;
label: string;
title: string;
description: ReactNode;
actions: ReactNode;
}) {
const { cols, rows, dots } = codeDots(code);
return (
<main className="flex flex-1 flex-col items-center justify-center px-4 py-24 text-center">
<Well variant="region" radius="region" className="inline-flex p-3" role="img" aria-label={`Error ${code}`}>
<DotDisplay cols={cols} rows={rows} dots={dots} inks={["off", "ink"]} />
</Well>
<p className="mt-6 type-label engraved">
Error {code} · {label}
</p>
<h1 className="mt-2 text-[22px] leading-7 font-semibold tracking-[-0.025em] text-ink">{title}</h1>
<p className="mt-1.5 max-w-md type-lead text-ink2">{description}</p>
<div className="mt-7 flex flex-wrap justify-center gap-2">{actions}</div>
</main>
);
}