1
0
Fork 0
polaris-task-force/src/app/(frontend)/map/[id]/page.tsx
Z8MB1E 9bbe44d38d feat(map): world map picker entry, intel fields, node icons, generic markers
- Maps gain worldMap flag, description, freeform weather, latitude/longitude,
  easeOfAccess and factionControl; picker cards render them as stat tags
- resource-nodes gain a shared icon set and may exist with no resources as
  plain marker nodes (placement ignores marker-only nodes)
- sidebar gains the World Map entry; Infrastructure section gets defaultOpen
- migrations 20260921_120000/123000/130500/134000; includes the generated
  types/schema sweep (currency emblem fields land in the next commit)
2026-09-21 20:47:46 -04:00

60 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import config from "@payload-config";
import { getPayload } from "payload";
import { headers } from "next/headers";
import { notFound } from "next/navigation";
import type { Metadata } from "next";
import { Map as MapIcon } from "lucide-react";
import { hasPermission } from "@/utils/access-control/hasPermission";
import { hasLogisticsQualification } from "@/utils/access-control/hasLogisticsQualification";
import { MapLoader } from "../MapLoader";
interface MapViewPageProps {
params: Promise<{ id: string }>;
}
export async function generateMetadata({ params }: MapViewPageProps): Promise<Metadata> {
const { id } = await params;
return { title: `World Map #${id}: Polaris Task Force` };
}
export default async function MapViewPage({ params }: MapViewPageProps) {
const { id } = await params;
const mapId = Number(id);
const payload = await getPayload({ config: await config });
const { user } = await payload.auth({ headers: await headers(), canSetHeaders: false });
const map = Number.isInteger(mapId)
? await payload
.findByID({ collection: "maps", id: mapId, depth: 0, overrideAccess: true })
.catch(() => null)
: null;
if (!map) notFound();
const [canEdit, canPlace] = await Promise.all([
user ? hasPermission(payload, user, "maps:update") : Promise.resolve(false),
user ? hasLogisticsQualification(payload, user) : Promise.resolve(false),
]);
// Inactive maps stay reachable for editors previewing them, but are hidden
// from everyone else.
if (!map.isActive && !canEdit) notFound();
return (
<div className="relative flex min-h-[240px] flex-1 flex-col">
<div className="flex items-center justify-between gap-3 border-b border-white/15 bg-black/50 px-5 py-2 backdrop-blur-sm">
<div className="flex items-center gap-2">
<MapIcon className="size-4 text-muted-foreground" />
<h1 className="text-sm font-semibold uppercase tracking-[0.2em]">{map.name}</h1>
</div>
<div className="flex items-center gap-4 font-mono text-[9px] uppercase tracking-[0.2em] text-white/60">
<span>PTF Unit Command // Tactical Grid</span>
<span>
{map.worldSizeWidth}×{map.worldSizeHeight} m
</span>
</div>
</div>
<MapLoader map={{ id: map.id, name: map.name }} canEdit={canEdit} canPlace={canPlace} />
</div>
);
}