import config from "@payload-config"; import { getPayload } from "payload"; import { headers as nextHeaders } from "next/headers"; import { FridayCalendar, type FridayCalendarEntry, type FridayCalendarMission, } from "@/components/frontend/intelligence/FridayCalendar"; import type { SideOpDialogOption } from "@/components/frontend/intelligence/CreateSideOpDialog"; import { dateKeyOf, nextDayKey, parseDateKey, wallTimeToInstant, zonedDateKey, } from "@/lib/intelligence/fridayTime"; export const metadata = { title: "Friday Operations", }; const MAX_SCHEDULED_AHEAD_MISSIONS = 2; const FRIDAYS_SHOWN = 8; function nextFridays(count: number): string[] { const fridays: string[] = []; const cursor = zonedDateKey(new Date()); const [y, m, d] = cursor.split("-").map(Number); const utc = new Date(Date.UTC(y, m - 1, d)); while (fridays.length < count) { if (utc.getUTCDay() === 5) { fridays.push(dateKeyOf(utc.getUTCFullYear(), utc.getUTCMonth() + 1, utc.getUTCDate())); } utc.setUTCDate(utc.getUTCDate() + 1); } return fridays; } export default async function FridayCalendarPage() { const payload = await getPayload({ config }); const { user } = await payload.auth({ headers: await nextHeaders(), canSetHeaders: false, }); const fridays = nextFridays(FRIDAYS_SHOWN); const first = parseDateKey(fridays[0]); const last = parseDateKey(nextDayKey(fridays[fridays.length - 1])); const rangeStart = wallTimeToInstant(first.year, first.month, first.day); const rangeEnd = wallTimeToInstant(last.year, last.month, last.day); const missionsRes = await payload.find({ collection: "missions", where: { "classification.startDateTime": { greater_than_equal: rangeStart.toISOString(), less_than: rangeEnd.toISOString(), }, }, sort: "classification.startDateTime", depth: 1, limit: 200, user, overrideAccess: false, select: { name: true, codeName: true, operationType: true, ownershipAndStatus: { status: true }, classification: { startDateTime: true, map: true }, createdBy: true, }, }); const entries: FridayCalendarEntry[] = fridays.map((fridayKey) => { const missions: FridayCalendarMission[] = missionsRes.docs .filter((m) => zonedDateKey(new Date(m.classification.startDateTime)) === fridayKey) .map((m) => { const map = m.classification.map; const createdBy = m.createdBy; const creator = typeof createdBy === "object" && createdBy !== null ? (createdBy as { displayName?: string | null; username?: string | null }) : null; return { id: m.id, name: m.name, codeName: m.codeName, status: m.ownershipAndStatus.status, startDateTime: m.classification.startDateTime, operationType: m.operationType, mapName: typeof map === "object" && map !== null ? map.name : null, hostName: creator != null ? (creator.displayName ?? creator.username ?? null) : null, isOwn: user != null && (typeof createdBy === "object" ? createdBy?.id : createdBy) === user.id, }; }); const k = parseDateKey(fridayKey); return { fridayIso: fridayKey, startIso: wallTimeToInstant(k.year, k.month, k.day, 20, 0).toISOString(), missions, }; }); let remainingSlots = 0; let maps: SideOpDialogOption[] = []; let campaigns: SideOpDialogOption[] = []; let modLists: SideOpDialogOption[] = []; if (user) { const userId = user.id as number; const [scheduledCount, mapsRes, campaignsRes, modListsRes] = await Promise.all([ payload.count({ collection: "missions", where: { and: [ { createdBy: { equals: userId } }, { "classification.startDateTime": { greater_than: new Date().toISOString() } }, { "ownershipAndStatus.status": { not_in: ["Completed", "Cancelled"] } }, ], }, }), payload.find({ collection: "maps", overrideAccess: true, depth: 0, limit: 200, sort: "name", select: { name: true }, }), payload.find({ collection: "campaigns", where: { owner: { equals: userId } }, depth: 0, limit: 100, sort: "name", select: { name: true }, }), payload.find({ collection: "mod-lists", overrideAccess: true, depth: 0, limit: 200, sort: "modlistName", select: { modlistName: true }, }), ]); remainingSlots = Math.max(0, MAX_SCHEDULED_AHEAD_MISSIONS - scheduledCount.totalDocs); maps = mapsRes.docs.map((m) => ({ id: m.id, name: m.name })); campaigns = campaignsRes.docs.map((c) => ({ id: c.id, name: c.name })); modLists = modListsRes.docs.map((l) => ({ id: l.id, name: l.modlistName })); } return (
); }