"use client"; import Link from "next/link"; import Image from "next/image"; import { useRouter } from "next/navigation"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { cn } from "@/lib/utils"; import { getInitials, formatRelativeDate } from "@/lib/utils"; import { MoreHorizontal, Film, MessageSquare, Clock, CheckCircle2, AlertCircle, ArrowUpRight, } from "lucide-react"; import type { ShotWithDetails } from "@/types"; interface ShotCardProps { shot: ShotWithDetails; projectId: string; compact?: boolean; } const STATUS_CONFIG: Record< string, { label: string; color: string; icon: React.ElementType } > = { WAITING: { label: "Waiting", color: "bg-zinc-500/10 text-zinc-400 border-zinc-500/20", icon: Clock }, IN_PROGRESS: { label: "In Progress", color: "bg-blue-500/10 text-blue-400 border-blue-500/20", icon: Film }, IN_REVIEW: { label: "In Review", color: "bg-purple-500/10 text-purple-400 border-purple-500/20", icon: AlertCircle }, REVISIONS: { label: "Revisions", color: "bg-orange-500/10 text-orange-400 border-orange-500/20", icon: AlertCircle }, COMPLETE: { label: "Complete", color: "bg-emerald-500/10 text-emerald-400 border-emerald-500/20", icon: CheckCircle2 }, }; const PRIORITY_DOT: Record = { LOW: "bg-zinc-500", NORMAL: "bg-blue-500", HIGH: "bg-amber-500", URGENT: "bg-red-500", }; export function ShotCard({ shot, projectId, compact = false }: ShotCardProps) { const router = useRouter(); const statusCfg = STATUS_CONFIG[shot.status] ?? STATUS_CONFIG.WAITING; const StatusIcon = statusCfg.icon; const latestVersion = shot.versions?.[0]; const openComments = shot.versions ?.reduce((sum, v) => sum + (v._count?.comments ?? 0), 0) ?? 0; if (compact) { return (
{shot.shotCode} {shot.sequence && ( {shot.sequence} )}
{shot.description && (

{shot.description}

)}
{statusCfg.label}
); } return ( {/* Thumbnail with cinema scope aspect ratio (2.39:1) */}
{shot.thumbnailUrl || latestVersion?.thumbnailUrl || latestVersion?.posterUrl ? ( {shot.shotCode} ) : (

{shot.shotCode}

)}
{/* Header info */}
{shot.shotCode} {shot.sequence && ( {shot.sequence} )}
{statusCfg.label} View shot
{shot.description && (

{shot.description}

)} {/* Stats row */}
{shot.versions?.length ?? 0} version{(shot.versions?.length ?? 0) !== 1 ? "s" : ""} {openComments > 0 && ( {openComments} open )} {shot.dueDate && ( {formatRelativeDate(shot.dueDate)} )}
{/* Artist avatar */} {shot.artist ? (
{shot.artist.image && } {getInitials(shot.artist.name)} {shot.artist.name ?? shot.artist.email}
) : ( Unassigned )}
); }