fix: update glossary UI
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
import type { Metadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getAllGlossaryEntries } from "@/lib/api";
|
||||
import { buildOgMeta } from "@/lib/og";
|
||||
import { GlossaryClient } from "../glossary-client";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Diacritic → base letter mapping
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const DIACRITIC_TO_BASE: Record<string, string> = {
|
||||
Ā: "A", Ä: "A",
|
||||
Ī: "I", É: "I",
|
||||
Ū: "U", Ü: "U",
|
||||
Ṛ: "R", Ṝ: "R",
|
||||
Ś: "S", Ç: "S", Ṣ: "S",
|
||||
Ñ: "N", Ṇ: "N", Ṅ: "N",
|
||||
Ṭ: "T",
|
||||
Ḍ: "D",
|
||||
Ḥ: "H",
|
||||
};
|
||||
|
||||
function getBaseLetter(term: string): string {
|
||||
if (!term) return "?";
|
||||
const first = term[0].toUpperCase();
|
||||
return DIACRITIC_TO_BASE[first] || first;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Metadata
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ letter: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { letter } = await params;
|
||||
const l = letter.toUpperCase();
|
||||
return buildOgMeta({
|
||||
title: `Glossary — ${l}`,
|
||||
detail: `Sanskrit & Vedic terms starting with ${l}`,
|
||||
quote:
|
||||
"A comprehensive glossary of Sanskrit and Vedic terms from the books of Śrīla Prabhupāda.",
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Page
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export default async function GlossaryLetterPage({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ letter: string }>;
|
||||
}) {
|
||||
const { letter: rawLetter } = await params;
|
||||
const activeLetter = rawLetter.toUpperCase();
|
||||
|
||||
// Validate — single letter A-Z
|
||||
if (!/^[A-Z]$/.test(activeLetter)) notFound();
|
||||
|
||||
// Fetch all entries (cached by Next.js request dedup within a single render)
|
||||
const allEntries = await getAllGlossaryEntries();
|
||||
|
||||
// Group all entries by base letter
|
||||
const byLetter: Record<string, typeof allEntries> = {};
|
||||
for (const entry of allEntries) {
|
||||
const base = getBaseLetter(entry.term);
|
||||
if (!byLetter[base]) byLetter[base] = [];
|
||||
byLetter[base].push(entry);
|
||||
}
|
||||
|
||||
// All available letters (sorted)
|
||||
const letters = Object.keys(byLetter).sort();
|
||||
|
||||
// Entries for the active letter
|
||||
const letterEntries = byLetter[activeLetter] || [];
|
||||
if (letterEntries.length === 0) notFound();
|
||||
|
||||
// Prepare client data — only the active letter's entries
|
||||
const clientEntries = letterEntries.map((e) => ({
|
||||
term: e.term,
|
||||
definition: e.definition,
|
||||
definition_html: e.definitionHtml,
|
||||
}));
|
||||
|
||||
// Letter counts for the nav
|
||||
const letterCounts: Record<string, number> = {};
|
||||
for (const [l, entries] of Object.entries(byLetter)) {
|
||||
letterCounts[l] = entries.length;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<GlossaryClient
|
||||
entries={clientEntries}
|
||||
activeLetter={activeLetter}
|
||||
letters={letters}
|
||||
letterCounts={letterCounts}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user