feat: allow path params for verse navigation

This commit is contained in:
gosangam
2026-04-15 13:41:34 +05:30
parent c0a00d4c04
commit abb7cc49d0
19 changed files with 1462 additions and 261 deletions
+14 -22
View File
@@ -1,6 +1,6 @@
"use client";
import { useRouter, useSearchParams } from "next/navigation";
import { useRouter } from "next/navigation";
import { useCallback, useMemo, useEffect, useState } from "react";
import { Card, CardHeader, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
@@ -58,6 +58,8 @@ type ChapterViewerProps = {
chapter: number;
/** Whether to show the Bengali script field (CC only) */
showBengali?: boolean;
/** Base path for verse URLs, e.g. "/books/bg/1" — verse number is appended */
basePath: string;
};
// ---------------------------------------------------------------------------
@@ -217,9 +219,9 @@ export function ChapterViewer({
division,
chapter,
showBengali = false,
basePath,
}: ChapterViewerProps) {
const router = useRouter();
const searchParams = useSearchParams();
// Verse cache: verseNum → Verse data
const [cache, setCache] = useState<Map<number, Verse>>(() => {
@@ -230,17 +232,9 @@ export function ChapterViewer({
const [loading, setLoading] = useState(false);
// Current verse number from URL (or default to initial)
const currentVerseNum = useMemo(() => {
const param = searchParams.get("verse");
if (param) {
const num = parseInt(param);
if (!isNaN(num) && verseIndex.some((v) => v.verse === num)) {
return num;
}
}
return initialVerseNum;
}, [searchParams, initialVerseNum, verseIndex]);
// Current verse number — driven by the initialVerseNum from the server
// (which reads it from the [verse] path param)
const currentVerseNum = initialVerseNum;
// Current index in the verseIndex array
const currentIdx = useMemo(
@@ -304,23 +298,21 @@ export function ChapterViewer({
[cache, book, division, chapter],
);
// Navigate to a verse — update the URL and fetch if needed
// Navigate to a verse — update the URL path and fetch if needed
const navigateTo = useCallback(
async (verseNum: number) => {
// Update URL with shallow navigation
const params = new URLSearchParams(searchParams.toString());
params.set("verse", String(verseNum));
router.push(`?${params.toString()}`, { scroll: false });
// Fetch if not cached
// Prefetch the verse data before navigating
if (!cache.has(verseNum)) {
await fetchVerse(verseNum);
}
// Navigate to the new path-based URL
router.push(`${basePath}/${verseNum}`, { scroll: false });
// Scroll to top of the verse
window.scrollTo({ top: 0, behavior: "smooth" });
},
[searchParams, router, cache, fetchVerse],
[basePath, router, cache, fetchVerse],
);
// Fetch current verse on mount/URL change if not cached
@@ -390,7 +382,7 @@ export function ChapterViewer({
return (
<a
key={v.verse}
href={`?verse=${v.verse}`}
href={`${basePath}/${v.verse}`}
onClick={(e) => {
e.preventDefault();
navigateTo(v.verse);