fix+upstream: hooks-order crash, ConfirmDialog/PageHeader/skeletons, styled error boundary

Hoists hooks above early return (render-time Navigate); ports finance's
ConfirmDialog/PageHeader/loading/states + APC error-copy mapper; removes
window.confirm, dead appbar search, and seeded fake notifications; wires toasts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jules
2026-07-04 13:46:12 +10:00
parent 3dbf2ac175
commit 675f6f8b35
13 changed files with 809 additions and 319 deletions

View File

@@ -6,10 +6,14 @@ import {
ScrollRestoration,
isRouteErrorResponse,
} from "react-router"
import { AlertTriangle, Home, RotateCcw } from "lucide-react"
import type { Route } from "./+types/root"
import "./app.css"
import { humanErrorMessage, humanErrorTitle } from "~/lib/errors"
import { Button, buttonVariants } from "~/components/ui/button"
import { ToastProvider } from "@crema/notification-ui"
import { CommandBusProvider } from "@crema/action-bus"
// CREMA:PROVIDERS-IMPORTS
@@ -50,30 +54,48 @@ export default function App() {
}
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
let message = "Oops!"
let details = "An unexpected error occurred."
let stack: string | undefined
if (isRouteErrorResponse(error)) {
message = error.status === 404 ? "404" : "Error"
details =
error.status === 404
? "The requested page could not be found."
: error.statusText || details
} else if (import.meta.env.DEV && error && error instanceof Error) {
details = error.message
stack = error.stack
}
const title = humanErrorTitle(error)
const message = humanErrorMessage(error)
const is404 = isRouteErrorResponse(error) && error.status === 404
// Stack traces are a developer affordance — never leak them to users in
// production, and even in dev keep them tucked below the human copy.
const stack =
import.meta.env.DEV && error instanceof Error ? error.stack : undefined
return (
<main className="container mx-auto p-4 pt-16">
<h1>{message}</h1>
<p>{details}</p>
{stack && (
<pre className="w-full overflow-x-auto p-4">
<code>{stack}</code>
</pre>
)}
<main className="flex min-h-svh items-center justify-center bg-background p-6">
<div className="w-full max-w-md rounded-2xl border bg-card p-8 text-center shadow-e1">
<div className="mx-auto mb-5 flex size-12 items-center justify-center rounded-2xl bg-destructive/10 text-destructive">
<AlertTriangle className="size-6" />
</div>
<h1 className="text-title font-semibold tracking-tight text-card-foreground">
{is404 ? "Page not found" : title}
</h1>
<p className="mx-auto mt-2 max-w-sm text-[15px] leading-relaxed text-muted-foreground">
{message}
</p>
<div className="mt-6 flex flex-wrap items-center justify-center gap-2">
<a
href="/"
data-action="error-go-home"
className={buttonVariants({ variant: "default" })}
>
<Home className="size-4" /> Go home
</a>
<Button
data-action="error-retry"
variant="outline"
onClick={() => window.location.reload()}
>
<RotateCcw className="size-4" /> Try again
</Button>
</div>
{stack ? (
<pre className="mt-6 max-h-64 overflow-auto rounded-lg border bg-muted/40 p-4 text-left font-mono text-xs leading-relaxed text-muted-foreground">
<code>{stack}</code>
</pre>
) : null}
</div>
</main>
)
}