Add configurable manifest-driven race audio system
This commit is contained in:
@@ -390,6 +390,7 @@ export function renderDriversView(deps) {
|
||||
})
|
||||
.join("");
|
||||
const editingProfileId = editingDriver ? getDriverProfileId(editingDriver) : "";
|
||||
const passingSoundOptions = (selected = "") => [`<option value="">${t("audio.pass_default")}</option>`, ...Array.from({ length: 8 }, (_item, index) => { const value = `pass_${String(index + 1).padStart(2, "0")}.wav`; return `<option value="${value}" ${selected === value ? "selected" : ""}>${value}</option>`; })].join("");
|
||||
const existingClubs = [...new Set(state.drivers.map((driver) => String(driver.club || "").trim()).filter(Boolean))].sort();
|
||||
const existingCountries = [...new Set([
|
||||
"Sverige", "Norge", "Finland", "Danmark", "Island", "Tyskland", "Nederländerna", "Belgien", "Frankrike", "Storbritannien", "Polen", "Tjeckien", "Österrike", "Schweiz",
|
||||
@@ -405,6 +406,7 @@ export function renderDriversView(deps) {
|
||||
<input name="brand" placeholder="${t("drivers.brand_placeholder")}" />
|
||||
<input name="transponder" placeholder="${t("drivers.transponder_placeholder")}" />
|
||||
<input name="speechName" placeholder="${t("drivers.speech_name_placeholder")}" title="${t("drivers.speech_name_hint")}" />
|
||||
<label>${t("audio.passing_sound")}<select name="passSound">${passingSoundOptions()}</select></label>
|
||||
<input name="club" list="driverClubOptions" placeholder="${t("drivers.club_placeholder")}" />
|
||||
<input name="country" list="driverCountryOptions" placeholder="${t("drivers.country_placeholder")}" />
|
||||
<label>${t("drivers.training_profile")}<select name="profileId" title="${t("drivers.training_profile_hint")}">
|
||||
@@ -470,6 +472,7 @@ export function renderDriversView(deps) {
|
||||
<input name="brand" value="${escapeHtml(editingDriver.brand || "")}" placeholder="${t("drivers.brand_placeholder")}" />
|
||||
<input name="transponder" value="${escapeHtml(editingDriver.transponder || "")}" placeholder="${t("drivers.transponder_placeholder")}" />
|
||||
<input name="speechName" value="${escapeHtml(editingDriver.speechName || "")}" placeholder="${t("drivers.speech_name_placeholder")}" title="${t("drivers.speech_name_hint")}" />
|
||||
<label>${t("audio.passing_sound")}<select name="passSound">${passingSoundOptions(editingDriver.passSound)}</select></label>
|
||||
<input name="club" list="driverClubOptions" value="${escapeHtml(profileGroups.find((profile) => profile.id === editingProfileId)?.club || editingDriver.club || "")}" placeholder="${t("drivers.club_placeholder")}" />
|
||||
<input name="country" list="driverCountryOptions" value="${escapeHtml(profileGroups.find((profile) => profile.id === editingProfileId)?.country || editingDriver.country || "")}" placeholder="${t("drivers.country_placeholder")}" />
|
||||
<label>${t("drivers.training_profile")}<select name="profileId" title="${t("drivers.training_profile_hint")}">
|
||||
@@ -516,6 +519,7 @@ export function renderDriversView(deps) {
|
||||
brand: String(form.get("brand") || "").trim(),
|
||||
transponder: String(form.get("transponder") || "").trim(),
|
||||
speechName: String(form.get("speechName") || "").trim(),
|
||||
passSound: String(form.get("passSound") || "").trim(),
|
||||
profileId,
|
||||
club: String(form.get("club") || linkedProfile?.club || "").trim(),
|
||||
country: String(form.get("country") || linkedProfile?.country || "").trim(),
|
||||
@@ -601,6 +605,7 @@ export function renderDriversView(deps) {
|
||||
const cleanedBrand = String(form.get("brand") || "").trim();
|
||||
const cleanedTp = String(form.get("transponder") || "").trim();
|
||||
const cleanedSpeechName = String(form.get("speechName") || "").trim();
|
||||
const cleanedPassSound = String(form.get("passSound") || "").trim();
|
||||
const requestedProfileId = String(form.get("profileId") || "").trim();
|
||||
const cleanedProfileId = requestedProfileId === "__new__" ? uid("profile") : requestedProfileId || editingProfileId;
|
||||
const cleanedClub = String(form.get("club") || "").trim();
|
||||
@@ -623,6 +628,7 @@ export function renderDriversView(deps) {
|
||||
brand: cleanedBrand,
|
||||
transponder: cleanedTp,
|
||||
speechName: cleanedSpeechName,
|
||||
passSound: cleanedPassSound,
|
||||
profileId: cleanedProfileId,
|
||||
club: cleanedClub,
|
||||
country: cleanedCountry,
|
||||
@@ -669,6 +675,7 @@ export function renderCarsView(deps) {
|
||||
!carSearch || [car.name, car.transponder, car.brand].map((value) => String(value || "").toLowerCase()).some((value) => value.includes(carSearch))
|
||||
);
|
||||
const editingCar = state.cars.find((car) => car.id === selectedCarEditId()) || null;
|
||||
const passingSoundOptions = (selected = "") => [`<option value="">${t("audio.pass_default")}</option>`, ...Array.from({ length: 8 }, (_item, index) => { const value = `pass_${String(index + 1).padStart(2, "0")}.wav`; return `<option value="${value}" ${selected === value ? "selected" : ""}>${value}</option>`; })].join("");
|
||||
|
||||
dom.view.innerHTML = `
|
||||
<section class="panel">
|
||||
@@ -677,6 +684,7 @@ export function renderCarsView(deps) {
|
||||
<input required name="name" placeholder="${t("cars.name_placeholder")}" />
|
||||
<input name="brand" placeholder="${t("cars.brand_placeholder")}" />
|
||||
<input required name="transponder" placeholder="${t("cars.transponder_placeholder")}" />
|
||||
<label>${t("audio.passing_sound")}<select name="passSound">${passingSoundOptions()}</select></label>
|
||||
<button class="btn btn-primary" type="submit">${t("cars.add")}</button>
|
||||
</form>
|
||||
</section>
|
||||
@@ -719,6 +727,7 @@ export function renderCarsView(deps) {
|
||||
<input name="name" required value="${escapeHtml(editingCar.name)}" placeholder="${t("cars.name_placeholder")}" />
|
||||
<input name="brand" value="${escapeHtml(editingCar.brand || "")}" placeholder="${t("cars.brand_placeholder")}" />
|
||||
<input name="transponder" required value="${escapeHtml(editingCar.transponder || "")}" placeholder="${t("cars.transponder_placeholder")}" />
|
||||
<label>${t("audio.passing_sound")}<select name="passSound">${passingSoundOptions(editingCar.passSound)}</select></label>
|
||||
<p class="form-error" id="carEditError" hidden></p>
|
||||
<div class="actions-inline">
|
||||
<button class="btn btn-primary" id="carEditSave" type="button">${t("common.save")}</button>
|
||||
@@ -741,6 +750,7 @@ export function renderCarsView(deps) {
|
||||
name: String(form.get("name")).trim(),
|
||||
brand: String(form.get("brand") || "").trim(),
|
||||
transponder: String(form.get("transponder")).trim(),
|
||||
passSound: String(form.get("passSound") || "").trim(),
|
||||
})
|
||||
);
|
||||
saveState();
|
||||
@@ -806,6 +816,7 @@ export function renderCarsView(deps) {
|
||||
const cleanedName = String(form.get("name") || "").trim();
|
||||
const cleanedBrand = String(form.get("brand") || "").trim();
|
||||
const cleanedTp = String(form.get("transponder") || "").trim();
|
||||
const cleanedPassSound = String(form.get("passSound") || "").trim();
|
||||
if (!cleanedName) {
|
||||
setFormError("carEditError", t("validation.required_name"));
|
||||
return;
|
||||
@@ -822,6 +833,7 @@ export function renderCarsView(deps) {
|
||||
name: cleanedName,
|
||||
brand: cleanedBrand,
|
||||
transponder: cleanedTp,
|
||||
passSound: cleanedPassSound,
|
||||
})
|
||||
: item
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user