From fc2aef0c3d14c9bd3def0c32b41b277e4dd5db3e Mon Sep 17 00:00:00 2001 From: gosangam Date: Wed, 17 Jun 2026 14:02:06 +0530 Subject: [PATCH] fix: ui fixes in transcript lusting for books --- .../book/[book]/book-browser.tsx | 515 +++++++----------- 1 file changed, 206 insertions(+), 309 deletions(-) diff --git a/app/(app)/transcriptions/book/[book]/book-browser.tsx b/app/(app)/transcriptions/book/[book]/book-browser.tsx index 70ad0909..e11ae9ff 100644 --- a/app/(app)/transcriptions/book/[book]/book-browser.tsx +++ b/app/(app)/transcriptions/book/[book]/book-browser.tsx @@ -38,13 +38,6 @@ export type TranscriptionItem = { audioUrl: string | null; }; -type YearGroup = { - year: number; - label: string; - count: number; - transcriptions: TranscriptionItem[]; -}; - type ChapterGroup = { key: string; label: string; @@ -60,48 +53,13 @@ type SectionGroup = { }; // --------------------------------------------------------------------------- -// Grouping helpers +// Grouping // --------------------------------------------------------------------------- -function buildYearGroups(transcriptions: TranscriptionItem[]): YearGroup[] { - const map = new Map(); - - for (const t of transcriptions) { - const y = t.year ?? 0; - if (!map.has(y)) map.set(y, []); - map.get(y)!.push(t); - } - - const groups: YearGroup[] = []; - - const years = Array.from(map.keys()).sort((a, b) => a - b); - for (const y of years) { - if (y === 0) continue; - const items = map.get(y)!; - groups.push({ - year: y, - label: String(y), - count: items.length, - transcriptions: items, - }); - } - const undated = map.get(0); - if (undated && undated.length > 0) { - groups.push({ - year: 0, - label: "Undated", - count: undated.length, - transcriptions: undated, - }); - } - - return groups; -} - -// Group a year's transcripts into sections (canto/līlā) → chapter accordions, +// 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 appear. Transcripts arrive already sorted chronologically. function buildSections( transcriptions: TranscriptionItem[], code: string, @@ -152,68 +110,93 @@ function buildSections( })); } -// --------------------------------------------------------------------------- -// Year Sidebar -// --------------------------------------------------------------------------- +// 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 YearSidebar({ - groups, - activeYear, - onSelect, -}: { - groups: YearGroup[]; - activeYear: number; - onSelect: (year: number) => void; -}) { - return ( - +function flattenChapters(sections: SectionGroup[]): FlatChapter[] { + return sections.flatMap((s) => + s.chapters.map((chapter) => ({ sectionLabel: s.label, chapter })), ); } // --------------------------------------------------------------------------- -// Mobile drawer +// Chapter nav list (shared by sidebar + mobile drawer) // --------------------------------------------------------------------------- -function YearMobileNav({ - groups, - activeYear, +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, }: { - groups: YearGroup[]; - activeYear: number; - onSelect: (year: number) => void; + sections: SectionGroup[]; + activeKey: string; + onSelect: (key: string) => void; title: string; }) { const [open, setOpen] = useState(false); @@ -227,47 +210,22 @@ function YearMobileNav({ )} > - Years + Chapters {title} - +
+ { + onSelect(key); + setOpen(false); + }} + /> +
); @@ -277,34 +235,34 @@ function YearMobileNav({ // Prev / Next nav // --------------------------------------------------------------------------- -function YearNav({ +function ChapterNav({ prev, next, - groups, - activeYear, + sections, + activeKey, onSelect, drawerTitle, }: { - prev: YearGroup | null; - next: YearGroup | null; - groups: YearGroup[]; - activeYear: number; - onSelect: (year: number) => void; + prev: FlatChapter | null; + next: FlatChapter | null; + sections: SectionGroup[]; + activeKey: string; + onSelect: (key: string) => void; drawerTitle: string; }) { return (
- {prev ? ( @@ -323,14 +281,14 @@ function YearNav({ {next ? ( - - {open && ( -
    - {group.transcriptions.map((t) => ( -
  • - -
    -
    -

    - {t.name} -

    - - {t.type === "lecture" ? "Lecture" : "Conversation"} - -
    -
    - {t.date && ( - - - {t.date} - - )} - {t.place && ( - - - {t.place} - - )} - {t.reference && ( - {t.reference} - )} - {t.durationMinutes && t.durationMinutes > 0 && ( - - - {t.durationMinutes} min - - )} -
    -
    - {t.audioUrl && ( - - )} - -
  • - ))} -
)} -
+ ); } @@ -456,45 +373,43 @@ export function TranscriptionBookBrowser({ title: string; totalCount: number; }) { - const yearGroups = useMemo( - () => buildYearGroups(transcriptions), - [transcriptions], + const sections = useMemo( + () => buildSections(transcriptions, code), + [transcriptions, code], ); - const [activeYearRaw, setActiveYear] = useState( - yearGroups.length > 0 ? yearGroups[0].year : 0, + const flat = useMemo(() => flattenChapters(sections), [sections]); + + const [activeKeyRaw, setActiveKey] = useState( + flat.length > 0 ? flat[0].chapter.key : "", ); - // Derive a safe active year - const activeYear = useMemo(() => { - if (yearGroups.length === 0) return activeYearRaw; - if (yearGroups.find((g) => g.year === activeYearRaw)) return activeYearRaw; - return yearGroups[0].year; - }, [yearGroups, activeYearRaw]); + // Derive a safe active chapter key (the data could change underneath us). + const activeKey = useMemo(() => { + if (flat.length === 0) return activeKeyRaw; + if (flat.find((f) => f.chapter.key === activeKeyRaw)) return activeKeyRaw; + return flat[0].chapter.key; + }, [flat, activeKeyRaw]); const contentRef = useRef(null); - const handleYearSelect = (year: number) => { - setActiveYear(year); + const handleSelect = (key: string) => { + setActiveKey(key); contentRef.current?.scrollIntoView({ behavior: "smooth", block: "start" }); }; - // Active group + neighbors - const activeIdx = yearGroups.findIndex((g) => g.year === activeYear); - const activeGroup = activeIdx >= 0 ? yearGroups[activeIdx] : null; - const prev = activeIdx > 0 ? yearGroups[activeIdx - 1] : null; + const activeIdx = flat.findIndex((f) => f.chapter.key === activeKey); + const active = activeIdx >= 0 ? flat[activeIdx] : null; + const prev = activeIdx > 0 ? flat[activeIdx - 1] : null; const next = - activeIdx >= 0 && activeIdx < yearGroups.length - 1 - ? yearGroups[activeIdx + 1] - : null; + activeIdx >= 0 && activeIdx < flat.length - 1 ? flat[activeIdx + 1] : null; - // Sections (canto/līlā) → chapters within the active year - const sections = useMemo( - () => buildSections(activeGroup?.transcriptions ?? [], code), - [activeGroup, code], - ); - - const activeYearLabel = activeGroup?.label ?? "Unknown"; + const activeFullLabel = active + ? active.sectionLabel + ? `${active.sectionLabel} · ${active.chapter.label}` + : active.chapter.label + : ""; + const activeCount = active?.chapter.transcriptions.length ?? 0; return ( <> @@ -508,79 +423,61 @@ export function TranscriptionBookBrowser({ ← Transcriptions by Book

- {title}: - {activeYearLabel} + {title} + {activeFullLabel ? `: ${activeFullLabel}` : ""}

- {activeGroup?.count ?? 0}{" "} - {(activeGroup?.count ?? 0) === 1 - ? "transcription" - : "transcriptions"}{" "} - in {activeYearLabel} · {totalCount} total + {activeCount} {activeCount === 1 ? "lecture" : "lectures"} in this + chapter · {totalCount} total

{/* Sidebar + Main */}
- {/* Left sidebar — years */} - {/* Main content */}
{/* Top navigation */} - - {/* Content — sections (canto/līlā) → chapter accordions */} - {sections.length === 0 ? ( + {/* Content — every lecture of the active chapter (all years/places) */} + {!active || active.chapter.transcriptions.length === 0 ? (

- No transcriptions for this year + No transcriptions for this chapter

) : ( -
- {sections.map((section) => ( -
- {section.label && ( -

- {section.label} -

- )} - - - {section.chapters.map((cg, i) => ( - - ))} - - -
- ))} -
+ + + {active.chapter.transcriptions.map((t) => ( + + ))} + + )} {/* Bottom navigation */} -