feat: add webpush and sadhna tracker
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
"use client";
|
||||
|
||||
/**
|
||||
* SadhnaStreakCTA — a compact streak card for the homepage. Tapping it opens
|
||||
* /sadhna-streak. For a signed-in devotee it shows their live streak and
|
||||
* today's status; for visitors it's a gentle invitation to begin. The feed
|
||||
* will sit alongside this later.
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { ChevronRight } from "lucide-react";
|
||||
import { useAuth } from "@/components/auth/auth-provider";
|
||||
import { sadhna, type SadhnaDashboard } from "@/lib/sadhna";
|
||||
import { StreakFlame } from "@/components/sadhna/streak-flame";
|
||||
|
||||
export function SadhnaStreakCTA() {
|
||||
const { user, loading } = useAuth();
|
||||
const authed = !loading && !!user;
|
||||
const [dash, setDash] = useState<SadhnaDashboard | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Only fetch when signed in; never setState synchronously here. A stale
|
||||
// dash from a previous session is ignored in render via `data` below.
|
||||
if (!authed) return;
|
||||
let cancelled = false;
|
||||
sadhna
|
||||
.dashboard()
|
||||
.then((d) => {
|
||||
if (!cancelled) setDash(d);
|
||||
})
|
||||
.catch(() => {
|
||||
/* card stays in its invitation state */
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [authed]);
|
||||
|
||||
// Ignore any leftover dashboard when not authed (e.g. after sign-out).
|
||||
const data = authed ? dash : null;
|
||||
const streak = data?.current_streak ?? 0;
|
||||
|
||||
const title = !authed
|
||||
? "Daily Sādhana"
|
||||
: streak > 0
|
||||
? `${streak} day${streak === 1 ? "" : "s"} sadhna streak`
|
||||
: "Start your streak";
|
||||
|
||||
const subtitle = !authed
|
||||
? "Chant your rounds and share a verse each day"
|
||||
: data?.today_completed
|
||||
? "Today's sādhana is complete 🌸"
|
||||
: data?.chant_done || data?.quote_done
|
||||
? "One offering done — finish today"
|
||||
: "Chant and post a quote to complete today";
|
||||
|
||||
return (
|
||||
<Link
|
||||
href="/sadhna-streak"
|
||||
className="group flex w-full max-w-md items-center gap-3.5 rounded-2xl border border-border bg-card p-4 text-left transition-colors hover:border-primary/40 hover:bg-muted/40"
|
||||
>
|
||||
<span
|
||||
className={
|
||||
"inline-flex size-12 shrink-0 items-center justify-center rounded-full " +
|
||||
(streak > 0 ? "bg-orange-500/15" : "bg-muted")
|
||||
}
|
||||
>
|
||||
<StreakFlame className="size-7" muted={streak === 0} />
|
||||
</span>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="text-base font-semibold text-foreground leading-snug">
|
||||
{title}
|
||||
</p>
|
||||
<p className="truncate text-sm text-muted-foreground leading-snug">
|
||||
{subtitle}
|
||||
</p>
|
||||
</div>
|
||||
<ChevronRight className="size-5 shrink-0 text-muted-foreground transition-transform group-hover:translate-x-0.5 group-hover:text-foreground" />
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user