diff --git a/frontend/src/pages/TrainingCoachPage.jsx b/frontend/src/pages/TrainingCoachPage.jsx
index abdf806..10c9ecc 100644
--- a/frontend/src/pages/TrainingCoachPage.jsx
+++ b/frontend/src/pages/TrainingCoachPage.jsx
@@ -13,6 +13,7 @@ import {
coachBranchPicksStorageKey,
coachOutlineGroupsFromTimeline,
coachShouldPromptSplitRejoin,
+ coachShouldPromptSplitRejoinTransition,
durationOverridesMapFromDeltas,
findCoachTimelineJumpIndexForPhase,
flattenPlanTimeline,
@@ -549,6 +550,14 @@ export default function TrainingCoachPage() {
}
return
}
+ const nextIdx = safeStep + 1
+ if (nextIdx < timeline.length) {
+ const rejoinMid = coachShouldPromptSplitRejoinTransition(unit, timeline[safeStep], timeline[nextIdx])
+ if (rejoinMid) {
+ setSplitRejoinPrompt(rejoinMid)
+ return
+ }
+ }
setStep((s) => clampStep(s + 1, timeline.length))
}
@@ -620,7 +629,6 @@ export default function TrainingCoachPage() {
.trim()
}
await api.updateTrainingUnit(idNum, payload)
- await reloadUnit()
setTrainerAppend('')
try {
sessionStorage.removeItem(storageDeltasKey(idNum))
@@ -630,14 +638,15 @@ export default function TrainingCoachPage() {
} catch {
/* ignore */
}
- setSearchParams({}, { replace: true })
- setStep(0)
setDeltas({})
setBranchPicks({})
setStreamChoiceHint(null)
+ setSplitRejoinPrompt(null)
setCoachDebriefPhase(false)
- setSaveOk('Gespeichert.')
setDebriefOpen(false)
+ setSaveOk('Gespeichert.')
+ setSearchParams({}, { replace: true })
+ navigate(`/planning/run/${unitId}`, { replace: true })
} catch (e) {
setSaveOk(`Fehler: ${e.message || e}`)
} finally {
@@ -771,11 +780,11 @@ export default function TrainingCoachPage() {
? String(splitRejoinPrompt.phaseTitle).trim()
: `Phase ${splitRejoinPrompt.phaseOrderIndex}`}
{' — '}
- alle Gruppen fertig?
+ alle Gruppen zusammen?
- Diese Phase hat mehrere Streams. Kurz mit dem anderen Trainer klären, dann gemeinsam Ist-Zeiten und Speichern
- (gilt auch, wenn danach kein weiterer Block mehr kommt).
+ Diese Phase hat mehrere Streams. Kurz mit dem anderen Trainer klären, dann gemeinsam weitermachen. Ist-Zeiten
+ und Speichern erfolgen in der Nachbereitung am Ende der Einheit.
{splitRejoinPrompt.streams.map((st) => (
@@ -786,22 +795,36 @@ export default function TrainingCoachPage() {
))}
- {
- setSplitRejoinPrompt(null)
- setCoachDebriefPhase(true)
- try {
- sessionStorage.setItem(storageDebriefKey(idNum), '1')
- } catch {
- /* ignore */
- }
- }}
- >
- Alle Gruppen fertig — zur Nachbereitung
-
+ {safeStep < timeline.length - 1 ? (
+ {
+ setSplitRejoinPrompt(null)
+ setStep((s) => clampStep(s + 1, timeline.length))
+ }}
+ >
+ Gruppen zusammengeführt — weiter mit dem Plan
+
+ ) : (
+ {
+ setSplitRejoinPrompt(null)
+ setCoachDebriefPhase(true)
+ try {
+ sessionStorage.setItem(storageDebriefKey(idNum), '1')
+ } catch {
+ /* ignore */
+ }
+ }}
+ >
+ Alle Gruppen fertig — zur Nachbereitung
+
+ )}
setSplitRejoinPrompt(null)}>
Zurück — andere Gruppe läuft noch
@@ -819,7 +842,9 @@ export default function TrainingCoachPage() {
}
}}
>
- Ausnahme: trotzdem zur Nachbereitung
+ {safeStep < timeline.length - 1
+ ? 'Ausnahme: jetzt schon zur Nachbereitung'
+ : 'Ausnahme: trotzdem zur Nachbereitung'}
diff --git a/frontend/src/utils/trainingPlanUtils.js b/frontend/src/utils/trainingPlanUtils.js
index 616de23..df92ca6 100644
--- a/frontend/src/utils/trainingPlanUtils.js
+++ b/frontend/src/utils/trainingPlanUtils.js
@@ -519,6 +519,20 @@ export function coachShouldPromptSplitRejoin(unit, lastTimelineEntry) {
}
}
+/**
+ * Nach dem letzten Block eines gewählten Streams: Rückfrage vor Ganzgruppenphase oder vor dem nächsten Split,
+ * wenn die aktuelle Parallelphase mehrere Streams hat.
+ */
+export function coachShouldPromptSplitRejoinTransition(unit, currentEntry, nextEntry) {
+ if (!currentEntry || !nextEntry) return null
+ const cRm = currentEntry.runMeta
+ if (!cRm || cRm.kind !== 'parallel' || cRm.streamOrder == null) return null
+ const intoWholeGroup = nextEntry.runMeta?.kind === 'whole_group'
+ const intoNextSplit = nextEntry.entryKind === COACH_ENTRY_BRANCH_GATE
+ if (!intoWholeGroup && !intoNextSplit) return null
+ return coachShouldPromptSplitRejoin(unit, currentEntry)
+}
+
export function summarizeTimelineEntry(ent) {
if (!ent) return ''
if (ent.entryKind === COACH_ENTRY_BRANCH_GATE) {