Enhance TrainingCoachPage and trainingPlanUtils with session storage management and phase handling improvements
All checks were successful
Deploy Development / deploy (push) Successful in 42s
Test Suite / pytest-backend (push) Successful in 37s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 12s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m8s

- Introduced a new function in TrainingCoachPage to clear session storage for coach steps, improving state management during training sessions.
- Updated the sectionsWithPlanLocForDisplay function in trainingPlanUtils to include logic for determining the maximum phase order index, enhancing phase handling.
- Enhanced the mapping of sections to include default plan locations for parallel phases, optimizing data representation and user experience.
This commit is contained in:
Lars 2026-05-15 17:01:00 +02:00
parent 73ac2218c7
commit 5e5350d5ac
2 changed files with 45 additions and 1 deletions

View File

@ -27,6 +27,18 @@ function storageStepKey(unitId, mergedPicks) {
return `sj_coach_step_${unitId}_${coachBranchPicksStepStorageSuffix(mergedPicks)}`
}
function clearCoachStepStorageForUnit(unitId) {
const pref = `sj_coach_step_${unitId}_`
try {
for (let i = sessionStorage.length - 1; i >= 0; i -= 1) {
const k = sessionStorage.key(i)
if (k && k.startsWith(pref)) sessionStorage.removeItem(k)
}
} catch {
/* ignore */
}
}
function storageDeltasKey(unitId) {
return `sj_coach_deltas_${unitId}`
}
@ -614,9 +626,12 @@ export default function TrainingCoachPage() {
sessionStorage.removeItem(storageDeltasKey(idNum))
sessionStorage.removeItem(storageDebriefKey(idNum))
sessionStorage.removeItem(coachBranchPicksStorageKey(idNum))
clearCoachStepStorageForUnit(idNum)
} catch {
/* ignore */
}
setSearchParams({}, { replace: true })
setStep(0)
setDeltas({})
setBranchPicks({})
setStreamChoiceHint(null)

View File

@ -5,6 +5,7 @@
import {
buildPlanPayloadForSave,
cloneJsonSerializablePlanningProfile,
defaultPlanLocWholeGroup,
inheritPlanLocForPhasedSave,
phaseRunsFromSections,
sectionIndicesForParallelStream,
@ -94,6 +95,16 @@ function planLocBySectionIdFromPhases(phases) {
return byId
}
function maxPhaseOrderIndexFromNestedPhases(phases) {
let m = -1
if (!Array.isArray(phases)) return m
for (const ph of phases) {
const po = Number(ph.order_index ?? ph.orderIndex ?? 0)
if (Number.isFinite(po)) m = Math.max(m, po)
}
return m
}
export function sectionsWithPlanLocForDisplay(unit) {
const sorted = sortedSections(unit)
const byId = planLocBySectionIdFromPhases(unit?.phases)
@ -105,7 +116,25 @@ export function sectionsWithPlanLocForDisplay(unit) {
if (s.planLoc && s.planLoc.phaseKind) return s
return { ...s }
})
return inheritPlanLocForPhasedSave(merged)
const inherited = inheritPlanLocForPhasedSave(merged)
const maxPhPo = maxPhaseOrderIndexFromNestedPhases(unit?.phases)
return inherited.map((s) => {
const sid = s.id != null ? Number(s.id) : NaN
if (!Number.isFinite(sid) || byId.has(sid)) return s
const pl = s.planLoc
if (pl?.phaseKind === 'parallel') {
const po = maxPhPo >= 0 ? maxPhPo + 1 : 0
return {
...s,
planLoc: {
...defaultPlanLocWholeGroup(po),
phaseTitle: pl.phaseTitle ?? null,
phaseGuidanceNotes: pl.phaseGuidanceNotes ?? null,
},
}
}
return s
})
}
/**