import Link from "next/link"; import { notFound } from "next/navigation"; import { getNoiContent, getNoiSidebarItems, type NoiVerse, type NoiIntroSegment, type NoiSidebarItem, } from "@/lib/noi"; import { PageHeader } from "@/components/page-header"; import { Card, CardContent } from "@/components/ui/card"; import { buttonVariants } from "@/components/ui/button"; import { ChevronLeft, ChevronRight } from "lucide-react"; import { cn } from "@/lib/utils"; // --------------------------------------------------------------------------- // Type guards // --------------------------------------------------------------------------- function isVerse(content: NoiVerse | NoiIntroSegment): content is NoiVerse { return "text" in content && "devanagari" in content; } function isIntroSegment( content: NoiVerse | NoiIntroSegment, ): content is NoiIntroSegment { return "paragraphs" in content && "order" in content; } // --------------------------------------------------------------------------- // Page // --------------------------------------------------------------------------- export default async function NoiTextPage({ params, }: { params: Promise<{ text: string }>; }) { const { text: slug } = await params; const content = await getNoiContent(slug); if (!content) notFound(); const sidebarItems = await getNoiSidebarItems(); const currentIdx = sidebarItems.findIndex((item) => item.slug === slug); const prev = currentIdx > 0 ? sidebarItems[currentIdx - 1] : null; const next = currentIdx < sidebarItems.length - 1 ? sidebarItems[currentIdx + 1] : null; // Build the page title for the header const verse = isVerse(content) ? content : null; const intro = isIntroSegment(content) ? content : null; return (
← The Nectar of Instruction

{verse && ( <> Text {verse.text}: {verse.title} )} {intro && intro.title}

{/* Left sidebar */} {/* Main content */}
{/* Top navigation */} {/* Content */} {verse && } {intro && } {/* Bottom navigation */}
); } // --------------------------------------------------------------------------- // Verse content (Devanagari, transliteration, synonyms, translation, purport) // --------------------------------------------------------------------------- function VerseContent({ verse }: { verse: NoiVerse }) { return ( {/* Devanagari */}
{verse.devanagari}
{/* Transliteration */}
{verse.transliteration}
{/* Synonyms */} {verse.synonyms.length > 0 && (

Synonyms

{verse.synonyms.map((s, i) => ( {i > 0 && "; "} {s.word} {"—"} {s.meanings.join(", ")} ))}
)} {/* Translation */}

Translation

{/* Purport */} {verse.purport.length > 0 && (

Purport

{verse.purport.map((p, i) => (
))}
)}
); } // --------------------------------------------------------------------------- // Intro segment content (paragraphs) // --------------------------------------------------------------------------- function IntroContent({ intro }: { intro: NoiIntroSegment }) { return (
{intro.paragraphs.map((paragraph, i) => (
))}
); } // --------------------------------------------------------------------------- // Sidebar // --------------------------------------------------------------------------- function NoiSidebar({ items, currentSlug, }: { items: NoiSidebarItem[]; currentSlug: string; }) { // Front matter items (front-pages + preface) const frontMatterItems = items.filter( (item) => item.slug === "intro-front-pages" || item.slug === "intro-preface", ); // Texts = 1-11 const textItems = items.filter((item) => item.type === "verse"); // Appendixes comes last const appendixesItem = items.find( (item) => item.slug === "intro-appendixes", ); return ( ); } function SidebarLink({ item, isActive, }: { item: NoiSidebarItem; isActive: boolean; }) { return ( {item.label} ); } // --------------------------------------------------------------------------- // Prev / Next navigation // --------------------------------------------------------------------------- function NoiNav({ prev, next, }: { prev: NoiSidebarItem | null; next: NoiSidebarItem | null; }) { return (
{prev ? ( {prev.type === "verse" && prev.text != null ? `Text ${prev.text}` : prev.label} Previous ) : (
)} {next ? ( {next.type === "verse" && next.text != null ? `Text ${next.text}` : next.label} Next ) : (
)}
); }