TypeScript 97.6%
SQL 1.4%
JavaScript 0.5%
1"use client";23import { useEffect, useState } from "react";4import { useSession } from "@/lib/store";5import { Sheet, Button } from "@/components/ui";6import { Clock } from "lucide-react";78/** Responsible-play reminder: "You've been playing for N minutes. Take a break anytime." */9export function SessionReminder() {10 const settings = useSession((s) => s.settings);11 const status = useSession((s) => s.status);12 const startedAt = useSession((s) => s.sessionStartedAt);13 const [shownFor, setShownFor] = useState<number | null>(null);14 const [open, setOpen] = useState(false);15 const interval = settings?.sessionReminderMinutes ?? 0;1617 useEffect(() => {18 if (status !== "authenticated" || !interval) return;19 const t = setInterval(() => {20 const minutes = Math.floor((Date.now() - startedAt) / 60_000);21 const step = Math.floor(minutes / interval) * interval;22 if (step > 0 && step !== shownFor) {23 setShownFor(step);24 setOpen(true);25 }26 }, 15_000);27 return () => clearInterval(t);28 }, [status, interval, startedAt, shownFor]);2930 return (31 <Sheet open={open} onClose={() => setOpen(false)} side="center" title="Time check">32 <div className="flex items-start gap-4">33 <div className="grid h-12 w-12 shrink-0 place-items-center rounded-full bg-accent-soft text-accent">34 <Clock className="h-6 w-6" />35 </div>36 <div>37 <p className="text-lg font-semibold tracking-tight">You've been playing for {shownFor} minutes.</p>38 <p className="mt-1 text-sm text-fg-2">Take a break anytime. Spinza credits are fictional and your progress is always saved.</p>39 </div>40 </div>41 <div className="mt-6 flex gap-3">42 <Button variant="secondary" className="flex-1" onClick={() => setOpen(false)}>43 Keep playing44 </Button>45 <Button className="flex-1" href="/" onClick={() => setOpen(false)}>46 Back to lobby47 </Button>48 </div>49 </Sheet>50 );51}52