/** * Zentrales Findings-Panel für Progressionsgraph-QA (Phase B.2). */ import React, { useMemo, useState } from 'react' import { offerCanExpandSlots, offerNeedsNewSlot, offerSourceLabel, resolveOfferSlotIndex, } from '../utils/progressionGraphDraft' function severityStyle(pathQa) { if (!pathQa) return {} return { background: pathQa.overall_ok ? 'color-mix(in srgb, var(--accent) 8%, var(--surface2))' : 'color-mix(in srgb, var(--danger) 8%, var(--surface2))', } } function GapOfferCard({ offer, slotCount, draft, onApplyDraft, onInsertSlot, onGenerateAi, generatingOfferId, aiBusy, }) { const defaultSlot = resolveOfferSlotIndex(draft, offer) const [slotPick, setSlotPick] = useState( defaultSlot != null && Number.isFinite(defaultSlot) ? String(defaultSlot) : '', ) const needsInsert = offerNeedsNewSlot(offer) const canInsert = offerCanExpandSlots(draft, offer) const slotOptions = useMemo(() => { const rows = [] for (let i = 0; i < slotCount; i += 1) { rows.push({ value: String(i), label: `Slot ${i + 1}` }) } return rows }, [slotCount]) const applyToSlot = () => { const idx = slotPick !== '' ? Number(slotPick) : defaultSlot if (!Number.isFinite(idx)) { alert('Bitte einen Slot wählen.') return } onApplyDraft(offer, idx) } return (
{offer.rationale}
) : null} {offer.from_title && offer.to_title ? (Zwischen „{offer.from_title}“ und „{offer.to_title}“
) : null}Prüft den Slot-Stand und listet KI-Angebote für leere Stufen und Lücken.
{error ? ({error}
) : null} {pathQa ? ({pathQa.topic_coverage}
) : null} {Array.isArray(pathQa.issues) && pathQa.issues.length > 0 ? (Empfehlungen
{pathQa.off_topic_count} Schritt(e) ohne Bezug zum Pfad-Thema.
) : null}Noch keine Bewertung. Roadmap anlegen, dann „Graph bewerten“ oder „Übungen matchen“.
)}Keine offenen Angebote. Nach Match oder Bewertung erscheinen Vorschläge für leere Slots und Lücken.
) : (