import { PROLOGUE_OPTIONS_SEC, formatPrologueOption } from "./prologue_logic.js"; function formatDateTimeLocalValue(ms) { const date = new Date(ms); date.setSeconds(0, 0); date.setMinutes(date.getMinutes() - date.getTimezoneOffset()); return date.toISOString().slice(0, 16); } function formatClockTime(ms) { return new Date(ms).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: false }); } export function renderEventManagerMarkup(context) { const { event, t, escapeHtml, sessions, eventSchedule, sessionTypeChoices, sessionTypeHintKey, raceTeams, getSessionEntrants, getSessionTypeLabel, getStartModeLabel, getStatusLabel, normalizeStartMode, branding, driverOptions, carOptions, manageStatuses, renderManageStatusBadgeView, selectedParticipantCount, raceDrivers, teamDriverPool, showTeamsSection, parseQualifyingHeatName, state, getDriverDisplayById, raceFormatAdvanced, racePresets, selectedPreset, isEndurancePreset, showBasicQualifyingFields = true, showBasicFinalFields = true, renderRaceFormatContextCardView, renderRaceFormatFieldView, raceSummaryWarnings, raceSummaryItems, selectedGridSession, renderGridEditor, renderRaceStandingsTableView, buildPracticeStandings, buildQualifyingStandings, buildFinalStandings, renderTeamRaceStandings, renderSessionChannelAnalysis, renderFinalMatrix, editingTeam, editingSession, getModeLabel, renderTable, } = context; // Checking a driver/car here moves them off whichever other team already has them (see // reassignTeamMembers in event_race_logic.js) - name that team here so the admin sees // the move coming rather than discovering it after saving. const driverTeamElsewhere = (driverId, excludeTeamId = "") => raceTeams.find((team) => team.id !== excludeTeamId && team.driverIds.includes(driverId))?.name || ""; const carTeamElsewhere = (carId, excludeTeamId = "") => raceTeams.find((team) => team.id !== excludeTeamId && team.carIds.includes(carId))?.name || ""; // Same idea as driverTeamElsewhere above, but for qualifying heats: checking a driver // onto this heat moves them out of whichever other heat in the SAME round they're // currently on (see moveDriversIntoQualifyingHeat) - name that heat so the admin sees the // move coming before saving, not after. const driverHeatElsewhere = (driverId, targetSession) => { const targetParsed = parseQualifyingHeatName(targetSession?.name); if (!targetParsed) return ""; const other = sessions.find((session) => session.id !== targetSession.id && session.type === "qualification" && (session.driverIds || []).includes(driverId) && parseQualifyingHeatName(session.name)?.round === targetParsed.round ); return other?.name || ""; }; const sessionChannelMarkup = sessions .map((session) => ({ session, markup: renderSessionChannelAnalysis(session) })) .filter((entry) => entry.markup) .map(({ session, markup }) => `

${escapeHtml(session.name)} • ${escapeHtml(getSessionTypeLabel(session.type))}

${markup}
`) .join(""); return `

${t("events.manage_title")}: ${escapeHtml(event.name)}

${t("events.seed_best_laps_hint")}

${t("events.free_practice_note")}

${t("events.open_practice_note")}

${renderTable( [t("table.session"), t("table.type"), t("table.duration"), t("table.start_mode"), t("table.seeding"), t("table.status"), t(event.mode === "track" ? "events.assignments" : "events.participants"), t("events.actions")], sessions.map((s) => { const assignCount = event.mode === "track" ? (s.assignments || []).length : s.type === "team_race" ? raceTeams.length : getSessionEntrants(s).length; return ` ${escapeHtml(s.name)} ${escapeHtml(getSessionTypeLabel(s.type))} ${s.type === "open_practice" ? t("events.open_practice_untimed") : `${s.durationMin} min`} ${escapeHtml(getStartModeLabel(s.startMode))} ${s.seedBestLapCount > 0 ? `${s.seedBestLapCount}` : "-"} ${escapeHtml(getStatusLabel(s.status))} ${assignCount || (event.mode === "track" ? t("events.na") : "-")} ${ event.mode === "race" && normalizeStartMode(s.startMode) === "position" ? `` : "" } ${ event.mode === "race" && ["qualification", "final"].includes(s.type) ? ` ` : "" } `; }) )}

${t("events.branding")}

${t("events.branding_note")}

${branding.logoDataUrl ? `
event-logo
` : ""}
${ event.mode === "track" ? `

${t("events.sponsor_tools")}

${t("events.tp_rule")}

${t("events.assign_title")}

` : "" } ${ event.mode === "race" ? `
${t("events.manage_step_setup")}${renderManageStatusBadgeView(manageStatuses?.setup?.status || "pending")}
${escapeHtml(manageStatuses?.setup?.detail || "")}

${t("events.manage_step_setup_hint")}

${t("events.manage_step_format")}${renderManageStatusBadgeView(manageStatuses?.format?.status || "pending")}
${escapeHtml(manageStatuses?.format?.detail || "")}

${t("events.manage_step_format_hint")}

${t("events.manage_step_generate")}${renderManageStatusBadgeView(manageStatuses?.generation?.status || "pending")}
${escapeHtml(manageStatuses?.generation?.detail || "")}

${t("events.manage_step_generate_hint")}

${t("events.manage_step_live")}${renderManageStatusBadgeView(manageStatuses?.live?.status || "pending")}
${escapeHtml(manageStatuses?.live?.detail || "")}

${t("events.manage_step_live_hint")}

${t("events.select_participants")}

${selectedParticipantCount}
${raceDrivers .map((driver) => { const checked = event.raceConfig.participantsConfigured ? (event.raceConfig.driverIds || []).includes(driver.id) : true; return ` `; }) .join("")}
${ showTeamsSection ? `

${t("events.teams")}

${raceTeams.length}

${t("events.team_race_intro")}

${t("events.team_steps")}

${t("events.team_hint")}

${t("events.team_drivers")}

${t("events.team_form_drivers")}

${teamDriverPool.fallback ? `

${t("events.team_driver_fallback")}

` : ""}
${ teamDriverPool.drivers.length ? teamDriverPool.drivers .map( (driver) => ` ` ) .join("") : `

${t("common.no_entries")}

` }

${t("events.team_cars")}

${t("events.team_form_cars")}

${ state.cars.length ? state.cars .map( (car) => ` ` ) .join("") : `

${t("common.no_entries")}

` }
${ raceTeams.length ? raceTeams .map( (team) => `
${escapeHtml(team.name)}
${t("events.team_drivers")}: ${escapeHtml( team.driverIds.map((driverId) => getDriverDisplayById(driverId)).join(", ") || "-" )}
${t("events.team_cars")}: ${escapeHtml( team.carIds .map((carId) => { const car = state.cars.find((item) => item.id === carId); return car ? `${car.name} (${car.transponder || "-"})` : ""; }) .filter(Boolean) .join(", ") || "-" )}
` ) .join("") : `

${t("events.no_teams")}

` }
` : "" }

${t("events.race_format")}

${t("events.race_format_intro")}

${t("events.race_format")}
${t("events.race_actions_hint")}

${t("events.practice_block")}

${t("events.practice_block_hint")}

${renderRaceFormatContextCardView(isEndurancePreset ? "events.context_endurance_title" : "events.context_standard_title", isEndurancePreset ? "events.context_endurance_hint" : "events.context_standard_hint")} ${renderRaceFormatFieldView( "events.race_preset", "events.race_preset_hint", `` )} ${raceFormatAdvanced ? `
${t("events.preset_name")} ${t("events.race_preset_hint")}
` : `
${t("events.race_preset")} ${t("events.race_preset_hint")}
`} ${showBasicQualifyingFields ? renderRaceFormatFieldView( "events.qualifying_scoring", "events.qualifying_scoring_hint", `` ) : ""} ${showBasicQualifyingFields ? renderRaceFormatFieldView( "events.qualifying_rounds", "events.qualifying_rounds_hint", `` ) : ""} ${showBasicQualifyingFields ? renderRaceFormatFieldView( "events.cars_per_heat", "events.cars_per_heat_hint", `` ) : ""} ${showBasicQualifyingFields ? renderRaceFormatFieldView( "events.qual_duration", "events.qual_duration_hint", `` ) : ""} ${showBasicQualifyingFields ? renderRaceFormatFieldView( "events.qual_start_mode", "events.qual_start_mode_hint", `` ) : ""} ${showBasicQualifyingFields ? renderRaceFormatFieldView( "events.qual_prologue", "events.prologue_hint", `` ) : ""} ${raceFormatAdvanced ? renderRaceFormatFieldView( "events.qual_seed_laps", "events.qual_seed_laps_hint", `` ) : ""} ${raceFormatAdvanced ? renderRaceFormatFieldView( "events.qual_seed_method", "events.qual_seed_method_hint", `` ) : ""} ${raceFormatAdvanced ? renderRaceFormatFieldView( "events.counted_qual_rounds", "events.counted_qual_rounds_hint", `` ) : ""} ${raceFormatAdvanced ? renderRaceFormatFieldView( "events.qual_points_table", "events.qual_points_table_hint", `` ) : ""} ${raceFormatAdvanced ? renderRaceFormatFieldView( "events.qual_tie_break", "events.qual_tie_break_hint", `` ) : ""}

${t("events.finals_block")}

${t("events.finals_block_hint")}

${renderRaceFormatContextCardView(isEndurancePreset ? "events.context_endurance_title" : "events.context_standard_title", isEndurancePreset ? "events.context_endurance_hint" : "events.context_standard_hint")} ${showBasicFinalFields ? renderRaceFormatFieldView( "events.cars_per_final", "events.cars_per_final_hint", `` ) : ""} ${showBasicFinalFields ? renderRaceFormatFieldView( "events.final_legs", "events.final_legs_hint", `` ) : ""} ${raceFormatAdvanced ? renderRaceFormatFieldView( "events.counted_final_legs", "events.counted_final_legs_hint", `` ) : ""} ${showBasicFinalFields ? renderRaceFormatFieldView( "events.final_duration", "events.final_duration_hint", `` ) : ""} ${showBasicFinalFields ? renderRaceFormatFieldView( "events.final_start_mode", "events.final_start_mode_hint", `` ) : ""} ${showBasicFinalFields ? renderRaceFormatFieldView( "events.final_prologue", "events.prologue_hint", `` ) : ""} ${showBasicFinalFields ? renderRaceFormatFieldView( "events.bump_count", "events.bump_count_hint", `` ) : ""} ${showBasicFinalFields ? renderRaceFormatFieldView( "events.source_for_finals", "events.finals_source_hint", `` ) : ""} ${raceFormatAdvanced ? renderRaceFormatFieldView( "events.reserve_bump_slots", "events.reserve_bump_slots_hint", ``, { checkbox: true } ) : ""}

${t("events.rules_block")}

${t("events.rules_block_hint")}

${renderRaceFormatContextCardView("events.context_rules_title", "events.context_rules_hint")} ${renderRaceFormatFieldView( "events.follow_up_sec", "events.follow_up_sec_hint", `` )} ${renderRaceFormatFieldView( "events.min_lap_time", "events.min_lap_time_hint", `` )} ${renderRaceFormatFieldView( "events.max_lap_time", "events.max_lap_time_hint", `` )}
${t("events.actions")} ${t("events.race_driver_scope")} ${t("events.bump_reserved_note")}

${t("events.race_actions_title")}

${t("events.race_actions_hint")}

${t("events.race_package_hint")}

${t("events.grid_editor")}

${renderGridEditor(selectedGridSession)}

${t("events.practice_standings")}

${renderRaceStandingsTableView(buildPracticeStandings(event), t("events.no_practice_results"))}

${t("events.qualifying_standings")}

${renderRaceStandingsTableView(buildQualifyingStandings(event), t("events.no_qualifying_results"))}

${t("events.final_standings")}

${renderRaceStandingsTableView(buildFinalStandings(event), t("events.no_final_results"))}

${t("events.team_standings")}

${renderTeamRaceStandings(event)}
${sessionChannelMarkup ? `

${t("timing.channel_analysis")}

${t("timing.channel_analysis_race_hint")}

${sessionChannelMarkup}
` : ""}

${t("events.schedule_title")}

${t("events.schedule_hint")}

${event.raceConfig?.scheduleStartAt ? `` : ""}
${eventSchedule && eventSchedule.length ? renderTable( [t("table.session"), t("table.type"), t("events.schedule_planned"), t("events.schedule_actual"), ""], eventSchedule.map((row) => { const session = sessions.find((item) => item.id === row.sessionId); if (!session) return ""; return ` ${escapeHtml(session.name)} ${escapeHtml(getSessionTypeLabel(session.type))} ${escapeHtml(formatClockTime(row.plannedStart))} - ${escapeHtml(formatClockTime(row.plannedEnd))} ${row.actualStart ? escapeHtml(formatClockTime(row.actualStart)) + (row.actualEnd ? ` - ${escapeHtml(formatClockTime(row.actualEnd))}` : "") : "-"} ${row.delayed ? `${t("events.schedule_delayed")}` : ""} `; }) ) : `

${t("events.schedule_not_set")}

`}

${t("events.final_matrix")}

${renderFinalMatrix(event)}
` : "" } ${ editingTeam ? ` ` : "" } ${ editingSession ? ` ` : "" } `;; }