export function frameworkSkillSummaryKey(id) { return `framework_program:${id}` } export function moduleSkillSummaryKey(id) { return `training_module:${id}` } export function skillEntryFromSummary(summary, skillId) { if (!summary?.skills) return null return summary.skills.find((s) => String(s.skill_id) === String(skillId)) || null } export function maxSelectedSkillClubPercent(summary, skillIds = []) { if (!summary || !skillIds.length) return null let max = null for (const id of skillIds) { const sk = skillEntryFromSummary(summary, id) if (!sk) continue const pct = sk.universal_percent if (pct == null) continue if (max == null || pct > max) max = pct } return max } export function formatClubPercent(value) { if (value == null || !Number.isFinite(Number(value))) return '—' const n = Number(value) return n % 1 === 0 ? `${n}%` : `${n.toFixed(1)}%` } export function artifactTypeLabel(type) { if (type === 'framework_program') return 'Rahmenprogramm' if (type === 'training_module') return 'Modul' if (type === 'progression_graph') return 'Regressionspfad' return type || 'Artefakt' } export function artifactPath(ref) { if (!ref) return null if (ref.artifact_type === 'framework_program') { return `/planning/framework-programs/${ref.artifact_id}` } if (ref.artifact_type === 'training_module') { return `/planning/training-modules/${ref.artifact_id}` } return null } /** Zeilen für Kompakt-Anzeige: gewählte Fähigkeiten oder Top je Kategorie. */ export function compactSkillDisplayRows(summary, { skillIds = [], limit = 6 } = {}) { if (!summary) return [] if (skillIds.length) { return skillIds .map((id) => skillEntryFromSummary(summary, id)) .filter(Boolean) .sort((a, b) => (b.universal_percent ?? 0) - (a.universal_percent ?? 0)) .slice(0, limit) } return (summary.top_by_category || []).slice(0, limit) }