No transcriptions for this chapter
"use client";
import { useState, useMemo, useRef } from "react";
import Link from "next/link";
import { usePathname, useSearchParams } from "next/navigation";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { buttonVariants } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { ChevronLeft, ChevronRight, Menu, Calendar, Clock, MapPin } from "lucide-react";
import { PlayAudioButton } from "@/app/(app)/transcriptions/[slug]/play-audio-button";
import { parseChapter, parseVerse } from "@/lib/book-reference";
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer";
// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------
export type TranscriptionItem = {
slug: string;
name: string;
type: string;
date: string | null;
year: number | null;
month: number | null;
day: number | null;
place: string | null;
context: string | null;
reference: string | null;
durationMinutes: number | null;
participants: string[];
audioUrl: string | null;
};
type ChapterGroup = {
key: string;
label: string;
transcriptions: TranscriptionItem[];
};
// A section is a canto (SB) or līlā (CC). Books without that level produce a
// single section with a null label (rendered without a heading).
type SectionGroup = {
key: string;
label: string | null;
chapters: ChapterGroup[];
};
// ---------------------------------------------------------------------------
// Grouping
// ---------------------------------------------------------------------------
// Group all of a book's transcripts into sections (canto/līlā) → chapters,
// ordered by the parsed sort tuple. Books without a canto/līlā level collapse
// into a single section with a null label. Only sections/chapters that have
// transcripts appear. Transcripts arrive already sorted chronologically.
function buildSections(
transcriptions: TranscriptionItem[],
code: string,
): SectionGroup[] {
const sections = new Map<
string,
{
label: string | null;
order: number;
chapters: Map<
string,
{ label: string; sort: [number, number]; items: TranscriptionItem[] }
>;
}
>();
for (const t of transcriptions) {
const ch = parseChapter(code, t.reference);
const secKey = ch.section ? ch.section.key : "__flat__";
if (!sections.has(secKey)) {
sections.set(secKey, {
label: ch.section ? ch.section.label : null,
order: ch.section ? ch.section.order : 0,
chapters: new Map(),
});
}
const sec = sections.get(secKey)!;
if (!sec.chapters.has(ch.key)) {
sec.chapters.set(ch.key, { label: ch.label, sort: ch.sort, items: [] });
}
sec.chapters.get(ch.key)!.items.push(t);
}
return Array.from(sections.entries())
.sort((a, b) => a[1].order - b[1].order)
.map(([key, s]) => ({
key,
label: s.label,
chapters: Array.from(s.chapters.entries())
.sort(
(a, b) => a[1].sort[0] - b[1].sort[0] || a[1].sort[1] - b[1].sort[1],
)
.map(([k, v]) => ({
key: k,
label: v.label,
// Order lectures by verse ascending (e.g. 2.1, 2.3, 2.4…),
// irrespective of year. Stable sort keeps year order within a verse.
transcriptions: v.items
.slice()
.sort((a, b) => parseVerse(a.reference) - parseVerse(b.reference)),
})),
}));
}
// Flatten sections into a linear chapter list for prev/next navigation and
// active-chapter lookup, carrying each chapter's section label for display.
type FlatChapter = { sectionLabel: string | null; chapter: ChapterGroup };
function flattenChapters(sections: SectionGroup[]): FlatChapter[] {
return sections.flatMap((s) =>
s.chapters.map((chapter) => ({ sectionLabel: s.label, chapter })),
);
}
// ---------------------------------------------------------------------------
// Chapter nav list (shared by sidebar + mobile drawer)
// ---------------------------------------------------------------------------
function ChapterNavList({
sections,
activeKey,
onSelect,
}: {
sections: SectionGroup[];
activeKey: string;
onSelect: (key: string) => void;
}) {
return (
);
}
function ChapterSidebar(props: {
sections: SectionGroup[];
activeKey: string;
onSelect: (key: string) => void;
}) {
return (
);
}
function ChapterMobileNav({
sections,
activeKey,
onSelect,
title,
}: {
sections: SectionGroup[];
activeKey: string;
onSelect: (key: string) => void;
title: string;
}) {
const [open, setOpen] = useState(false);
return (
{t.name}
{activeCount} {activeCount === 1 ? "lecture" : "lectures"} in this chapter · {totalCount} total
No transcriptions for this chapter