add stat
This commit is contained in:
@@ -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"]');
|
||||
|
||||
Reference in New Issue
Block a user