import { renderEventWorkspaceMarkup } from "./event_views.js"; export function renderEventWorkspaceView(context) { const { mode, state, dom, t, escapeHtml, renderTable, renderRaceWizardStepsView, renderRaceWizardContentView, getRaceWizardDraft, setRaceWizardDraft, getRaceWizardStep, setRaceWizardStep, ensureRaceWizardDraft, getDriversForClass, getRaceWizardPreset, getSessionsForEvent, getClassName, getModeLabel, getSelectedEventEditId, setSelectedEventEditId, renderView, renderEventManager, uid, normalizeEvent, applyRaceFormatPreset, buildOpenPracticeBundle, buildRaceSessionsFromWizard, buildDefaultRaceWizardDraft, applyRaceWizardPresetDefaults, setSelectedTeamEditId, setSelectedSessionEditId, setFormError, bindModalShell, isValidIsoDate, saveState, purgeSessionPassings, openTimingSession, } = context; const isRaceMode = mode === "race"; if (isRaceMode) { ensureRaceWizardDraft(); } const filteredEvents = state.events.filter((event) => event.mode === mode); const editingEvent = filteredEvents.find((event) => event.id === getSelectedEventEditId()) || null; const raceWizardDraft = getRaceWizardDraft(); const raceWizardStep = getRaceWizardStep(); dom.view.innerHTML = renderEventWorkspaceMarkup(mode, { state, t, escapeHtml, renderTable, renderRaceWizardStepsView, renderRaceWizardContentView, raceWizardDraft, raceWizardStep, getDriversForClass, getRaceWizardPreset, getSessionsForEvent, getClassName, getModeLabel, editingEvent, }); document.getElementById("quickOpenPracticeForm")?.addEventListener("submit", (event) => { event.preventDefault(); const formNode = event.currentTarget; if (!(formNode instanceof HTMLFormElement)) { return; } const form = new FormData(formNode); const name = String(form.get("name") || "").trim() || t("events.quick_open_practice_default"); const bundle = buildOpenPracticeBundle({ name, date: new Date().toISOString().slice(0, 10) }); state.events.push(bundle.event); state.sessions.push(bundle.session); setSelectedTeamEditId(null); setSelectedSessionEditId(null); openTimingSession(bundle.session.id); }); if (isRaceMode) { const persistWizardStepOne = () => { const form = document.getElementById("raceWizardStepForm"); if (!(form instanceof HTMLFormElement)) { return true; } const data = new FormData(form); const nextName = String(data.get("name") || "").trim(); const nextDate = String(data.get("date") || "").trim(); const nextClassId = String(data.get("classId") || "").trim(); const nextPresetId = String(data.get("presetId") || "club_qualifying").trim() || "club_qualifying"; if (!nextName || !nextDate || !nextClassId) { return false; } const draft = getRaceWizardDraft(); const classChanged = draft.classId !== nextClassId; draft.name = nextName; draft.date = nextDate; draft.classId = nextClassId; if (classChanged) { draft.driverIds = getDriversForClass(nextClassId).map((driver) => driver.id); } if (draft.presetId !== nextPresetId) { applyRaceWizardPresetDefaults(draft, nextPresetId); } return true; }; const persistWizardParticipants = () => { const draft = getRaceWizardDraft(); draft.driverIds = Array.from(document.querySelectorAll(".wizard-participant:checked")).map((node) => node.value); return true; }; const persistWizardPlan = () => { const form = document.getElementById("raceWizardPlanForm"); if (!(form instanceof HTMLFormElement)) { return true; } const data = new FormData(form); const draft = getRaceWizardDraft(); draft.createPractice = data.get("createPractice") === "on"; draft.practiceSessions = Math.max(0, Number(data.get("practiceSessions") || 0) || 0); draft.createQualifying = data.get("createQualifying") === "on"; draft.qualifyingRounds = Math.max(0, Number(data.get("qualifyingRounds") || 0) || 0); draft.createTeamRace = data.get("createTeamRace") === "on"; draft.teamRaceDurationMin = Math.max(1, Number(data.get("teamRaceDurationMin") || 1) || 1); return draft.createPractice || draft.createQualifying || draft.createTeamRace; }; document.getElementById("raceWizardReset")?.addEventListener("click", () => { setRaceWizardDraft(applyRaceWizardPresetDefaults(buildDefaultRaceWizardDraft(), "club_qualifying")); setRaceWizardStep(1); renderView(); }); document.getElementById("raceWizardPrev")?.addEventListener("click", () => { if (getRaceWizardStep() === 2) { persistWizardParticipants(); } if (getRaceWizardStep() === 3) { persistWizardPlan(); } setRaceWizardStep(Math.max(1, getRaceWizardStep() - 1)); renderView(); }); document.getElementById("raceWizardNext")?.addEventListener("click", () => { let valid = true; if (getRaceWizardStep() === 1) { valid = persistWizardStepOne(); } else if (getRaceWizardStep() === 2) { valid = persistWizardParticipants(); } else if (getRaceWizardStep() === 3) { valid = persistWizardPlan(); } if (!valid) { return; } setRaceWizardStep(Math.min(4, getRaceWizardStep() + 1)); renderView(); }); const wizardBasicsForm = document.getElementById("raceWizardStepForm"); const syncWizardBasicsDraft = () => { if (!(wizardBasicsForm instanceof HTMLFormElement)) { return; } const data = new FormData(wizardBasicsForm); const draft = getRaceWizardDraft(); draft.name = String(data.get("name") || "").trim(); draft.date = String(data.get("date") || draft.date || "").trim(); }; wizardBasicsForm?.querySelector('[name="classId"]')?.addEventListener("change", (event) => { syncWizardBasicsDraft(); const nextClassId = String(event.currentTarget?.value || "").trim(); if (!nextClassId) { return; } const draft = getRaceWizardDraft(); const classChanged = draft.classId !== nextClassId; draft.classId = nextClassId; if (classChanged) { draft.driverIds = getDriversForClass(nextClassId).map((driver) => driver.id); } renderView(); }); wizardBasicsForm?.querySelector('[name="presetId"]')?.addEventListener("change", (event) => { syncWizardBasicsDraft(); const nextPresetId = String(event.currentTarget?.value || "club_qualifying").trim() || "club_qualifying"; applyRaceWizardPresetDefaults(getRaceWizardDraft(), nextPresetId); renderView(); }); const wizardPlanForm = document.getElementById("raceWizardPlanForm"); const toggleWizardPlanField = (toggleName, fieldName) => { const toggle = wizardPlanForm?.querySelector(`[name="${toggleName}"]`); const field = wizardPlanForm?.querySelector(`[name="${fieldName}"]`); if (!(toggle instanceof HTMLInputElement) || !(field instanceof HTMLInputElement)) { return; } const applyDisabledState = () => { field.disabled = !toggle.checked; }; applyDisabledState(); toggle.addEventListener("change", applyDisabledState); }; toggleWizardPlanField("createPractice", "practiceSessions"); toggleWizardPlanField("createQualifying", "qualifyingRounds"); toggleWizardPlanField("createTeamRace", "teamRaceDurationMin"); document.getElementById("wizardSelectAllParticipants")?.addEventListener("click", () => { const draft = getRaceWizardDraft(); draft.driverIds = getDriversForClass(draft.classId).map((driver) => driver.id); renderView(); }); document.getElementById("wizardClearParticipants")?.addEventListener("click", () => { getRaceWizardDraft().driverIds = []; renderView(); }); document.getElementById("raceWizardCreate")?.addEventListener("click", () => { const draft = getRaceWizardDraft(); const selectedDrivers = draft.driverIds.length ? draft.driverIds : getDriversForClass(draft.classId).map((driver) => driver.id); const event = normalizeEvent({ id: uid("event"), name: draft.name.trim(), date: draft.date, classId: draft.classId, mode, }); applyRaceFormatPreset(event, draft.presetId); event.raceConfig.driverIds = selectedDrivers; event.raceConfig.participantsConfigured = true; state.events.push(event); buildRaceSessionsFromWizard(event, draft).forEach((session) => state.sessions.push(session)); setSelectedTeamEditId(null); setSelectedSessionEditId(null); setRaceWizardDraft(applyRaceWizardPresetDefaults(buildDefaultRaceWizardDraft(), "club_qualifying")); setRaceWizardStep(1); saveState(); renderView(); renderEventManager(event.id); }); } else { document.getElementById("eventForm")?.addEventListener("submit", (e) => { e.preventDefault(); const form = new FormData(e.currentTarget); const event = { id: uid("event"), name: String(form.get("name")).trim(), date: String(form.get("date")), classId: String(form.get("classId")), mode, }; state.events.push(normalizeEvent(event)); saveState(); renderView(); }); } filteredEvents.forEach((e) => { document.getElementById(`event-edit-${e.id}`)?.addEventListener("click", () => { setSelectedEventEditId(e.id); renderView(); }); document.getElementById(`event-delete-${e.id}`)?.addEventListener("click", () => { const sessionIds = getSessionsForEvent(e.id).map((s) => s.id); state.events = state.events.filter((x) => x.id !== e.id); state.sessions = state.sessions.filter((x) => x.eventId !== e.id); sessionIds.forEach((id) => delete state.resultsBySession[id]); if (state.activeSessionId && sessionIds.includes(state.activeSessionId)) { state.activeSessionId = null; } saveState(); void purgeSessionPassings(sessionIds); renderView(); }); document.getElementById(`event-manage-${e.id}`)?.addEventListener("click", () => { renderEventManager(e.id); }); document.getElementById(`event-timing-${e.id}`)?.addEventListener("click", () => { const session = getSessionsForEvent(e.id).find((item) => item.type === "open_practice"); if (session) { openTimingSession(session.id); } }); }); document.getElementById("eventEditCancel")?.addEventListener("click", () => { setSelectedEventEditId(null); renderView(); }); document.getElementById("eventEditCancelFooter")?.addEventListener("click", () => { setSelectedEventEditId(null); renderView(); }); document.getElementById("eventEditModalOverlay")?.addEventListener("click", (event) => { if (event.target?.id === "eventEditModalOverlay") { setSelectedEventEditId(null); renderView(); } }); bindModalShell("eventEditModalOverlay", () => { setSelectedEventEditId(null); renderView(); }); const commitEventEdit = () => { if (!editingEvent) { return; } const formNode = document.getElementById("eventEditForm"); if (!(formNode instanceof HTMLFormElement)) { return; } const form = new FormData(formNode); const cleanedName = String(form.get("name") || "").trim(); const cleanedDate = String(form.get("date") || "").trim(); const cleanedClassId = String(form.get("classId") || "").trim(); if (!cleanedName) { setFormError("eventEditError", t("validation.required_name")); return; } if (!cleanedDate) { setFormError("eventEditError", t("validation.required_date")); return; } if (!isValidIsoDate(cleanedDate)) { setFormError("eventEditError", t("validation.invalid_date")); return; } if (cleanedClassId && !state.classes.some((item) => item.id === cleanedClassId)) { setFormError("eventEditError", t("validation.invalid_selection")); return; } setFormError("eventEditError", ""); state.events = state.events.map((item) => item.id === editingEvent.id ? normalizeEvent({ ...item, name: cleanedName, date: cleanedDate, classId: cleanedClassId || item.classId, }) : item ); setSelectedEventEditId(null); saveState(); renderView(); }; document.getElementById("eventEditForm")?.addEventListener("submit", (event) => { event.preventDefault(); commitEventEdit(); }); }