Extract event and race workspace markup into module

This commit is contained in:
larssand
2026-03-26 19:48:53 +01:00
parent 9933c9c8f8
commit a4a40454aa
2 changed files with 160 additions and 127 deletions

View File

@@ -12,6 +12,7 @@ import { renderDashboardView, renderClassesView, renderDriversView, renderCarsVi
import { renderGuideView, renderOverlayPageView } from "./misc_views.js";
import { getSessionsForEventHelper, getModeLabelHelper, normalizeStartModeHelper, getStartModeLabelHelper, getClassNameHelper, getEventNameHelper, renderAssignmentListView, renderSessionsTableView } from "./event_common.js";
import { renderEventWorkspaceMarkup } from "./event_views.js";
import { createDefaultAmmcConfigHelper, getManagedWsUrlHelper, loadAmmcConfigFromBackendHelper, saveAmmcConfigToBackendHelper, refreshAmmcStatusHelper, startManagedAmmcHelper, stopManagedAmmcHelper, applyPersistedStateHelper, hydrateFromBackendHelper, scheduleBackendSyncHelper, syncStateToBackendHelper, pingBackendHelper, checkAppVersionHelper, startAppVersionPollingHelper, startOverlaySyncHelper, startOverlayRotationHelper, startOverlayLiveRefreshHelper, ensureAudioContextHelper, playPassingBeepHelper, playFinishSirenHelper, playLeaderCueHelper, playStartCueHelper, playBestLapCueHelper, pushOverlayEventHelper, speakTextHelper, announcePassingHelper, announceRaceFinishedHelper, handleSessionTimerTickHelper, tickClockHelper } from "./runtime_services.js";
import { connectDecoderHelper, disconnectDecoderHelper, processDecoderMessageHelper } from "./decoder_runtime.js";
@@ -2815,135 +2816,24 @@ function renderEventWorkspace(mode) {
ensureRaceWizardDraft();
}
const filteredEvents = state.events.filter((event) => event.mode === mode);
const classOptions = state.classes
.map((c) => `<option value="${c.id}">${escapeHtml(c.name)}</option>`)
.join("");
const wizardClassOptions = state.classes
.map((c) => `<option value="${c.id}" ${c.id === raceWizardDraft?.classId ? "selected" : ""}>${escapeHtml(c.name)}</option>`)
.join("");
const editingEvent = filteredEvents.find((event) => event.id === selectedEventEditId) || null;
dom.view.innerHTML = `
<section class="panel">
<div class="panel-header"><h3>${t(isRaceMode ? "events.create_race" : "events.create")}</h3></div>
<div class="panel-body">
<p>${t(isRaceMode ? "events.race_only_intro" : "events.track_only_intro")}</p>
${isRaceMode ? `<p class="hint">${t("events.wizard_hint")}</p>` : ""}
</div>
${
isRaceMode
? `
<div class="panel-body race-wizard-steps">
${renderRaceWizardStepsView()}
</div>
<div class="panel-body">
${renderRaceWizardContentView(raceWizardDraft, wizardClassOptions, getDriversForClass(raceWizardDraft.classId), getRaceWizardPreset(raceWizardDraft.presetId))}
</div>
<div class="panel-body race-wizard-footer">
<button id="raceWizardReset" class="btn" type="button">${t("common.reset")}</button>
<div class="actions-inline">
${raceWizardStep > 1 ? `<button id="raceWizardPrev" class="btn" type="button">${t("common.previous")}</button>` : ""}
${raceWizardStep < 4 ? `<button id="raceWizardNext" class="btn btn-primary" type="button">${t("common.next")}</button>` : `<button id="raceWizardCreate" class="btn btn-primary" type="button">${t("events.wizard_create")}</button>`}
</div>
</div>
`
: `
<form id="eventForm" class="panel-body form-grid cols-4">
<label>
${t("events.field_name")}
<input required name="name" placeholder="${t("events.name_placeholder")}" />
<small>${t("events.field_name_hint")}</small>
</label>
<label>
${t("events.field_date")}
<input required type="date" name="date" />
<small>${t("events.field_date_hint")}</small>
</label>
<label>
${t("events.field_class")}
<select name="classId">${classOptions}</select>
<small>${t("events.field_class_hint")}</small>
</label>
<div class="actions-inline align-end">
<button class="btn btn-primary" type="submit">${t("events.add")}</button>
</div>
</form>
`
}
</section>
<section class="panel">
<div class="panel-header"><h3>${t(isRaceMode ? "events.race_title" : "events.title")}</h3></div>
<div class="panel-body">
${renderTable(
[t("table.name"), t("table.date"), t("table.class"), t("table.mode"), t("events.sessions"), t("events.actions")],
filteredEvents.map((e) => {
const sessions = getSessionsForEvent(e.id);
return `
<tr>
<td>${escapeHtml(e.name)}</td>
<td>${escapeHtml(e.date)}</td>
<td>${escapeHtml(getClassName(e.classId))}</td>
<td>${getModeLabel(e.mode)}</td>
<td>${sessions.length}</td>
<td class="actions-inline">
<button id="event-edit-${e.id}" class="btn">${t("events.edit")}</button>
<button id="event-manage-${e.id}" class="btn">${t("events.manage")}</button>
<button id="event-delete-${e.id}" class="btn btn-danger">${t("common.delete")}</button>
</td>
</tr>
`;
})
)}
</div>
</section>
<section id="eventManageArea"></section>
${
editingEvent
? `
<div class="modal-overlay" id="eventEditModalOverlay">
<div class="modal-card">
<div class="panel-header">
<h3>${t("common.edit")}</h3>
<button class="btn" id="eventEditCancel">${t("common.cancel")}</button>
</div>
<form id="eventEditForm" class="panel-body form-grid cols-3">
<label>
${t("events.field_name")}
<input name="name" required value="${escapeHtml(editingEvent.name)}" placeholder="${t("events.name_placeholder")}" />
<small>${t("events.field_name_hint")}</small>
</label>
<label>
${t("events.field_date")}
<input name="date" required type="date" value="${escapeHtml(editingEvent.date || "")}" />
<small>${t("events.field_date_hint")}</small>
</label>
<label>
${t("events.field_class")}
<select name="classId">
${state.classes
.map(
(item) =>
`<option value="${item.id}" ${item.id === editingEvent.classId ? "selected" : ""}>${escapeHtml(item.name)}</option>`
)
.join("")}
</select>
<small>${t("events.field_class_hint")}</small>
</label>
<p class="form-error" id="eventEditError" hidden></p>
<div class="actions-inline">
<button class="btn btn-primary" type="submit">${t("common.save")}</button>
<button class="btn" id="eventEditCancelFooter" type="button">${t("common.cancel")}</button>
</div>
</form>
</div>
</div>
`
: ""
}
`;
dom.view.innerHTML = renderEventWorkspaceMarkup(mode, {
state,
t,
escapeHtml,
renderTable,
renderRaceWizardStepsView,
renderRaceWizardContentView,
raceWizardDraft,
raceWizardStep,
getDriversForClass,
getRaceWizardPreset,
getSessionsForEvent,
getClassName,
getModeLabel,
editingEvent,
});
if (isRaceMode) {
const persistWizardStepOne = () => {

143
src/event_views.js Normal file
View File

@@ -0,0 +1,143 @@
export function renderEventWorkspaceMarkup(mode, deps) {
const {
state,
t,
escapeHtml,
renderTable,
renderRaceWizardStepsView,
renderRaceWizardContentView,
raceWizardDraft,
raceWizardStep,
getDriversForClass,
getRaceWizardPreset,
getSessionsForEvent,
getClassName,
getModeLabel,
editingEvent,
} = deps;
const isRaceMode = mode === "race";
const filteredEvents = state.events.filter((event) => event.mode === mode);
const classOptions = state.classes.map((c) => `<option value="${c.id}">${escapeHtml(c.name)}</option>`).join("");
const wizardClassOptions = state.classes
.map((c) => `<option value="${c.id}" ${c.id === raceWizardDraft?.classId ? "selected" : ""}>${escapeHtml(c.name)}</option>`)
.join("");
return `
<section class="panel">
<div class="panel-header"><h3>${t(isRaceMode ? "events.create_race" : "events.create")}</h3></div>
<div class="panel-body">
<p>${t(isRaceMode ? "events.race_only_intro" : "events.track_only_intro")}</p>
${isRaceMode ? `<p class="hint">${t("events.wizard_hint")}</p>` : ""}
</div>
${
isRaceMode
? `
<div class="panel-body race-wizard-steps">
${renderRaceWizardStepsView()}
</div>
<div class="panel-body">
${renderRaceWizardContentView(raceWizardDraft, wizardClassOptions, getDriversForClass(raceWizardDraft.classId), getRaceWizardPreset(raceWizardDraft.presetId))}
</div>
<div class="panel-body race-wizard-footer">
<button id="raceWizardReset" class="btn" type="button">${t("common.reset")}</button>
<div class="actions-inline">
${raceWizardStep > 1 ? `<button id="raceWizardPrev" class="btn" type="button">${t("common.previous")}</button>` : ""}
${raceWizardStep < 4 ? `<button id="raceWizardNext" class="btn btn-primary" type="button">${t("common.next")}</button>` : `<button id="raceWizardCreate" class="btn btn-primary" type="button">${t("events.wizard_create")}</button>`}
</div>
</div>
`
: `
<form id="eventForm" class="panel-body form-grid cols-4">
<label>
${t("events.field_name")}
<input required name="name" placeholder="${t("events.name_placeholder")}" />
<small>${t("events.field_name_hint")}</small>
</label>
<label>
${t("events.field_date")}
<input required type="date" name="date" />
<small>${t("events.field_date_hint")}</small>
</label>
<label>
${t("events.field_class")}
<select name="classId">${classOptions}</select>
<small>${t("events.field_class_hint")}</small>
</label>
<div class="actions-inline align-end">
<button class="btn btn-primary" type="submit">${t("events.add")}</button>
</div>
</form>
`
}
</section>
<section class="panel">
<div class="panel-header"><h3>${t(isRaceMode ? "events.race_title" : "events.title")}</h3></div>
<div class="panel-body">
${renderTable(
[t("table.name"), t("table.date"), t("table.class"), t("table.mode"), t("events.sessions"), t("events.actions")],
filteredEvents.map((e) => {
const sessions = getSessionsForEvent(e.id);
return `
<tr>
<td>${escapeHtml(e.name)}</td>
<td>${escapeHtml(e.date)}</td>
<td>${escapeHtml(getClassName(e.classId))}</td>
<td>${getModeLabel(e.mode)}</td>
<td>${sessions.length}</td>
<td class="actions-inline">
<button id="event-edit-${e.id}" class="btn">${t("events.edit")}</button>
<button id="event-manage-${e.id}" class="btn">${t("events.manage")}</button>
<button id="event-delete-${e.id}" class="btn btn-danger">${t("common.delete")}</button>
</td>
</tr>
`;
})
)}
</div>
</section>
<section id="eventManageArea"></section>
${
editingEvent
? `
<div class="modal-overlay" id="eventEditModalOverlay">
<div class="modal-card">
<div class="panel-header">
<h3>${t("common.edit")}</h3>
<button class="btn" id="eventEditCancel">${t("common.cancel")}</button>
</div>
<form id="eventEditForm" class="panel-body form-grid cols-3">
<label>
${t("events.field_name")}
<input name="name" required value="${escapeHtml(editingEvent.name)}" placeholder="${t("events.name_placeholder")}" />
<small>${t("events.field_name_hint")}</small>
</label>
<label>
${t("events.field_date")}
<input name="date" required type="date" value="${escapeHtml(editingEvent.date || "")}" />
<small>${t("events.field_date_hint")}</small>
</label>
<label>
${t("events.field_class")}
<select name="classId">
${state.classes
.map((item) => `<option value="${item.id}" ${item.id === editingEvent.classId ? "selected" : ""}>${escapeHtml(item.name)}</option>`)
.join("")}
</select>
<small>${t("events.field_class_hint")}</small>
</label>
<p class="form-error" id="eventEditError" hidden></p>
<div class="actions-inline">
<button class="btn btn-primary" type="submit">${t("common.save")}</button>
<button class="btn" id="eventEditCancelFooter" type="button">${t("common.cancel")}</button>
</div>
</form>
</div>
</div>
`
: ""
}
`;
}