All checks were successful
Deploy Development / deploy (push) Successful in 44s
Test Suite / pytest-backend (push) Successful in 40s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 14s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m20s
- Updated ExerciseAiQuickCreateOffer to set showSketchField to true by default and introduced sketchOptional prop for improved flexibility in exercise creation. - Refactored ExercisePickerModal and ExercisesListPageRoot to leverage useExerciseAiQuickCreateFields hook, simplifying state management for quick create fields. - Removed deprecated parsing logic and streamlined error handling for sketch input, enhancing user experience during exercise creation. - Improved placeholder text and labels for clarity, ensuring better guidance for users when providing input for AI-generated exercises.
124 lines
3.9 KiB
JavaScript
124 lines
3.9 KiB
JavaScript
import React from 'react'
|
|
|
|
/**
|
|
* Inline-Angebot: aus Suchstring neue Übung per KI anlegen (Fokusbereich + optional Titel/Skizze).
|
|
*/
|
|
export default function ExerciseAiQuickCreateOffer({
|
|
searchLabel,
|
|
title,
|
|
onTitleChange,
|
|
sketch,
|
|
onSketchChange,
|
|
focusAreaId,
|
|
onFocusAreaChange,
|
|
focusAreas = [],
|
|
catalogsReady = true,
|
|
busy = false,
|
|
error = '',
|
|
onRunAi,
|
|
showSketchField = true,
|
|
sketchOptional = true,
|
|
hint,
|
|
}) {
|
|
const canRun =
|
|
!busy &&
|
|
(title || '').trim().length >= 3 &&
|
|
focusAreaId &&
|
|
(sketchOptional || (sketch || '').trim().length > 0)
|
|
|
|
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' }}>
|
|
Keine passende Übung gefunden
|
|
</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">
|
|
Kurzbeschreibung / Idee{sketchOptional ? ' (optional)' : ' *'}
|
|
</label>
|
|
<textarea
|
|
id="ex-ai-quick-sketch"
|
|
className="form-input"
|
|
rows={4}
|
|
value={sketch}
|
|
onChange={(e) => onSketchChange(e.target.value)}
|
|
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 …'
|
|
}
|
|
/>
|
|
{searchLabel && !(sketch || '').trim() ? (
|
|
<p style={{ margin: '6px 0 0', fontSize: '12px', color: 'var(--text3)' }}>
|
|
Suchbegriff: „{searchLabel}“ — wird als Titel übernommen.
|
|
</p>
|
|
) : null}
|
|
</div>
|
|
) : null}
|
|
|
|
{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>
|
|
)
|
|
}
|