diff --git a/README.md b/README.md index 599a63d..1455a2c 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ JMK RB RaceController is an RC timing and race-control system with support for s - Basic mode now reacts to the selected preset, including a cleaner endurance view - `Basic / Advanced` mode for `Race Format` - a right-side race summary card + - a preset-aware summary card that changes between endurance and normal race focus - separate `Race actions` for generation, reseeding and bump-up - reorganized in-app `Guide` with overview cards and two-column sections - explicit race participant selection diff --git a/README.sv.md b/README.sv.md index b794d9f..de068fe 100644 --- a/README.sv.md +++ b/README.sv.md @@ -39,6 +39,7 @@ RC timing app med sponsor-eventflöde (delade bilar/transpondrar mellan olika he - Grundläge reagerar nu på valt preset, inklusive renare endurance-vy - `Grundläge / Avancerat` för `Raceformat` - en sammanfattningspanel till höger + - ett presetstyrt sammanfattningskort som växlar mellan endurance- och vanligt race-fokus - separata `Race actions` för generering, reseeding och bump-up - omgjord inbyggd `Guide` med översiktskort och tvåkolumnslayout - välj exakt vilka förare som är med i racet diff --git a/src/app.js b/src/app.js index 89e312d..6d29d80 100644 --- a/src/app.js +++ b/src/app.js @@ -193,6 +193,8 @@ const TRANSLATIONS = { "events.race_summary_finals": "Finalupplägg", "events.race_summary_validation": "Varvfönster", "events.race_summary_follow_up": "Follow-up", + "events.race_summary_focus": "Fokus", + "events.race_summary_generation": "Generering", "events.race_actions_title": "Race actions", "events.race_actions_hint": "Generering och reseeding ligger separat från formatinställningarna så setupen blir lättare att läsa.", "events.context_standard_title": "Klubbrace-läge", @@ -907,6 +909,8 @@ const TRANSLATIONS = { "events.race_summary_finals": "Finals setup", "events.race_summary_validation": "Lap window", "events.race_summary_follow_up": "Follow-up", + "events.race_summary_focus": "Focus", + "events.race_summary_generation": "Generation", "events.race_actions_title": "Race actions", "events.race_actions_hint": "Generation and reseeding live separately from the format fields so setup is easier to read.", "events.context_standard_title": "Club race mode", @@ -7712,12 +7716,25 @@ function getRaceSummaryItems(event, sessions, raceDrivers, selectedPreset) { const teamCount = sessions.filter((session) => session.type === "team_race").length; const scoringLabel = cfg.qualifyingScoring === "best" ? t("events.qualifying_scoring_best") : t("events.qualifying_scoring_points"); const lapWindow = `${((cfg.minLapMs || 0) / 1000).toFixed(1)}s / ${((cfg.maxLapMs || 0) / 1000).toFixed(1)}s`; + const isEndurancePreset = selectedPreset?.id === "endurance"; + if (isEndurancePreset) { + return [ + { label: t("events.race_summary_preset"), value: selectedPreset?.label || t("events.preset_custom") }, + { label: t("events.race_summary_focus"), value: `${t("events.team_race")} · ${getStartModeLabel("mass")}` }, + { label: t("events.race_summary_participants"), value: String(participantCount || 0) }, + { label: t("events.race_summary_created_sessions"), value: `P ${practiceCount} · T ${teamCount}` }, + { label: t("events.race_summary_generation"), value: `${teamCount ? t("events.team_race") : t("events.wizard_use_team_race")} · ${cfg.finalDurationMin || 0} min` }, + { label: t("events.race_summary_validation"), value: lapWindow }, + { label: t("events.race_summary_follow_up"), value: `${cfg.followUpSec || 0}s` }, + ]; + } return [ { label: t("events.race_summary_preset"), value: selectedPreset?.label || t("events.preset_custom") }, { label: t("events.race_summary_participants"), value: String(participantCount || 0) }, { label: t("events.race_summary_created_sessions"), value: `P ${practiceCount} · Q ${qualCount} · F ${finalCount} · T ${teamCount}` }, { label: t("events.race_summary_qualifying"), value: `${cfg.qualifyingRounds || 0} x ${cfg.qualDurationMin || 0} min · ${cfg.carsPerHeat || 0}/heat · ${scoringLabel}` }, { label: t("events.race_summary_finals"), value: `${cfg.carsPerFinal || 0}/main · ${cfg.finalLegs || 0} leg · ${getStartModeLabel(cfg.finalStartMode || "position")}` }, + { label: t("events.race_summary_generation"), value: `${cfg.finalsSource === "practice" ? t("events.finals_from_practice") : t("events.finals_from_qualifying")} · bump ${cfg.bumpCount || 0}` }, { label: t("events.race_summary_validation"), value: lapWindow }, { label: t("events.race_summary_follow_up"), value: `${cfg.followUpSec || 0}s` }, ]; diff --git a/src/styles.css b/src/styles.css index d083b46..e52f5af 100644 --- a/src/styles.css +++ b/src/styles.css @@ -514,6 +514,16 @@ body { line-height: 1.35; } +.race-summary-card { + position: sticky; + top: 16px; +} + +.race-summary-card .panel-body { + display: grid; + gap: 10px; +} + .panel-header-inline { padding: 0; border: 0;