import { useMemo, useRef, useState, type FormEvent } from "react"; import { useShellStore } from "../app/shellStore"; import { DUNGEON_REPORT_COMMENT_MAX_LENGTH, submitDungeonReport } from "../app/dungeonReports"; import { dungeonById } from "../game/dungeonCatalog"; import { useGameStore } from "../game/store"; import { useMenuController, type MenuAction } from "../input/useMenuController"; import { ControllerButton } from "./ControllerButton"; export function DungeonIssueReportPanel() { const dungeonId = useGameStore((state) => state.activeDungeonId); const openOverlay = useGameStore((state) => state.openOverlay); const session = useShellStore((state) => state.session); const [comment, setComment] = useState(""); const [submitting, setSubmitting] = useState(false); const [submitted, setSubmitted] = useState(false); const [error, setError] = useState(""); const busy = useRef(false); const form = useRef(null); const back = () => { if (!busy.current) openOverlay("pause"); }; const canSubmit = Boolean(comment.trim()) && comment.length <= DUNGEON_REPORT_COMMENT_MAX_LENGTH && !submitting; const actions = useMemo(() => [ { id: "report-back", run: back, enabled: !submitting }, { id: "report-submit", run: () => form.current?.requestSubmit(), enabled: canSubmit && !submitted }, ], [canSubmit, openOverlay, submitted, submitting]); const controller = useMenuController(actions, { initialId: "report-back", onBack: back }); const submit = async (event: FormEvent) => { event.preventDefault(); if (!canSubmit || busy.current || submitted) return; busy.current = true; setSubmitting(true); setError(""); try { await submitDungeonReport(session, dungeonId, comment); setSubmitted(true); } catch (failure) { setError(failure instanceof Error ? failure.message : "Your report could not be submitted. Please try again."); } finally { busy.current = false; setSubmitting(false); } }; return (

Dungeon feedback

Report an issue

{dungeonById(dungeonId)?.title ?? dungeonId}

{submitted ?

Report submitted. You can follow its status in View Reports on the main menu.

: (
void submit(event)}>