"use client"; /** * /sadhna-streak/chant — the japa counter. * * Shows the Hare Kṛṣṇa mahā-mantra with a big tap-to-count round counter * running toward the devotee's daily target (their profile's * daily_chanting_rounds, falling back to 16). Save persists the count; * reaching the target marks today's chanting discipline complete. * * Auth-gated like the rest of /sadhna-streak. It seeds the counter from * today's already-saved progress so a devotee can chant in sittings. */ import { useCallback, useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import Link from "next/link"; import { ArrowLeft, Check, Minus, RotateCcw } from "lucide-react"; import { toast } from "sonner"; import { useAuth } from "@/components/auth/auth-provider"; import { useAuthGate } from "@/components/auth/auth-gate"; import { sadhna } from "@/lib/sadhna"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; const MANTRA = [ "Hare Kṛṣṇa Hare Kṛṣṇa", "Kṛṣṇa Kṛṣṇa Hare Hare", "Hare Rāma Hare Rāma", "Rāma Rāma Hare Hare", ]; const FALLBACK_TARGET = 16; export default function ChantPage() { const { user, loading } = useAuth(); const { requireAuth } = useAuthGate(); const router = useRouter(); const [target, setTarget] = useState(FALLBACK_TARGET); const [count, setCount] = useState(0); const [state, setState] = useState<"loading" | "ready" | "error">("loading"); const [saving, setSaving] = useState(false); const [savedAt, setSavedAt] = useState(0); // count value at last save // Auth gate. useEffect(() => { if (loading || user) return; let cancelled = false; (async () => { const ok = await requireAuth(); if (!ok && !cancelled) router.replace("/"); })(); return () => { cancelled = true; }; }, [loading, user, requireAuth, router]); // Seed from today's saved progress. useEffect(() => { if (!user) return; let cancelled = false; sadhna .dashboard() .then((d) => { if (cancelled) return; setTarget(d.target_rounds || FALLBACK_TARGET); setCount(d.rounds_completed || 0); setSavedAt(d.rounds_completed || 0); setState("ready"); }) .catch(() => !cancelled && setState("error")); return () => { cancelled = true; }; }, [user]); const inc = useCallback(() => { setCount((c) => Math.min(target, c + 1)); }, [target]); const dec = useCallback(() => setCount((c) => Math.max(0, c - 1)), []); const reset = useCallback(() => setCount(0), []); const save = useCallback(async () => { setSaving(true); try { const d = await sadhna.saveChant(count); setSavedAt(count); setTarget(d.target_rounds || FALLBACK_TARGET); toast.success( d.chant_done ? "Today's chanting complete 🙏" : `Saved — ${count} of ${d.target_rounds} rounds`, ); } catch { toast.error("Could not save. Please try again."); } finally { setSaving(false); } }, [count]); if (loading || !user) { return (

{loading ? "Loading…" : "Sign in to chant."}

); } const complete = count >= target; const dirty = count !== savedAt; const pct = target > 0 ? Math.min(100, (count / target) * 100) : 0; return (
Sādhana
{/* Mantra */}

The Mahā-mantra

{MANTRA.map((line) => (

{line}

))}
{/* Big tap-to-count dial */}

One round is 108 names on the mālā.

{/* Save */}
{state === "error" ? (

Could not load today`'s progress.

) : null}
); }