/** Minimaler Snapshot einer Übung für die modulübergreifende Auswahl (filterunabhängig). */ export function snapshotExerciseForSelection(exercise) { if (!exercise || exercise.id == null) return null const id = Number(exercise.id) if (!Number.isFinite(id) || id < 1) return null return { id, title: exercise.title || '', summary: exercise.summary || '', visibility: exercise.visibility, status: exercise.status, exercise_kind: exercise.exercise_kind, created_by: exercise.created_by, focus_area: exercise.focus_area, focus_area_names: exercise.focus_area_names, style_direction_names: exercise.style_direction_names, training_type_names: exercise.training_type_names, media_count: exercise.media_count, variant_count: exercise.variant_count, media: Array.isArray(exercise.media) ? exercise.media : [], } } export function normalizeSelectedEntries(raw) { if (!Array.isArray(raw)) return [] const out = [] const seen = new Set() for (const item of raw) { const snap = snapshotExerciseForSelection(item) if (!snap || seen.has(snap.id)) continue seen.add(snap.id) out.push(snap) } return out } export function mergeSelectedWithListEntries(selectedEntries, exercises) { const byId = new Map() for (const e of exercises || []) { const id = Number(e?.id) if (Number.isFinite(id) && id > 0) byId.set(id, e) } return (selectedEntries || []).map((entry) => byId.get(Number(entry.id)) || entry) } export function moduleItemToPayload(row, orderIndex) { if ((row?.item_type || 'exercise') === 'note') { return { item_type: 'note', order_index: orderIndex, note_body: row.note_body ?? '', } } const eid = Number(row.exercise_id) if (!Number.isFinite(eid) || eid < 1) return null const vidRaw = row.exercise_variant_id const vid = vidRaw === '' || vidRaw == null || row.exercise_kind === 'combination' ? null : Number(vidRaw) return { item_type: 'exercise', order_index: orderIndex, exercise_id: eid, exercise_variant_id: Number.isFinite(vid) && vid > 0 ? vid : null, planned_duration_min: row.planned_duration_min !== '' && row.planned_duration_min != null ? Number(row.planned_duration_min) : null, notes: row.notes != null && String(row.notes).trim() ? String(row.notes).trim() : null, } } export function buildRowsPayload(rows) { return rows .map((row, idx) => moduleItemToPayload( { ...row, exercise_id: row.exercise_id, exercise_variant_id: row.exercise_variant_id, planned_duration_min: row.planned_duration_min, notes: row.notes, exercise_kind: row.exercise_kind, }, idx ) ) .filter(Boolean) }