diff --git a/src/components/CreateModal.jsx b/src/components/CreateModal.jsx new file mode 100644 index 0000000..25486d5 --- /dev/null +++ b/src/components/CreateModal.jsx @@ -0,0 +1,203 @@ +import { useState, useRef } from 'react'; +import { apiPost, apiUpload } from '../lib/api'; + +// Per-table create form definitions +const CREATE_FORMS = { + words: { + title: 'Neues Wort', + fields: [ + { key: 'titel_de', label: 'Titel DE', type: 'text', required: true, placeholder: 'z.B. Apfel' }, + { key: 'titel_en', label: 'Titel EN', type: 'text', required: false, placeholder: 'z.B. Apple' }, + { key: 'titel_sv', label: 'Titel SV', type: 'text', required: false, placeholder: 'z.B. Äpple' }, + { key: 'difficulty_level', label: 'Schwierigkeitsgrad', type: 'number', required: false, min: 1, max: 10 }, + ], + }, + pictures: { + title: 'Neues Bild', + fields: [ + { key: 'design', label: 'Design', type: 'text', required: true, placeholder: 'z.B. red apple on white background' }, + ], + hasImageUpload: true, + }, +}; + +export function hasCreateForm(tableKey) { + return !!CREATE_FORMS[tableKey]; +} + +function FieldInput({ field, value, onChange }) { + if (field.type === 'number') { + return ( + onChange(e.target.value === '' ? null : Number(e.target.value))} + placeholder={field.placeholder} + className="w-full border border-slate-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400" + /> + ); + } + return ( + onChange(e.target.value)} + placeholder={field.placeholder} + className="w-full border border-slate-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-400" + /> + ); +} + +export default function CreateModal({ tableKey, meta, onClose, onCreated }) { + const formDef = CREATE_FORMS[tableKey]; + const [values, setValues] = useState({}); + const [file, setFile] = useState(null); + const [preview, setPreview] = useState(null); + const [saving, setSaving] = useState(false); + const [error, setError] = useState(''); + const fileRef = useRef(); + + if (!formDef) return null; + + function handleFileChange(e) { + const f = e.target.files[0]; + if (!f) return; + setFile(f); + const url = URL.createObjectURL(f); + setPreview(url); + } + + async function handleSubmit(e) { + e.preventDefault(); + setError(''); + setSaving(true); + try { + // Build payload — skip nulls/empty strings for optional fields + const body = {}; + formDef.fields.forEach(f => { + if (values[f.key] != null && values[f.key] !== '') { + body[f.key] = values[f.key]; + } + }); + + // Step 1: Create record + const created = await apiPost(meta.endpoint, body); + + // Step 2: Upload image if provided + let final = created; + if (formDef.hasImageUpload && file) { + const fd = new FormData(); + fd.append('file', file); + final = await apiUpload(`${meta.endpoint}/${created.id}/upload`, fd); + } + + onCreated(final); + onClose(); + } catch (err) { + setError(err.message); + } finally { + setSaving(false); + } + } + + return ( +
Unbekannte Tabelle: {tableKey}