"use client"; import Link from "next/link"; import type { Campaign } from "@/payload-types"; import { cn } from "@/lib/utils"; import { ClockIcon, CrosshairIcon, UsersIcon } from "lucide-react"; interface CampaignCardCampaign extends Pick< Campaign, "id" | "name" | "summary" | "status" | "startDate" | "endDate" > { readonly coverImageUrl: string | null; readonly missionCount: number; readonly completedMissions: number; readonly avgPlayers: number; readonly avgDurationMinutes: number; } type CampaignCardInput = CampaignCardCampaign | Campaign; interface CampaignCardProps { readonly campaign: CampaignCardInput; readonly size?: "lg" | "sm"; } const statusColors: Record = { concept: "bg-muted text-muted-foreground", inProgress: "bg-blue-500/20 text-blue-400", completed: "bg-emerald-500/20 text-emerald-400", }; const statusLabels: Record = { concept: "Concept", inProgress: "In Progress", completed: "Completed", }; const officialStatusLabels: Record = { concept: "Planning", inProgress: "Active Deployment", completed: "Concluded", }; const statusTextColors: Record = { concept: "text-muted-foreground", inProgress: "text-blue-400", completed: "text-emerald-400", }; export function CampaignCard({ campaign, size = "lg" }: CampaignCardProps) { const isSmall = size === "sm"; const coverImageUrl = "coverImageUrl" in campaign ? campaign.coverImageUrl : typeof campaign.coverImage === "object" && campaign.coverImage !== null ? (campaign.coverImage.url ?? null) : null; const missionCount = "missionCount" in campaign ? campaign.missionCount : 0; const completedMissions = "completedMissions" in campaign ? campaign.completedMissions : 0; const avgPlayers = "avgPlayers" in campaign ? campaign.avgPlayers : 0; const avgDurationMinutes = "avgDurationMinutes" in campaign ? campaign.avgDurationMinutes : 0; const roundedDuration = Math.round(avgDurationMinutes); const durationHours = Math.floor(roundedDuration / 60); const durationMinutes = roundedDuration % 60; const durationLabel = roundedDuration >= 60 ? `${durationHours}h ${durationMinutes}m` : `${roundedDuration}m`; const playersLabel = Number.isInteger(avgPlayers) ? avgPlayers.toString() : avgPlayers.toFixed(1); const owner = (campaign as any).owner; const ownerName = owner && typeof owner === "object" && "displayName" in owner ? owner.displayName : "Unknown"; const refCode = String(campaign.id).padStart(3, "0"); const statusLabel = isSmall ? statusLabels[campaign.status] : officialStatusLabels[campaign.status]; const readoutCells = [ { label: "Msns", value: missionCount.toString(), mono: true }, { label: "Done", value: completedMissions.toString(), mono: true }, { label: "Avg Squad", value: playersLabel, mono: true }, { label: "Duration", value: durationLabel, mono: true }, ]; return (
{coverImageUrl !== null ? ( <> {!isSmall && ( <> )} ) : (
); }