2026-05-22 19:24:36 +02:00
|
|
|
import React from 'react'
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Inline-Angebot: aus Suchstring neue Übung per KI anlegen (Fokusbereich + optional Titel/Skizze).
|
|
|
|
|
*/
|
2026-05-23 06:16:37 +02:00
|
|
|
/** Kompakter Einstieg unter Trefferliste — expandiert zum vollen Formular. */
|
|
|
|
|
export function ExerciseAiQuickCreateTeaser({ onExpand, disabled = false }) {
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className="card"
|
|
|
|
|
style={{
|
|
|
|
|
padding: '12px 16px',
|
|
|
|
|
marginTop: 16,
|
|
|
|
|
borderColor: 'var(--border)',
|
|
|
|
|
background: 'var(--surface2)',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
style={{
|
|
|
|
|
display: 'flex',
|
|
|
|
|
flexWrap: 'wrap',
|
|
|
|
|
gap: '10px 12px',
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
justifyContent: 'space-between',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<span style={{ fontSize: '0.92rem', lineHeight: 1.45 }}>
|
|
|
|
|
<strong>Nichts Richtiges dabei?</strong>{' '}
|
|
|
|
|
<span style={{ color: 'var(--text2)' }}>Neue Übung mit KI anlegen und direkt übernehmen.</span>
|
|
|
|
|
</span>
|
|
|
|
|
<button type="button" className="btn btn-secondary" disabled={disabled} onClick={() => onExpand?.()}>
|
|
|
|
|
Neue Übung anlegen
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 19:24:36 +02:00
|
|
|
export default function ExerciseAiQuickCreateOffer({
|
|
|
|
|
searchLabel,
|
|
|
|
|
title,
|
|
|
|
|
onTitleChange,
|
|
|
|
|
sketch,
|
|
|
|
|
onSketchChange,
|
|
|
|
|
focusAreaId,
|
|
|
|
|
onFocusAreaChange,
|
|
|
|
|
focusAreas = [],
|
|
|
|
|
catalogsReady = true,
|
|
|
|
|
busy = false,
|
|
|
|
|
error = '',
|
|
|
|
|
onRunAi,
|
2026-05-22 19:36:22 +02:00
|
|
|
showSketchField = true,
|
|
|
|
|
sketchOptional = true,
|
2026-05-22 19:24:36 +02:00
|
|
|
hint,
|
2026-05-23 06:16:37 +02:00
|
|
|
headline,
|
2026-05-22 19:24:36 +02:00
|
|
|
}) {
|
|
|
|
|
const canRun =
|
|
|
|
|
!busy &&
|
|
|
|
|
(title || '').trim().length >= 3 &&
|
2026-05-22 19:36:22 +02:00
|
|
|
focusAreaId &&
|
|
|
|
|
(sketchOptional || (sketch || '').trim().length > 0)
|
2026-05-22 19:24:36 +02:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className="card"
|
|
|
|
|
style={{
|
|
|
|
|
padding: '14px 16px',
|
|
|
|
|
marginBottom: '12px',
|
|
|
|
|
borderColor: 'var(--accent-dark, rgba(29,158,117,0.35))',
|
|
|
|
|
background: 'var(--surface2)',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<strong style={{ display: 'block', marginBottom: '6px', fontSize: '0.95rem' }}>
|
2026-05-23 06:16:37 +02:00
|
|
|
{headline || 'Keine passende Übung gefunden'}
|
2026-05-22 19:24:36 +02:00
|
|
|
</strong>
|
|
|
|
|
<p style={{ margin: '0 0 12px', fontSize: '13px', color: 'var(--text2)', lineHeight: 1.45 }}>
|
|
|
|
|
{hint ||
|
|
|
|
|
(searchLabel
|
|
|
|
|
? `Für „${searchLabel}“ lässt sich eine neue Übung mit KI vorschlagen — Texte danach bearbeiten und speichern.`
|
|
|
|
|
: 'Neue Übung mit KI vorschlagen — Texte danach bearbeiten und speichern.')}
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<div style={{ display: 'grid', gap: '10px' }}>
|
|
|
|
|
<div>
|
|
|
|
|
<label className="form-label" htmlFor="ex-ai-quick-title">
|
|
|
|
|
Titel *
|
|
|
|
|
</label>
|
|
|
|
|
<input
|
|
|
|
|
id="ex-ai-quick-title"
|
|
|
|
|
type="text"
|
|
|
|
|
className="form-input"
|
|
|
|
|
value={title}
|
|
|
|
|
onChange={(e) => onTitleChange(e.target.value)}
|
|
|
|
|
autoComplete="off"
|
|
|
|
|
maxLength={300}
|
|
|
|
|
placeholder="Titel der neuen Übung"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<label className="form-label" htmlFor="ex-ai-quick-focus">
|
|
|
|
|
Fokusbereich *
|
|
|
|
|
</label>
|
|
|
|
|
<select
|
|
|
|
|
id="ex-ai-quick-focus"
|
|
|
|
|
className="form-input"
|
|
|
|
|
value={focusAreaId}
|
|
|
|
|
onChange={(e) => onFocusAreaChange(e.target.value)}
|
|
|
|
|
disabled={!catalogsReady}
|
|
|
|
|
>
|
|
|
|
|
<option value="">— wählen —</option>
|
|
|
|
|
{(focusAreas || []).map((fa) => (
|
|
|
|
|
<option key={fa.id} value={String(fa.id)}>
|
|
|
|
|
{`${fa.icon ? `${fa.icon} ` : ''}${fa.name || `#${fa.id}`}`.trim()}
|
|
|
|
|
</option>
|
|
|
|
|
))}
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{showSketchField ? (
|
|
|
|
|
<div>
|
|
|
|
|
<label className="form-label" htmlFor="ex-ai-quick-sketch">
|
2026-05-22 19:36:22 +02:00
|
|
|
Kurzbeschreibung / Idee{sketchOptional ? ' (optional)' : ' *'}
|
2026-05-22 19:24:36 +02:00
|
|
|
</label>
|
|
|
|
|
<textarea
|
|
|
|
|
id="ex-ai-quick-sketch"
|
|
|
|
|
className="form-input"
|
2026-05-22 19:36:22 +02:00
|
|
|
rows={4}
|
2026-05-22 19:24:36 +02:00
|
|
|
value={sketch}
|
|
|
|
|
onChange={(e) => onSketchChange(e.target.value)}
|
2026-05-22 19:36:22 +02:00
|
|
|
placeholder={
|
|
|
|
|
sketchOptional
|
|
|
|
|
? 'Leer lassen: KI schlägt Inhalt frei vor (Titel + Fokus). Oder kurz beschreiben, was die Übung tun soll …'
|
|
|
|
|
: 'Kurze Beschreibung für die KI …'
|
|
|
|
|
}
|
2026-05-22 19:24:36 +02:00
|
|
|
/>
|
2026-05-22 19:36:22 +02:00
|
|
|
{searchLabel && !(sketch || '').trim() ? (
|
|
|
|
|
<p style={{ margin: '6px 0 0', fontSize: '12px', color: 'var(--text3)' }}>
|
|
|
|
|
Suchbegriff: „{searchLabel}“ — wird als Titel übernommen.
|
|
|
|
|
</p>
|
|
|
|
|
) : null}
|
2026-05-22 19:24:36 +02:00
|
|
|
</div>
|
2026-05-22 19:36:22 +02:00
|
|
|
) : null}
|
2026-05-22 19:24:36 +02:00
|
|
|
|
|
|
|
|
{error ? (
|
|
|
|
|
<p style={{ margin: 0, fontSize: '13px', color: 'var(--danger)' }}>{error}</p>
|
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
|
|
|
|
<button type="button" className="btn btn-primary" disabled={!canRun} onClick={() => onRunAi()}>
|
|
|
|
|
{busy ? 'KI erzeugt Vorschlag…' : 'Mit KI anlegen'}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|