Extract shared event and session helpers into module

This commit is contained in:
larssand
2026-03-26 19:23:38 +01:00
parent 65c3c3c03c
commit bee5a8453a
2 changed files with 96 additions and 88 deletions

View File

@@ -11,6 +11,7 @@ import { getSessionTypeLabel as getSessionTypeLabelLogic, getStatusLabel as getS
import { renderDashboardView, renderClassesView, renderDriversView, renderCarsView } from "./core_views.js"; import { renderDashboardView, renderClassesView, renderDriversView, renderCarsView } from "./core_views.js";
import { renderGuideView, renderOverlayPageView } from "./misc_views.js"; import { renderGuideView, renderOverlayPageView } from "./misc_views.js";
import { getSessionsForEventHelper, getModeLabelHelper, normalizeStartModeHelper, getStartModeLabelHelper, getClassNameHelper, getEventNameHelper, renderAssignmentListView, renderSessionsTableView } from "./event_common.js";
import { renderTimingView, renderJudgingView } from "./timing_views.js"; import { renderTimingView, renderJudgingView } from "./timing_views.js";
@@ -101,6 +102,14 @@ const renderFinalMatrix = (event) => renderFinalMatrixHelper(event, { t, escapeH
const buildPrintBrandBlock = (branding) => buildPrintBrandBlockHelper(branding, { escapeHtml }); const buildPrintBrandBlock = (branding) => buildPrintBrandBlockHelper(branding, { escapeHtml });
const buildRaceStartListsHtml = (event) => buildRaceStartListsHtmlHelper(event, { t, state, escapeHtml, resolveEventBranding, getSessionsForEvent, getSessionSortWeight, getClassName, buildPrintBrandBlock, getSessionGridEntries, getSessionTypeLabel, getStartModeLabel, renderTable }); const buildRaceStartListsHtml = (event) => buildRaceStartListsHtmlHelper(event, { t, state, escapeHtml, resolveEventBranding, getSessionsForEvent, getSessionSortWeight, getClassName, buildPrintBrandBlock, getSessionGridEntries, getSessionTypeLabel, getStartModeLabel, renderTable });
const buildRaceResultsHtml = (event) => buildRaceResultsHtmlHelper(event, { t, escapeHtml, resolveEventBranding, getClassName, buildPrintBrandBlock, renderRaceStandingsTableView, buildPracticeStandings, buildQualifyingStandings, buildFinalStandings, renderTeamRaceStandings }); const buildRaceResultsHtml = (event) => buildRaceResultsHtmlHelper(event, { t, escapeHtml, resolveEventBranding, getClassName, buildPrintBrandBlock, renderRaceStandingsTableView, buildPracticeStandings, buildQualifyingStandings, buildFinalStandings, renderTeamRaceStandings });
const getSessionsForEvent = (eventId) => getSessionsForEventHelper(state, eventId);
const getModeLabel = (mode) => getModeLabelHelper(mode, { t });
const normalizeStartMode = (mode) => normalizeStartModeHelper(mode);
const getStartModeLabel = (mode) => getStartModeLabelHelper(mode, { t, normalizeStartMode });
const getClassName = (classId) => getClassNameHelper(state, classId, { t });
const getEventName = (eventId) => getEventNameHelper(state, eventId, { t });
const renderAssignmentList = (eventId) => renderAssignmentListView(eventId, { state, t, escapeHtml, getSessionsForEvent, getSessionTypeLabel, saveState, renderAssignmentList });
const renderSessionsTable = (sessions) => renderSessionsTableView(sessions, { t, renderTable, escapeHtml, getEventName, getSessionTypeLabel, getStatusLabel, getModeLabel });
const buildTeamRaceResultsHtml = (event) => buildTeamRaceResultsHtmlHelper(event, { t, escapeHtml, resolveEventBranding, getClassName, buildPrintBrandBlock, buildTeamRaceStandings, renderTable, formatLap, renderTeamStintLog }); const buildTeamRaceResultsHtml = (event) => buildTeamRaceResultsHtmlHelper(event, { t, escapeHtml, resolveEventBranding, getClassName, buildPrintBrandBlock, buildTeamRaceStandings, renderTable, formatLap, renderTeamStintLog });
const renderDashboard = () => renderDashboardView({ state, dom, t, backend, getActiveSession, getStatusLabel, getSessionTypeLabel, getEventName, getModeLabel, getBackendUrl, formatLap, renderSessionsTable, setCurrentView: (view) => { currentView = view; }, renderNav, renderView, connectDecoder, disconnectDecoder, openOverlayWindow, ensureAudioContext, playPassingBeep, playFinishSiren, escapeHtml }); const renderDashboard = () => renderDashboardView({ state, dom, t, backend, getActiveSession, getStatusLabel, getSessionTypeLabel, getEventName, getModeLabel, getBackendUrl, formatLap, renderSessionsTable, setCurrentView: (view) => { currentView = view; }, renderNav, renderView, connectDecoder, disconnectDecoder, openOverlayWindow, ensureAudioContext, playPassingBeep, playFinishSiren, escapeHtml });
const renderClasses = () => renderClassesView({ state, dom, t, selectedClassEditId: () => selectedClassEditId, setSelectedClassEditId: (value) => { selectedClassEditId = value; }, uid, saveState, renderView, renderTable, escapeHtml, setFormError, bindModalShell }); const renderClasses = () => renderClassesView({ state, dom, t, selectedClassEditId: () => selectedClassEditId, setSelectedClassEditId: (value) => { selectedClassEditId = value; }, uid, saveState, renderView, renderTable, escapeHtml, setFormError, bindModalShell });
@@ -5091,50 +5100,6 @@ function renderEventManager(eventId) {
} }
} }
function renderAssignmentList(eventId) {
const block = document.getElementById("assignmentList");
if (!block) {
return;
}
const sessions = getSessionsForEvent(eventId);
block.innerHTML = sessions
.map((s) => {
const items = (s.assignments || [])
.map((a) => {
const driver = state.drivers.find((d) => d.id === a.driverId);
const car = state.cars.find((c) => c.id === a.carId);
return `
<li>
${escapeHtml(driver?.name || t("common.unknown_driver"))} -> ${escapeHtml(car?.name || t("common.unknown_car"))} (${escapeHtml(
car?.transponder || "-"
)})
<button id="as-delete-${a.id}" class="btn btn-danger btn-mini">x</button>
</li>
`;
})
.join("");
return `
<div class="assignment-group">
<h4>${escapeHtml(s.name)} (${escapeHtml(getSessionTypeLabel(s.type))})</h4>
<ul>${items || `<li>${t("events.no_assignments")}</li>`}</ul>
</div>
`;
})
.join("");
sessions.forEach((s) => {
(s.assignments || []).forEach((a) => {
document.getElementById(`as-delete-${a.id}`)?.addEventListener("click", () => {
s.assignments = s.assignments.filter((x) => x.id !== a.id);
saveState();
renderAssignmentList(eventId);
});
});
});
}
function getQuickAddState(transponder) { function getQuickAddState(transponder) {
const normalized = String(transponder || "").trim(); const normalized = String(transponder || "").trim();
const driver = state.drivers.find((item) => String(item.transponder || "").trim() === normalized) || null; const driver = state.drivers.find((item) => String(item.transponder || "").trim() === normalized) || null;
@@ -5330,30 +5295,6 @@ function renderRecentPassings(session) {
} }
function getSessionsForEvent(eventId) {
return state.sessions.filter((s) => s.eventId === eventId);
}
function getModeLabel(mode) {
return mode === "track" ? t("mode.track") : t("mode.race");
}
function normalizeStartMode(mode) {
return ["mass", "position", "staggered"].includes(String(mode || "").toLowerCase()) ? String(mode).toLowerCase() : "mass";
}
function getStartModeLabel(mode) {
return t(`events.start_mode_${normalizeStartMode(mode)}`);
}
function getClassName(classId) {
return state.classes.find((x) => x.id === classId)?.name || t("common.unknown");
}
function getEventName(eventId) {
return state.events.find((x) => x.id === eventId)?.name || t("common.unknown_event");
}
function getFreePracticeSessions(eventId) { function getFreePracticeSessions(eventId) {
return getSessionsForEvent(eventId).filter((session) => session.type === "free_practice"); return getSessionsForEvent(eventId).filter((session) => session.type === "free_practice");
} }
@@ -5710,26 +5651,6 @@ function resolveCompetitor(session, transponder) {
}; };
} }
function renderSessionsTable(sessions) {
if (!sessions.length) {
return `<p>${t("session.none_yet")}</p>`;
}
return renderTable(
[t("table.event"), t("table.session"), t("table.type"), t("table.status"), t("table.mode")],
sessions.map(
(s) => `
<tr>
<td>${escapeHtml(getEventName(s.eventId))}</td>
<td>${escapeHtml(s.name)}</td>
<td>${escapeHtml(getSessionTypeLabel(s.type))}</td>
<td>${escapeHtml(getStatusLabel(s.status))}</td>
<td>${getModeLabel(s.mode)}</td>
</tr>
`
)
);
}
function renderSimpleList(items, labelFn, idFn) { function renderSimpleList(items, labelFn, idFn) {
if (!items.length) { if (!items.length) {
return `<p>${t("common.no_entries")}</p>`; return `<p>${t("common.no_entries")}</p>`;

87
src/event_common.js Normal file
View File

@@ -0,0 +1,87 @@
export function getSessionsForEventHelper(state, eventId) {
return state.sessions.filter((s) => s.eventId === eventId);
}
export function getModeLabelHelper(mode, { t }) {
return mode === "track" ? t("mode.track") : t("mode.race");
}
export function normalizeStartModeHelper(mode) {
return ["mass", "position", "staggered"].includes(String(mode || "").toLowerCase()) ? String(mode).toLowerCase() : "mass";
}
export function getStartModeLabelHelper(mode, { t, normalizeStartMode }) {
return t(`events.start_mode_${normalizeStartMode(mode)}`);
}
export function getClassNameHelper(state, classId, { t }) {
return state.classes.find((x) => x.id === classId)?.name || t("common.unknown");
}
export function getEventNameHelper(state, eventId, { t }) {
return state.events.find((x) => x.id === eventId)?.name || t("common.unknown_event");
}
export function renderAssignmentListView(eventId, deps) {
const { state, t, escapeHtml, getSessionsForEvent, getSessionTypeLabel, saveState, renderAssignmentList } = deps;
const block = document.getElementById("assignmentList");
if (!block) {
return;
}
const sessions = getSessionsForEvent(eventId);
block.innerHTML = sessions
.map((s) => {
const items = (s.assignments || [])
.map((a) => {
const driver = state.drivers.find((d) => d.id === a.driverId);
const car = state.cars.find((c) => c.id === a.carId);
return `
<li>
${escapeHtml(driver?.name || t("common.unknown_driver"))} -> ${escapeHtml(car?.name || t("common.unknown_car"))} (${escapeHtml(car?.transponder || "-")})
<button id="as-delete-${a.id}" class="btn btn-danger btn-mini">x</button>
</li>
`;
})
.join("");
return `
<div class="assignment-group">
<h4>${escapeHtml(s.name)} (${escapeHtml(getSessionTypeLabel(s.type))})</h4>
<ul>${items || `<li>${t("events.no_assignments")}</li>`}</ul>
</div>
`;
})
.join("");
sessions.forEach((s) => {
(s.assignments || []).forEach((a) => {
document.getElementById(`as-delete-${a.id}`)?.addEventListener("click", () => {
s.assignments = s.assignments.filter((x) => x.id !== a.id);
saveState();
renderAssignmentList(eventId);
});
});
});
}
export function renderSessionsTableView(sessions, deps) {
const { t, renderTable, escapeHtml, getEventName, getSessionTypeLabel, getStatusLabel, getModeLabel } = deps;
if (!sessions.length) {
return `<p>${t("session.none_yet")}</p>`;
}
return renderTable(
[t("table.event"), t("table.session"), t("table.type"), t("table.status"), t("table.mode")],
sessions.map(
(s) => `
<tr>
<td>${escapeHtml(getEventName(s.eventId))}</td>
<td>${escapeHtml(s.name)}</td>
<td>${escapeHtml(getSessionTypeLabel(s.type))}</td>
<td>${escapeHtml(getStatusLabel(s.status))}</td>
<td>${getModeLabel(s.mode)}</td>
</tr>
`
)
);
}