shinkan-jinkendo/frontend/src/components/ExerciseAiQuickCreateOffer.jsx
Lars c816e50c68
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
Refactor Exercise Creation Components to Utilize Custom Hook for Quick Create Fields
- 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.
2026-05-22 19:36:22 +02:00

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>
)
}