import { useMemo } from "react"; import { enterRandomGmReview } from "../app/gmManastormRuntime"; import { useShellStore } from "../app/shellStore"; import { configWithGmReviewNote, configWithGmReviewStatus, describeGmReviewTarget, gmReviewQueue, } from "../game/gmContentReview"; import { GM_REVIEW_NOTE_MAX_LENGTH, isGameMasterSession, type GmReadinessStatus, } from "../game/manastormAdminConfig"; import { useManastormAdminStore } from "../game/manastormAdminStore"; import { useGameStore } from "../game/store"; const STATUS_LABELS: Readonly> = { ready: "Ready", "needs-tested": "Needs tested", "not-ready": "Not ready", }; const KIND_LABELS = { dungeon: "Dungeon review", boss: "Boss review", manastorm: "Manastorm review", } as const; export function GmReviewCard() { const session = useShellStore((state) => state.session); const target = useGameStore((state) => state.activeGmReviewTarget); const config = useManastormAdminStore((state) => state.config); const draft = useManastormAdminStore((state) => state.draft); const dirty = useManastormAdminStore((state) => state.dirty); const saving = useManastormAdminStore((state) => state.saving); const error = useManastormAdminStore((state) => state.error); const replaceDraft = useManastormAdminStore((state) => state.replaceDraft); const publish = useManastormAdminStore((state) => state.publish); const descriptor = useMemo( () => target ? describeGmReviewTarget(target, draft) : null, [draft, target], ); const nextCount = useMemo( () => target ? gmReviewQueue(target.kind, config, target).length : 0, [config, target], ); if (!target || !descriptor || !isGameMasterSession(session)) return null; const setStatus = (status: GmReadinessStatus) => { if (descriptor.status === status) return; const next = configWithGmReviewStatus(draft, target, status); if (next) replaceDraft(next); }; const setNote = (note: string) => { const next = configWithGmReviewNote(draft, target, note); if (next) replaceDraft(next); }; const targetKey = target.kind === "dungeon" ? target.dungeonId : target.bossKey; const notePreview = descriptor.note.replace(/\s+/g, " ").trim(); const reviewMetadata = descriptor.reviewedAt && descriptor.reviewedBy ? `${descriptor.reviewedBy} · ${new Date(descriptor.reviewedAt).toLocaleString()}` : null; return (
event.stopPropagation()} onClick={(event) => event.stopPropagation()} onKeyDown={(event) => event.stopPropagation()} onKeyUp={(event) => event.stopPropagation()} >
{KIND_LABELS[target.kind]} {dirty ? "Unsaved" : STATUS_LABELS[descriptor.status]}
{descriptor.name} {descriptor.dungeonTitle} · Map {descriptor.mapId}
{(["ready", "needs-tested", "not-ready"] as const).map((status) => ( ))}
Review note {notePreview || "Add context"}