"use client"; import { useProgress } from "@bprogress/next"; import { Lock, Logs, Unlock } from "lucide-react"; import Link from "next/link"; import { useParams, useRouter } from "next/navigation"; import { useEffect, useRef, useState } from "react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { SidebarMenu, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, } from "@/components/ui/sidebar"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; import { shared } from "@/lib/comms"; import { sse } from "@/lib/db/sse-endpoints"; import { cn } from "@/lib/utils"; import { setFree, setLimit, toggleCheck, toggleLock } from "../api"; export function SidebarLink({ submission, className, prefetch = true, }: { submission: { id: string; name: string; checked: boolean; queue: number }; className?: string; prefetch?: boolean; }) { const { stop } = useProgress(); const { id } = useParams(); const [checked, setChecked] = useState(submission.checked); useEffect(() => { setChecked(submission.checked); }, [submission.checked]); return ( { if ((ev.target as HTMLButtonElement).type === "button") { ev.preventDefault(); } }} > {submission.queue}. {submission.name} { setChecked((x) => !x); await toggleCheck(submission.id); stop(); }} /> ); } export function LimitManager({ config, length, ...props }: React.ComponentProps & { config: Awaited>; length: number; }) { const [dialog, setDialog] = useState(1); return ( {config.locked ? ( <>

ปิดรับ

) : config.limit >= 0 && length > config.limit ? ( <>

เต็มแล้ว

) : ( <>

เปิดรับ

)}
{" "} จำนวน
{ e.preventDefault(); setDialog(1); }} > ตั้งจำกัดคิว { await toggleLock(); toast.success("บันทึกการเปลี่ยนแปลงแล้ว"); }} > {config.locked && "เ"}ปิดรับ { e.preventDefault(); setDialog(2); }} > ตั้งจำนวนคิวฟรี
{dialog === 1 ? ( ตั้งจำกัดคิว
{ await setLimit(Number(data.get("limit")) || -1); toast.success("บันทึกการเปลี่ยนแปลงแล้ว"); }} > = 0 ? config.limit : ""} autoFocus />
) : ( ตั้งจำนวนคิวฟรี
{ await setFree(Number(data.get("free")) || 0); toast.success("บันทึกการเปลี่ยนแปลงแล้ว"); }} > = 0 ? config.free : ""} autoFocus />
)}
{length} {config.limit >= 0 ? `/${config.limit}` : ""} {config.free > 0 ? ` (เหลือคิวฟรี ${config.free})` : ""}
); } export function SubmissionList({ subs, }: { subs: { id: string; name: string; checked: boolean; queue: number; publicQueue: number; paid: boolean; archived: boolean; }[]; }) { const [query, setQuery] = useState(""); const [debug] = shared.state("debug"); const bottomRef = useRef(null); useEffect(() => { void debug; // Scrolls to the dummy div whenever 'items' changes bottomRef.current?.scrollIntoView({ behavior: "smooth" }); }, [debug]); return ( <> setQuery(ev.target.value.toLowerCase())} /> {subs .filter( (s) => (debug || (s.paid && !s.archived)) && (s.queue + s.name).toLowerCase().includes(query), ) .map((s) => ( ))}
); } export function Watcher() { const router = useRouter(); const count = useRef(undefined); // Reload after connection restored shared.signal("sync", () => router.refresh()); useEffect(() => { const { clean } = sse.rubgram.sub("update", () => router.refresh()); const interval = setInterval(() => { fetch("/api/rubgram/count") .then((r) => r.json()) .then((r) => { if (typeof count.current === "undefined") count.current = r; if (count.current !== r) router.refresh(); count.current = r; }) .catch((e) => console.error("Fetching rubgram count failed", e)); }, 60000); return () => { clean(); clearInterval(interval); }; }, [router]); return
; } export function SlipButton() { return (

All time คิว

); }