This commit is contained in:
larssand
2026-08-24 21:28:38 +02:00
parent 355a1ad3b0
commit 3aeb77a042
13 changed files with 642 additions and 8 deletions

View File

@@ -5,12 +5,14 @@ export function renderTrainingView(deps) {
t,
escapeHtml,
formatLap,
formatRaceClock,
uid,
saveState,
renderView,
normalizeTrainingState,
syncTrainingLedger,
buildDriverTrainingStats,
buildDriverActivePracticeStats,
buildTrainingRecommendation,
getTrainingGoalProgress,
getNextTrainingMilestone,
@@ -39,6 +41,7 @@ export function renderTrainingView(deps) {
const selectedDriver = drivers.find((driver) => driver.id === selectedDriverId);
const stats = buildDriverTrainingStats(state, selectedDriverId);
const activePractice = buildDriverActivePracticeStats(state, selectedDriverId);
const recommendation = buildTrainingRecommendation(stats);
const nextMilestone = getNextTrainingMilestone(stats);
const goals = state.training.goals.filter((goal) => goal.driverId === selectedDriverId);
@@ -119,12 +122,41 @@ export function renderTrainingView(deps) {
<h3>${escapeHtml(selectedDriver.name)}</h3>
<p>${escapeHtml(t("training.intro"))}</p>
</div>
<label class="training-driver-select">
<span>${escapeHtml(t("training.driver"))}</span>
<select id="training-driver">${driverOptions}</select>
</label>
<div class="training-hero-controls">
<label class="training-driver-select">
<span>${escapeHtml(t("training.driver"))}</span>
<select id="training-driver">${driverOptions}</select>
</label>
<div class="actions training-hero-actions">
${profileShare ? `
<button class="btn btn-primary" id="trainingHeroOpenProfile" type="button">${escapeHtml(t("training.start_personal"))}</button>
<button class="btn" id="trainingHeroCopyProfile" type="button">${escapeHtml(t("training.copy_mobile_link"))}</button>
` : `
<button class="btn btn-primary" id="trainingHeroEnableProfile" type="button">${escapeHtml(t("training.create_personal_link"))}</button>
`}
</div>
</div>
</section>
${activePractice ? `
<section class="training-live-card">
<div class="training-live-head">
<div>
<span class="training-kicker">${escapeHtml(t("training.live_now"))}</span>
<h3>${escapeHtml(activePractice.sessionName || t("training.active_practice"))}</h3>
</div>
<span class="badge badge-online">${escapeHtml(t("training.shared_practice"))}</span>
</div>
<div class="training-live-stats">
${trainingInsight(t("training.session_laps"), String(activePractice.laps))}
${trainingInsight(t("training.best_lap"), formatLap(activePractice.bestLapMs))}
${trainingInsight(t("training.average_lap"), formatLap(activePractice.averageLapMs))}
${trainingInsight(t("training.latest_lap"), formatLap(activePractice.lastLapMs))}
</div>
<p>${escapeHtml(t("training.live_practice_hint"))}</p>
</section>
` : ""}
<div class="grid cols-4 training-stats">
${trainingStat(t("training.total_laps"), String(stats.totalLaps), t("training.valid_laps"))}
${trainingStat(t("training.training_days"), String(stats.trainingDays), t("training.sessions_count", { sessions: stats.totalSessions }))}
@@ -221,6 +253,10 @@ export function renderTrainingView(deps) {
${trainingInsight(t("training.recent_average"), formatLap(stats.recentAverageMs))}
${trainingInsight(t("training.controlled_streak"), t("training.lap_count", { laps: stats.controlledLapStreak }))}
${trainingInsight(t("training.last_activity"), lastActivity)}
${trainingInsight(t("training.stints"), String(stats.stintCount))}
${trainingInsight(t("training.best_three"), stats.bestThreeConsecutive ? `3/${formatRaceClock(stats.bestThreeConsecutive.totalMs)}` : "-")}
${trainingInsight(t("training.best_five"), stats.bestFiveMinuteResult ? `${stats.bestFiveMinuteResult.lapCount}/${formatRaceClock(stats.bestFiveMinuteResult.totalMs)}` : "-")}
${trainingInsight(t("training.five_avg_pace"), stats.bestFiveMinuteResult ? formatLap(stats.bestFiveMinuteResult.averageLapMs) : "-")}
</section>
<div class="training-section-title">
<h3>${escapeHtml(t("training.history"))}</h3>
@@ -255,6 +291,18 @@ export function renderTrainingView(deps) {
renderView();
});
document.getElementById("trainingHeroEnableProfile")?.addEventListener("click", () => {
replacePublicProfileShare(state, selectedDriverId);
saveState();
renderView();
});
document.getElementById("trainingHeroOpenProfile")?.addEventListener("click", () => {
window.open(publicProfileUrl, "_blank", "noopener,noreferrer");
});
document.getElementById("trainingHeroCopyProfile")?.addEventListener("click", async () => {
await copyText(publicProfileUrl);
});
document.querySelectorAll(".training-preset").forEach((button) => {
button.addEventListener("click", () => {
const input = document.querySelector('#training-goal-form input[name="targetLaps"]');