Skip to content

Commit c45dd7a

Browse files
authored
Merge pull request #30 from AdaInTheLab/fix/note-detail-view
Adds root error boundary and improves note excerpt
2 parents 0e1eb8f + dfc2f48 commit c45dd7a

2 files changed

Lines changed: 74 additions & 10 deletions

File tree

src/main.tsx

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,41 @@ export {};
4040

4141
const GA_ID = import.meta.env.VITE_GA_ID as string | undefined;
4242

43+
class RootErrorBoundary extends React.Component<
44+
{ children: React.ReactNode },
45+
{ hasError: boolean; error?: unknown }
46+
> {
47+
state = { hasError: false as boolean, error: undefined as unknown };
48+
49+
static getDerivedStateFromError(error: unknown) {
50+
return { hasError: true, error };
51+
}
52+
53+
componentDidCatch(error: unknown) {
54+
console.error("[HPL] Uncaught render error:", error);
55+
}
56+
57+
render() {
58+
if (this.state.hasError) {
59+
return (
60+
<div className="min-h-screen bg-slate-950 text-slate-100 flex items-center justify-center p-6">
61+
<div className="max-w-xl space-y-3 rounded-xl border border-slate-800 bg-slate-900/30 p-6">
62+
<div className="text-xs font-mono uppercase tracking-widest text-slate-400">
63+
HPL Recovery Mode
64+
</div>
65+
<div className="text-lg font-semibold">Something crashed during render.</div>
66+
<div className="text-sm text-slate-300">
67+
Check the console for details. If this is production, we can add a safer fallback path.
68+
</div>
69+
</div>
70+
</div>
71+
);
72+
}
73+
return this.props.children;
74+
}
75+
}
76+
77+
4378
function initGA(measurementId: string) {
4479
// 1) Create dataLayer + gtag stub immediately
4580
window.dataLayer = window.dataLayer ?? [];
@@ -70,6 +105,8 @@ if (GA_ID) initGA(GA_ID);
70105

71106
ReactDOM.createRoot(document.getElementById("root")!).render(
72107
<React.StrictMode>
73-
<RouterProvider router={router} />
108+
<RootErrorBoundary>
109+
<RouterProvider router={router} />
110+
</RootErrorBoundary>
74111
</React.StrictMode>
75112
);

src/pages/admin/pages/AdminNotesPage.tsx

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ export function AdminNotesPage() {
152152
await refreshNotes();
153153
};
154154

155+
const EXCERPT_SOFT_LIMIT = 280;
156+
const excerptLength = form.excerpt.length;
157+
const overLimit = excerptLength > EXCERPT_SOFT_LIMIT;
158+
155159
return (
156160
<div className="space-y-6">
157161
{/* Header */}
@@ -317,16 +321,39 @@ export function AdminNotesPage() {
317321
</div>
318322

319323
<div className="space-y-2">
320-
<label className="text-xs uppercase tracking-widest text-zinc-500">
321-
Excerpt
324+
<label className="block space-y-1">
325+
<span className="text-xs font-mono uppercase tracking-widest text-zinc-400">
326+
Excerpt (preview surface)
327+
</span>
328+
329+
<textarea
330+
name="excerpt"
331+
value={form.excerpt}
332+
onChange={handleChange}
333+
className={`
334+
h-24 w-full resize-y rounded-lg
335+
border bg-zinc-950/40 px-3 py-2 text-zinc-100
336+
${overLimit ? "border-vesper/60 ring-1 ring-vesper/40" : "border-zinc-800"}
337+
`}
338+
placeholder="Short summary shown in lists"
339+
/>
340+
341+
<div
342+
className={`
343+
flex justify-between text-xs font-mono
344+
${overLimit ? "text-vesper" : "text-zinc-500"}
345+
`}
346+
>
347+
<span>
348+
Used on cards and previews. Full body lives in MD source.
349+
</span>
350+
351+
<span>
352+
{excerptLength} / {EXCERPT_SOFT_LIMIT}
353+
{overLimit && " · preview overflow"}
354+
</span>
355+
</div>
322356
</label>
323-
<textarea
324-
name="excerpt"
325-
value={form.excerpt}
326-
onChange={handleChange}
327-
className="h-24 w-full rounded-lg border border-zinc-800 bg-zinc-950/40 px-3 py-2 text-zinc-100"
328-
placeholder="Short summary shown in lists"
329-
/>
330357
</div>
331358

332359
<div className="flex flex-wrap gap-2">

0 commit comments

Comments
 (0)