import config from "@payload-config"; import { getPayload } from "payload"; import { notFound } from "next/navigation"; import Link from "next/link"; import type { Campaign, Faction, Mission } from "@/payload-types"; import { RichText } from "@payloadcms/richtext-lexical/react"; import { ArrowLeftIcon, CalendarDaysIcon, ChevronRightIcon, CrosshairIcon, ShieldIcon, TargetIcon, UsersIcon, } from "lucide-react"; import { Item, ItemContent, ItemDescription, ItemHeader, ItemTitle, } from "@/components/ui/item"; interface CampaignDetailPageProps { params: Promise<{ id: string }>; } 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 factionTypeColors: Record = { majorFaction: "bg-blue-500/20 text-blue-400", minorFaction: "bg-muted text-muted-foreground", corporation: "bg-amber-500/20 text-amber-400", special: "bg-purple-500/20 text-purple-400", }; const missionStatusColors: Record = { Concept: "bg-muted text-muted-foreground", Planning: "bg-muted text-muted-foreground", Ready: "bg-blue-500/20 text-blue-400", Scheduled: "bg-amber-500/20 text-amber-400", Active: "bg-green-500/20 text-green-400", Completed: "bg-emerald-500/20 text-emerald-400", Cancelled: "bg-red-500/20 text-red-400", }; export default async function CampaignDetailPage({ params, }: CampaignDetailPageProps) { const { id } = await params; const payload = await getPayload({ config }); const campaign = await payload .findByID({ collection: "campaigns", id: Number(id), depth: 0, }) .catch(() => null); if (!campaign) { notFound(); } const [missionsRes, factionsRes] = await Promise.all([ payload .find({ collection: "missions", where: { "classification.campaign": { equals: campaign.id } }, sort: "-classification.startDateTime", limit: 100, depth: 1, select: { name: true, codeName: true, summary: true, operationType: true, classification: true, ownershipAndStatus: true, missionRoles: true, }, }) .catch(() => ({ docs: [] })), payload.find({ collection: "factions", where: { associatedCampaigns: { equals: campaign.id } }, limit: 100, depth: 0, select: { name: true, type: true, description: true }, }), ]); const missions = missionsRes.docs as Mission[]; const factions = factionsRes.docs as Faction[]; const startDate = campaign.startDate ? new Date(campaign.startDate).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric", }) : null; const endDate = campaign.endDate ? new Date(campaign.endDate).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric", }) : null; // Mission status breakdown const statusCounts: Record = {}; for (const m of missions) { const s = m.ownershipAndStatus.status; statusCounts[s] = (statusCounts[s] ?? 0) + 1; } return (
Back to Campaigns

{campaign.name}

{campaign.status === "inProgress" ? "In Progress" : campaign.status.charAt(0).toUpperCase() + campaign.status.slice(1)} {startDate && ( {startDate} {endDate ? ` — ${endDate}` : " — Present"} )}

{campaign.summary}

{/* ── Main Content (2/3) ──────────────────────────── */}
{campaign.description && ( Description )}

Missions

{missions.length} mission{missions.length !== 1 ? "s" : ""}
{missions.length > 0 ? (
{missions.map((mission) => (
{mission.codeName} {mission.name}
{mission.ownershipAndStatus.status}
{mission.summary}
))}
) : (

No missions in this campaign yet.

)}
{/* ── Right Sidebar (1/3) ─────────────────────────── */}
{/* Campaign Stats */}
Campaign Stats
Total Missions {missions.length}
{Object.entries(statusCounts).map(([status, count]) => (
{status} {count}
))} {campaign.startDate && (
Duration {startDate} {endDate ? ` — ${endDate}` : " — Present"}
)}
{/* Faction Roster */} {factions.length > 0 && (
Faction Roster
View all
{factions.map((faction) => (
{faction.name} {faction.type === "majorFaction" ? "Major" : faction.type === "minorFaction" ? "Minor" : faction.type}
))}
)}
); }