import config from "@payload-config"; import { getPayload } from "payload"; import { headers as nextHeaders } from "next/headers"; import type { Assignment, Campaign, GameStructure, Map, Media, Rank, User } from "@/payload-types"; import { resolveLevel } from "@/utils/xp/resolveLevel"; import { hasIntelligenceQualification } from "@/utils/access-control/hasIntelligenceQualification"; import { ProfileSummary } from "@/components/frontend/dashboard/ProfileSummary"; import { MissionBriefing } from "@/components/frontend/dashboard/MissionBriefing"; import { RecentEvents } from "@/components/frontend/dashboard/RecentEvents"; import { QuickStats } from "@/components/frontend/dashboard/QuickStats"; import { UpcomingMissions } from "@/components/frontend/dashboard/UpcomingMissions"; import { ActiveCampaigns } from "@/components/frontend/dashboard/ActiveCampaigns"; export default async function HomePage() { const payload = await getPayload({ config }); const headers = await nextHeaders(); const { user } = await payload.auth({ headers, canSetHeaders: false }); if (!user) return null; const userId = user.id; const hasIntelligence = await hasIntelligenceQualification(payload, user).catch(() => false); const [profileRes, experienceRes, assignmentRes] = await Promise.all([ payload.find({ collection: "profiles", where: { user: { equals: userId } }, depth: 2, select: { user: true, rank: true, progression: { xp: true, awards: true, scoreboard: true, minigames: true }, createdAt: true, }, }), payload.find({ collection: "experience", sort: "requiredPoints", limit: 100, select: { name: true, requiredPoints: true }, }), payload.find({ collection: "assignments", where: { members: { equals: userId } }, limit: 10, select: { name: true, type: true, callsign: true }, }), ]); const profile = profileRes.docs[0]; const xp = profile?.progression?.xp ?? 0; const xpLevel = resolveLevel(xp, experienceRes.docs); const profileUser = profile?.user as User | undefined; const rank = profile?.rank as Rank | undefined; const assignments = assignmentRes.docs as Pick[]; const rankData = rank ? { name: rank.name, abbreviation: rank.abbreviation, insigniaUrl: rank.insignia && typeof rank.insignia === "object" ? (rank.insignia as Media).url : null, } : { name: "Unknown", abbreviation: "?" }; // Fetch upcoming missions (Scheduled or Ready) — up to 5 for the sidebar const upcomingRes = await payload .find({ collection: "missions", where: { "ownershipAndStatus.status": { in: ["Scheduled", "Ready"] }, }, sort: "classification.startDateTime", limit: 5, depth: 2, }) .catch(() => ({ docs: [] })); // If no upcoming, get most recently completed for the briefing card let briefingMission = upcomingRes.docs[0] ?? null; if (!briefingMission) { const completedRes = await payload .find({ collection: "missions", where: { "ownershipAndStatus.status": { equals: "Completed" }, }, sort: "-classification.startDateTime", limit: 1, depth: 2, }) .catch(() => ({ docs: [] })); briefingMission = completedRes.docs[0] ?? null; } const mission = briefingMission ? { id: briefingMission.id, name: briefingMission.name, codeName: briefingMission.codeName, summary: briefingMission.summary, operationType: briefingMission.operationType, classification: { missionType: briefingMission.classification.missionType, startDateTime: briefingMission.classification.startDateTime, estimatedDuration: briefingMission.classification.estimatedDuration, map: briefingMission.classification.map as number | Map, campaign: briefingMission.classification.campaign as number | Campaign, }, ownershipAndStatus: { status: briefingMission.ownershipAndStatus.status, }, missionRoles: briefingMission.missionRoles ? { maxPlayers: briefingMission.missionRoles.maxPlayers } : null, coverImage: briefingMission.coverImage, } : null; const upcomingMissions = upcomingRes.docs.map((m) => ({ id: m.id, name: m.name, codeName: m.codeName, summary: m.summary, operationType: m.operationType, classification: { missionType: m.classification.missionType, startDateTime: m.classification.startDateTime, estimatedDuration: m.classification.estimatedDuration, map: m.classification.map as number | Map, campaign: m.classification.campaign as number | Campaign, }, ownershipAndStatus: { status: m.ownershipAndStatus.status, }, missionRoles: m.missionRoles ? { maxPlayers: m.missionRoles.maxPlayers } : null, coverImage: m.coverImage, })); // Fetch recent events const eventsRes = await payload.find({ collection: "game-event-logs", sort: "-timestamp", limit: 8, depth: 1, }); const events = eventsRes.docs.map((e) => ({ id: e.id, timestamp: e.timestamp, type: e.type, message: e.message, system: e.system ?? true, actor: e.actor as number | User | null | undefined, structure: e.structure as number | GameStructure | null | undefined, })); // Fetch active campaigns for the sidebar const activeCampaignsRes = await payload .find({ collection: "campaigns", where: { status: { equals: "inProgress" } }, limit: 5, sort: "-createdAt", }) .catch(() => ({ docs: [] })); const activeCampaigns = activeCampaignsRes.docs.map((c) => ({ id: c.id, name: c.name, summary: c.summary, status: c.status, })); // Fetch counts const [campaignsRes, missionsCountRes, structuresRes, factionsRes, profilesRes] = await Promise.all([ payload.find({ collection: "campaigns", where: { status: { equals: "inProgress" } }, limit: 0, }), payload .find({ collection: "missions", limit: 0, }) .catch(() => ({ totalDocs: 0 })), payload.find({ collection: "game-structures", limit: 0, }), payload.find({ collection: "factions", limit: 0, }), payload.find({ collection: "profiles", limit: 0, }), ]); return (

Welcome back, {rankData.name}. {/*{profileUser?.displayName ?? user.username}*/}

Here's your operations dashboard.

{/* ── Main Content (2/3) ──────────────────────────── */}
{profile && profileUser && ( )}
{/* ── Right Sidebar (1/3) ─────────────────────────── */}
{hasIntelligence && } {hasIntelligence && }
); }