"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { ExternalLink, Copy, Check, Trash2, Clock } from "lucide-react"; import { Button } from "@/components/ui/button"; import { useToast } from "@/components/ui/use-toast"; import { cn, formatRelativeDate } from "@/lib/utils"; interface ReviewSession { id: string; token: string; label: string | null; email: string | null; expiresAt: Date | string | null; accessCount: number; isActive: boolean; project: { name: string }; } interface ReviewSessionListProps { sessions: ReviewSession[]; } const APP_URL = process.env.NEXT_PUBLIC_APP_URL ?? ""; export function ReviewSessionList({ sessions }: ReviewSessionListProps) { const [copiedId, setCopiedId] = useState(null); const [deletingId, setDeletingId] = useState(null); const { toast } = useToast(); const router = useRouter(); const handleCopy = async (token: string, id: string) => { const url = `${APP_URL}/client/${token}`; await navigator.clipboard.writeText(url); setCopiedId(id); setTimeout(() => setCopiedId(null), 2000); }; const handleDeactivate = async (id: string) => { setDeletingId(id); try { const res = await fetch(`/api/review-sessions?id=${id}`, { method: "DELETE" }); if (!res.ok) throw new Error(); toast({ title: "Review link deactivated" }); router.refresh(); } catch { toast({ title: "Failed to deactivate link", variant: "destructive" }); } finally { setDeletingId(null); } }; if (sessions.length === 0) return null; return (

Active Review Links ({sessions.length})

{sessions.map((session) => { const portalUrl = `${APP_URL}/client/${session.token}`; const expired = session.expiresAt && new Date(session.expiresAt) < new Date(); return (

{session.label || "Untitled Review"}

{expired && ( Expired )}
{session.project.name} {session.email && ( <> · {session.email} )} {session.expiresAt && ( <> · {expired ? "Expired" : `Expires ${formatRelativeDate(session.expiresAt)}`} )}

{portalUrl}

{session.accessCount} view{session.accessCount !== 1 ? "s" : ""}
); })}
); }