export function renderEventManagerView(context) { const { eventId, state, t, escapeHtml, normalizeEvent, ensureRaceParticipantsConfigured, getSessionsForEvent, getSelectedTeamEditId, setSelectedTeamEditId, getSelectedSessionEditId, setSelectedSessionEditId, getSelectedGridSessionId, setSelectedGridSessionId, getRaceFormatAdvanced, setRaceFormatAdvanced, getTeamDriverPool, getEventTeams, normalizeBrandingConfig, getSessionTypeChoices, getRaceFormatPresets, getRaceSummaryItems, getRaceSummaryWarnings, getRaceManageStatuses, normalizeStartMode, renderEventManagerMarkup, getSessionEntrants, getSessionTypeLabel, getStartModeLabel, getStatusLabel, renderManageStatusBadgeView, getDriverDisplayById, renderRaceFormatContextCardView, renderRaceFormatFieldView, renderGridEditor, renderRaceStandingsTableView, buildPracticeStandings, buildQualifyingStandings, buildFinalStandings, renderTeamRaceStandings, renderFinalMatrix, getModeLabel, renderTable, bindModalShell, setFormError, saveState, renderView, rerenderEventManager, updateHeaderState, uid, normalizeSession, buildSessionHeatSheetHtml, openPrintWindow, exportSessionHeatSheet, exportSessionHeatSheetPdf, getSelectedAssignmentSessionId, autoAssignTrackSession, renderAssignmentList, normalizeRaceTeam, buildRaceFormatConfigFromForm, applyRaceFormatPreset, normalizeStoredRacePreset, generateQualifyingForRace, clearGeneratedQualifying, reseedUpcomingQualifying, generateFinalsForRace, clearGeneratedFinals, applyBumpsForRace, buildRacePackagePayload, downloadJsonFile, sanitizeFilenameSegment, importRacePackagePayload, buildRaceStartListsHtml, buildRaceResultsHtml, buildTeamRaceResultsHtml, exportRaceStartListsPdf, exportRaceResultsPdf, exportTeamRaceResultsPdf, ensureSessionDriverOrder, reorderList, getEventName, } = context; const selectedTeamEditId = getSelectedTeamEditId(); const selectedSessionEditId = getSelectedSessionEditId(); const selectedGridSessionId = getSelectedGridSessionId(); const raceFormatAdvanced = getRaceFormatAdvanced(); const event = state.events.find((e) => e.id === eventId); if (!event) { return; } const normalizedEvent = normalizeEvent(event); if (normalizedEvent !== event) { Object.assign(event, normalizedEvent); } ensureRaceParticipantsConfigured(event); const sessions = getSessionsForEvent(eventId); const eventManageArea = document.getElementById("eventManageArea"); if (!eventManageArea) { return; } const driverOptions = state.drivers .map((d) => ``) .join(""); const teamDriverPool = event.mode === "race" ? getTeamDriverPool(event) : { drivers: [], fallback: false }; const raceDrivers = event.mode === "race" ? teamDriverPool.drivers : []; const raceTeams = event.mode === "race" ? getEventTeams(event) : []; if (selectedTeamEditId && !raceTeams.some((team) => team.id === selectedTeamEditId)) { setSelectedTeamEditId(null); } const editingTeam = event.mode === "race" ? raceTeams.find((team) => team.id === selectedTeamEditId) || null : null; const carOptions = state.cars .map((c) => ``) .join(""); const branding = normalizeBrandingConfig(event.branding); const editingSession = sessions.find((session) => session.id === selectedSessionEditId) || null; const sessionTypeChoices = getSessionTypeChoices(event.mode); const sessionTypeHintKey = event.mode === "track" ? "events.session_type_hint_track" : "events.session_type_hint_race"; const racePresets = getRaceFormatPresets(); const selectedPreset = racePresets.find((preset) => preset.id === event.raceConfig.presetId) || racePresets[0]; const isEndurancePreset = event.mode === "race" && selectedPreset?.id === "endurance"; const showTeamsSection = event.mode === "race" && (sessions.some((session) => session.type === "team_race") || raceTeams.length > 0 || Boolean(selectedTeamEditId)); const showBasicQualifyingFields = raceFormatAdvanced || !isEndurancePreset; const showBasicFinalFields = raceFormatAdvanced || !isEndurancePreset; const selectedParticipantCount = event.mode === "race" ? (event.raceConfig.participantsConfigured ? (event.raceConfig.driverIds || []).length : raceDrivers.length) : 0; const raceSummaryItems = event.mode === "race" ? getRaceSummaryItems(event, sessions, raceDrivers, selectedPreset, { t, getStartModeLabel }) : []; const raceSummaryWarnings = event.mode === "race" ? getRaceSummaryWarnings(event, sessions, raceDrivers, raceTeams, selectedPreset, { t }) : []; const manageStatuses = event.mode === "race" ? getRaceManageStatuses(event, sessions, raceDrivers, raceTeams, selectedPreset) : null; const gridSessions = event.mode === "race" ? sessions.filter((session) => normalizeStartMode(session.startMode) === "position") : []; if (selectedGridSessionId && !gridSessions.some((session) => session.id === selectedGridSessionId)) { setSelectedGridSessionId(""); } const selectedGridSession = gridSessions.find((session) => session.id === selectedGridSessionId) || gridSessions[0] || null; if (!selectedGridSessionId && selectedGridSession) { setSelectedGridSessionId(selectedGridSession.id); } eventManageArea.innerHTML = renderEventManagerMarkup({ event, t, escapeHtml, sessions, sessionTypeChoices, sessionTypeHintKey, raceTeams, getSessionEntrants, getSessionTypeLabel, getStartModeLabel, getStatusLabel, normalizeStartMode, branding, driverOptions, carOptions, manageStatuses, renderManageStatusBadgeView, selectedParticipantCount, raceDrivers, teamDriverPool, showTeamsSection, state, getDriverDisplayById, raceFormatAdvanced, racePresets, selectedPreset, isEndurancePreset, showBasicQualifyingFields, showBasicFinalFields, renderRaceFormatContextCardView, renderRaceFormatFieldView, raceSummaryWarnings, raceSummaryItems, selectedGridSession, renderGridEditor, renderRaceStandingsTableView, buildPracticeStandings, buildQualifyingStandings, buildFinalStandings, renderTeamRaceStandings, renderFinalMatrix, editingTeam, editingSession, getModeLabel, renderTable, }); const bindManageJump = (node) => { const triggerJump = () => { const targetId = node.getAttribute("data-target") || ""; const target = targetId ? document.getElementById(targetId) : null; if (target) { target.scrollIntoView({ behavior: "smooth", block: "start" }); } }; node.addEventListener("click", triggerJump); node.addEventListener("keydown", (event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); triggerJump(); } }); }; eventManageArea.querySelectorAll(".summary-warning-link, .manage-step-card-link").forEach((node) => { bindManageJump(node); }); const refreshManager = () => { renderView(); rerenderEventManager(eventId); }; document.getElementById("eventBrandingForm")?.addEventListener("submit", (e) => { e.preventDefault(); const form = new FormData(e.currentTarget); event.branding = normalizeBrandingConfig({ ...event.branding, brandName: String(form.get("brandName") || "").trim(), brandTagline: String(form.get("brandTagline") || "").trim(), pdfFooter: String(form.get("pdfFooter") || "").trim(), pdfTheme: String(form.get("pdfTheme") || "").trim(), }); saveState(); rerenderEventManager(eventId); }); document.getElementById("eventLogoUpload")?.addEventListener("change", (eventInput) => { const input = eventInput.currentTarget; const file = input instanceof HTMLInputElement ? input.files?.[0] : null; if (!file) { return; } const reader = new FileReader(); reader.onload = () => { event.branding = normalizeBrandingConfig({ ...event.branding, logoDataUrl: typeof reader.result === "string" ? reader.result : "", }); saveState(); rerenderEventManager(eventId); }; reader.readAsDataURL(file); }); document.getElementById("eventLogoClear")?.addEventListener("click", () => { event.branding = normalizeBrandingConfig({ ...event.branding, logoDataUrl: "", }); saveState(); rerenderEventManager(eventId); }); document.getElementById("sessionForm")?.addEventListener("submit", (e) => { e.preventDefault(); const formNode = e.currentTarget; if (!(formNode instanceof HTMLFormElement)) { return; } const form = new FormData(formNode); const typeField = formNode.querySelector('[name="type"]'); const selectedType = typeField instanceof HTMLSelectElement ? typeField.value : String(form.get("type") || ""); state.sessions.push(normalizeSession({ id: uid("session"), eventId, name: String(form.get("name")).trim(), type: selectedType, durationMin: Number(form.get("durationMin")), followUpSec: Math.max(0, Number(form.get("followUpSec") || 0) || 0), startMode: String(form.get("startMode") || "mass"), seedBestLapCount: Math.max(0, Number(form.get("seedBestLapCount") || 0) || 0), seedMethod: String(form.get("seedMethod") || "best_sum"), staggerGapSec: Math.max(0, Number(form.get("staggerGapSec") || 0) || 0), maxCars: Number(form.get("maxCars") || 0) || null, mode: event.mode, status: "ready", startedAt: null, endedAt: null, finishedByTimer: false, assignments: [], })); saveState(); refreshManager(); updateHeaderState(); }); sessions.forEach((s) => { document.getElementById(`session-edit-${s.id}`)?.addEventListener("click", () => { setSelectedSessionEditId(s.id); rerenderEventManager(eventId); }); document.getElementById(`session-active-${s.id}`)?.addEventListener("click", () => { state.activeSessionId = s.id; saveState(); updateHeaderState(); renderView(); }); document.getElementById(`session-delete-${s.id}`)?.addEventListener("click", () => { state.sessions = state.sessions.filter((x) => x.id !== s.id); delete state.resultsBySession[s.id]; if (state.activeSessionId === s.id) { state.activeSessionId = null; } saveState(); refreshManager(); updateHeaderState(); }); document.getElementById(`session-grid-${s.id}`)?.addEventListener("click", () => { ensureSessionDriverOrder(s); setSelectedGridSessionId(s.id); saveState(); refreshManager(); }); document.getElementById(`session-sheet-print-${s.id}`)?.addEventListener("click", () => { openPrintWindow(`${getEventName(eventId)} - ${s.name}`, buildSessionHeatSheetHtml(s)); }); document.getElementById(`session-sheet-export-${s.id}`)?.addEventListener("click", () => { exportSessionHeatSheet(s); }); document.getElementById(`session-sheet-pdf-${s.id}`)?.addEventListener("click", async () => { await exportSessionHeatSheetPdf(s); }); }); document.getElementById("sessionEditCancel")?.addEventListener("click", () => { setSelectedSessionEditId(null); refreshManager(); }); document.getElementById("sessionEditCancelFooter")?.addEventListener("click", () => { setSelectedSessionEditId(null); refreshManager(); }); document.getElementById("sessionEditModalOverlay")?.addEventListener("click", (event) => { if (event.target?.id === "sessionEditModalOverlay") { setSelectedSessionEditId(null); refreshManager(); } }); bindModalShell("sessionEditModalOverlay", () => { setSelectedSessionEditId(null); refreshManager(); }); document.getElementById("sessionEditForm")?.addEventListener("submit", (event) => { event.preventDefault(); if (!editingSession) { return; } const formNode = event.currentTarget; if (!(formNode instanceof HTMLFormElement)) { return; } const form = new FormData(formNode); const typeField = formNode.querySelector('[name="type"]'); const selectedType = typeField instanceof HTMLSelectElement ? typeField.value : String(form.get("type") || editingSession.type); const cleanedName = String(form.get("name") || "").trim(); const cleanedDuration = Number(form.get("durationMin") || editingSession.durationMin || 5) || 0; if (!cleanedName) { setFormError("sessionEditError", t("validation.required_name")); return; } if (cleanedDuration < 1) { setFormError("sessionEditError", t("validation.required_duration")); return; } setFormError("sessionEditError", ""); editingSession.name = cleanedName; editingSession.type = selectedType; editingSession.durationMin = Math.max(1, cleanedDuration); editingSession.followUpSec = Math.max(0, Number(form.get("followUpSec") || 0) || 0); editingSession.startMode = normalizeStartMode(String(form.get("startMode") || editingSession.startMode || "mass")); editingSession.seedBestLapCount = Math.max(0, Number(form.get("seedBestLapCount") || 0) || 0); editingSession.seedMethod = ["best_sum", "average", "consecutive"].includes(String(form.get("seedMethod") || "").toLowerCase()) ? String(form.get("seedMethod")).toLowerCase() : "best_sum"; editingSession.staggerGapSec = Math.max(0, Number(form.get("staggerGapSec") || 0) || 0); editingSession.maxCars = Number(form.get("maxCars") || 0) || null; setSelectedSessionEditId(null); saveState(); refreshManager(); }); if (event.mode === "track") { document.getElementById("sponsorRoundsForm")?.addEventListener("submit", (e) => { e.preventDefault(); const form = new FormData(e.currentTarget); const qualificationRounds = Number(form.get("qualificationRounds") || 0); const heatRounds = Number(form.get("heatRounds") || 0); const finalRounds = Number(form.get("finalRounds") || 0); const durationMin = Number(form.get("roundDuration") || 5); createSponsorRounds(eventId, { qualificationRounds, heatRounds, finalRounds, durationMin, }); saveState(); rerenderEventManager(eventId); }); document.getElementById("assignForm")?.addEventListener("submit", (e) => { e.preventDefault(); const form = new FormData(e.currentTarget); const sessionId = String(form.get("sessionId")); const session = state.sessions.find((x) => x.id === sessionId); if (!session) { return; } const driverId = String(form.get("driverId")); const carId = String(form.get("carId")); const car = state.cars.find((x) => x.id === carId); if (!car) { return; } const duplicateCar = (session.assignments || []).find((a) => a.carId === carId); if (duplicateCar) { alert(t("events.duplicate_car")); return; } const duplicateDriver = (session.assignments || []).find((a) => a.driverId === driverId); if (duplicateDriver) { alert(t("events.duplicate_driver")); return; } const duplicateTp = (session.assignments || []).find((a) => { const existingCar = state.cars.find((x) => x.id === a.carId); return existingCar?.transponder && existingCar.transponder === car.transponder; }); if (duplicateTp) { alert(t("events.duplicate_tp")); return; } session.assignments = session.assignments || []; session.assignments.push({ id: uid("as"), driverId, carId }); saveState(); rerenderEventManager(eventId); }); document.getElementById("autoAssignSession")?.addEventListener("click", () => { const sessionId = getSelectedAssignmentSessionId(); if (!sessionId) { return; } autoAssignTrackSession(event, sessionId); saveState(); rerenderEventManager(eventId); }); document.getElementById("clearAssignSession")?.addEventListener("click", () => { const sessionId = getSelectedAssignmentSessionId(); if (!sessionId) { return; } const session = state.sessions.find((x) => x.id === sessionId); if (!session) { return; } session.assignments = []; saveState(); rerenderEventManager(eventId); }); renderAssignmentList(eventId); } if (event.mode === "race") { const persistRaceParticipants = () => { const selectedIds = Array.from(document.querySelectorAll(".race-participant:checked")).map((node) => node.value); event.raceConfig.driverIds = selectedIds; event.raceConfig.participantsConfigured = true; saveState(); }; document.querySelectorAll(".race-participant").forEach((node) => { node.addEventListener("change", persistRaceParticipants); }); document.getElementById("selectAllParticipants")?.addEventListener("click", () => { document.querySelectorAll(".race-participant").forEach((node) => { node.checked = true; }); persistRaceParticipants(); }); document.getElementById("clearParticipants")?.addEventListener("click", () => { document.querySelectorAll(".race-participant").forEach((node) => { node.checked = false; }); persistRaceParticipants(); }); if (showTeamsSection) { document.getElementById("teamForm")?.addEventListener("submit", (e) => { e.preventDefault(); const formNode = e.currentTarget; if (!(formNode instanceof HTMLFormElement)) { return; } const form = new FormData(formNode); const name = String(form.get("teamName") || "").trim(); const driverIds = Array.from(document.querySelectorAll('[form="teamForm"][name="teamDriverIds"]:checked')) .map((node) => String(node.value)) .filter(Boolean); const carIds = Array.from(document.querySelectorAll('[form="teamForm"][name="teamCarIds"]:checked')) .map((node) => String(node.value)) .filter(Boolean); if (!name) { setFormError("teamCreateError", t("validation.required_name")); return; } if (!driverIds.length && !carIds.length) { setFormError("teamCreateError", t("validation.invalid_selection")); return; } setFormError("teamCreateError", ""); const createdTeam = normalizeRaceTeam({ id: uid("team"), name, driverIds, carIds }); event.raceConfig.teams = [...getEventTeams(event), createdTeam]; setSelectedTeamEditId(null); saveState(); refreshManager(); }); raceTeams.forEach((team) => { document.getElementById(`team-edit-${team.id}`)?.addEventListener("click", () => { setSelectedTeamEditId(team.id); refreshManager(); }); document.getElementById(`team-delete-${team.id}`)?.addEventListener("click", () => { event.raceConfig.teams = getEventTeams(event).filter((item) => item.id !== team.id); if (getSelectedTeamEditId() === team.id) { setSelectedTeamEditId(null); } saveState(); refreshManager(); }); }); document.getElementById("teamEditCancel")?.addEventListener("click", () => { setSelectedTeamEditId(null); refreshManager(); }); document.getElementById("teamEditCancelFooter")?.addEventListener("click", () => { setSelectedTeamEditId(null); refreshManager(); }); document.getElementById("teamEditModalOverlay")?.addEventListener("click", (modalEvent) => { if (modalEvent.target?.id === "teamEditModalOverlay") { setSelectedTeamEditId(null); refreshManager(); } }); bindModalShell("teamEditModalOverlay", () => { setSelectedTeamEditId(null); refreshManager(); }); document.getElementById("teamEditForm")?.addEventListener("submit", (submitEvent) => { submitEvent.preventDefault(); if (!editingTeam) { return; } const formNode = submitEvent.currentTarget; if (!(formNode instanceof HTMLFormElement)) { return; } const form = new FormData(formNode); const name = String(form.get("teamName") || "").trim(); const driverIds = Array.from(formNode.querySelectorAll('[name="teamDriverIds"]:checked')) .map((node) => String(node.value)) .filter(Boolean); const carIds = Array.from(formNode.querySelectorAll('[name="teamCarIds"]:checked')) .map((node) => String(node.value)) .filter(Boolean); if (!name) { setFormError("teamEditError", t("validation.required_name")); return; } if (!driverIds.length && !carIds.length) { setFormError("teamEditError", t("validation.invalid_selection")); return; } setFormError("teamEditError", ""); event.raceConfig.teams = getEventTeams(event).map((team) => team.id === editingTeam.id ? normalizeRaceTeam({ ...team, name, driverIds, carIds }) : team ); setSelectedTeamEditId(null); saveState(); refreshManager(); }); } document.getElementById("raceFormatBasicToggle")?.addEventListener("click", () => { setRaceFormatAdvanced(false); rerenderEventManager(eventId); }); document.getElementById("raceFormatAdvancedToggle")?.addEventListener("click", () => { setRaceFormatAdvanced(true); rerenderEventManager(eventId); }); document.getElementById("raceFormatForm")?.addEventListener("submit", (e) => { e.preventDefault(); const form = new FormData(e.currentTarget); event.raceConfig = buildRaceFormatConfigFromForm(form, event); saveState(); rerenderEventManager(eventId); }); document.getElementById("applyRacePreset")?.addEventListener("click", () => { const formElement = document.getElementById("raceFormatForm"); if (!(formElement instanceof HTMLFormElement)) { return; } const form = new FormData(formElement); applyRaceFormatPreset(event, String(form.get("presetId") || "custom")); saveState(); rerenderEventManager(eventId); }); document.getElementById("saveRacePreset")?.addEventListener("click", () => { const formElement = document.getElementById("raceFormatForm"); if (!(formElement instanceof HTMLFormElement)) { return; } const form = new FormData(formElement); const presetName = String(form.get("presetName") || "").trim(); if (!presetName) { return; } const config = buildRaceFormatConfigFromForm(form, event); const selectedPresetId = String(form.get("presetId") || "custom"); const existingCustomPreset = (state.settings.racePresets || []).find((preset) => preset.id === selectedPresetId); const presetId = existingCustomPreset ? existingCustomPreset.id : uid("preset"); const storedPreset = normalizeStoredRacePreset({ id: presetId, name: presetName, values: { qualifyingScoring: config.qualifyingScoring, qualifyingRounds: config.qualifyingRounds, carsPerHeat: config.carsPerHeat, qualDurationMin: config.qualDurationMin, qualStartMode: config.qualStartMode, qualSeedLapCount: config.qualSeedLapCount, qualSeedMethod: config.qualSeedMethod, countedQualRounds: config.countedQualRounds, qualifyingPointsTable: config.qualifyingPointsTable, qualifyingTieBreak: config.qualifyingTieBreak, carsPerFinal: config.carsPerFinal, finalLegs: config.finalLegs, countedFinalLegs: config.countedFinalLegs, finalDurationMin: config.finalDurationMin, finalStartMode: config.finalStartMode, followUpSec: config.followUpSec, minLapMs: config.minLapMs, maxLapMs: config.maxLapMs, bumpCount: config.bumpCount, reserveBumpSlots: config.reserveBumpSlots, finalsSource: config.finalsSource, }, }); const otherPresets = (state.settings.racePresets || []).filter((preset) => preset.id !== presetId); state.settings.racePresets = [...otherPresets, storedPreset]; event.raceConfig = { ...config, presetId }; saveState(); rerenderEventManager(eventId); }); document.getElementById("deleteRacePreset")?.addEventListener("click", () => { const formElement = document.getElementById("raceFormatForm"); if (!(formElement instanceof HTMLFormElement)) { return; } const form = new FormData(formElement); const presetId = String(form.get("presetId") || "custom"); if (!(state.settings.racePresets || []).some((preset) => preset.id === presetId)) { return; } state.settings.racePresets = (state.settings.racePresets || []).filter((preset) => preset.id !== presetId); event.raceConfig.presetId = "custom"; saveState(); rerenderEventManager(eventId); }); document.getElementById("generateQualifying")?.addEventListener("click", () => { const created = generateQualifyingForRace(event); saveState(); rerenderEventManager(eventId); if (created > 0) { alert(t("events.generated_qualifying")); } }); document.getElementById("clearGeneratedQualifying")?.addEventListener("click", () => { clearGeneratedQualifying(event.id); saveState(); rerenderEventManager(eventId); }); document.getElementById("reseedQualifying")?.addEventListener("click", () => { const result = reseedUpcomingQualifying(event); saveState(); rerenderEventManager(eventId); const messages = []; if (result.updated > 0) { messages.push(t("events.reseed_done")); } else { messages.push(t("events.no_reseed_done")); } if (result.locked > 0) { messages.push(t("events.reseed_locked", { count: result.locked })); } alert(messages.join("\n")); }); document.getElementById("generateFinals")?.addEventListener("click", () => { const created = generateFinalsForRace(event); saveState(); rerenderEventManager(eventId); if (created > 0) { alert(t("events.finals_generated")); } }); document.getElementById("clearGeneratedFinals")?.addEventListener("click", () => { clearGeneratedFinals(event.id); saveState(); rerenderEventManager(eventId); }); document.getElementById("applyBumps")?.addEventListener("click", () => { const applied = applyBumpsForRace(event); saveState(); rerenderEventManager(eventId); alert(t(applied > 0 ? "events.bumps_applied" : "events.no_bumps_applied")); }); document.getElementById("exportRacePackage")?.addEventListener("click", () => { const payload = buildRacePackagePayload(eventId); downloadJsonFile(`${sanitizeFilenameSegment(event.name)}_race_package.json`, payload); }); document.getElementById("importRacePackage")?.addEventListener("change", (importEvent) => { const input = importEvent.currentTarget; const file = input instanceof HTMLInputElement ? input.files?.[0] : null; if (!file) { return; } const reader = new FileReader(); reader.onload = () => { try { const parsed = JSON.parse(String(reader.result || "{}")); importRacePackagePayload(parsed); } catch (error) { alert(t("settings.import_failed", { msg: error instanceof Error ? error.message : String(error) })); } }; reader.readAsText(file); }); document.getElementById("printStartlists")?.addEventListener("click", () => { openPrintWindow(`${event.name} - ${t("events.start_lists")}`, buildRaceStartListsHtml(event)); }); document.getElementById("printResults")?.addEventListener("click", () => { openPrintWindow(`${event.name} - ${t("events.results_overview")}`, buildRaceResultsHtml(event)); }); document.getElementById("printTeamResults")?.addEventListener("click", () => { openPrintWindow(`${event.name} - ${t("events.team_report")}`, buildTeamRaceResultsHtml(event)); }); document.getElementById("pdfStartlists")?.addEventListener("click", async () => { await exportRaceStartListsPdf(event); }); document.getElementById("pdfResults")?.addEventListener("click", async () => { await exportRaceResultsPdf(event); }); document.getElementById("pdfTeamResults")?.addEventListener("click", async () => { await exportTeamRaceResultsPdf(event); }); document.getElementById("gridResetOrder")?.addEventListener("click", () => { if (!selectedGridSession) { return; } selectedGridSession.driverIds = getSessionEntrants(selectedGridSession) .map((driver) => driver.id) .filter(Boolean); selectedGridSession.manualGridIds = [...selectedGridSession.driverIds]; selectedGridSession.gridCustomized = false; saveState(); rerenderEventManager(eventId); }); document.getElementById("gridToggleLock")?.addEventListener("click", () => { if (!selectedGridSession) { return; } if (!selectedGridSession.gridCustomized) { selectedGridSession.manualGridIds = [...ensureSessionDriverOrder(selectedGridSession)]; selectedGridSession.gridCustomized = true; } else { selectedGridSession.manualGridIds = [...selectedGridSession.driverIds]; selectedGridSession.gridCustomized = false; } saveState(); rerenderEventManager(eventId); }); let dragIndex = null; document.querySelectorAll("#gridDragList .drag-item").forEach((node) => { node.addEventListener("dragstart", () => { dragIndex = Number(node.dataset.index); node.classList.add("drag-item-active"); }); node.addEventListener("dragend", () => { dragIndex = null; node.classList.remove("drag-item-active"); }); node.addEventListener("dragover", (dragEvent) => { dragEvent.preventDefault(); node.classList.add("drag-item-over"); }); node.addEventListener("dragleave", () => { node.classList.remove("drag-item-over"); }); node.addEventListener("drop", (dropEvent) => { dropEvent.preventDefault(); node.classList.remove("drag-item-over"); if (!selectedGridSession || dragIndex === null) { return; } const dropIndex = Number(node.dataset.index); if (Number.isNaN(dropIndex) || dropIndex === dragIndex) { return; } selectedGridSession.manualGridIds = reorderList(ensureSessionDriverOrder(selectedGridSession), dragIndex, dropIndex); selectedGridSession.gridCustomized = true; saveState(); rerenderEventManager(eventId); }); }); } }