feat: delete pair button in EditPairForm with confirmation

Two-step: "Pair löschen" → confirm "Wirklich löschen" before DELETE /pairs/:id.
On success closes the form and reloads the pairs list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 14:40:38 +02:00
parent d57313084f
commit da3d7319a6

View File

@@ -1,6 +1,6 @@
import { useEffect, useState, useRef, useCallback, useMemo } from 'react'; import { useEffect, useState, useRef, useCallback, useMemo } from 'react';
import Layout from '../components/Layout'; import Layout from '../components/Layout';
import { apiFetch, apiPost, apiPatch, apiLink, apiUnlink, getUserLang } from '../lib/api'; import { apiFetch, apiPost, apiPatch, apiLink, apiUnlink, apiDelete, getUserLang } from '../lib/api';
import { STATUS_COLORS } from '../lib/tables'; import { STATUS_COLORS } from '../lib/tables';
// ─── Word / placeholder helpers ─────────────────────────────────────────────── // ─── Word / placeholder helpers ───────────────────────────────────────────────
@@ -425,7 +425,7 @@ function PairForm({ objectId, allObjects, onPairSaved }) {
// ─── EditPairForm ───────────────────────────────────────────────────────────── // ─── EditPairForm ─────────────────────────────────────────────────────────────
function EditPairForm({ pair, allObjects, onSaved, onCancel }) { function EditPairForm({ pair, allObjects, onSaved, onCancel, onDeleted }) {
const lang = getUserLang(); const lang = getUserLang();
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
@@ -441,9 +441,20 @@ function EditPairForm({ pair, allObjects, onSaved, onCancel }) {
const [selection, setSelection] = useState(''); const [selection, setSelection] = useState('');
const [wordInput, setWordInput] = useState(''); const [wordInput, setWordInput] = useState('');
const [creatingWord, setCreatingWord] = useState(false); const [creatingWord, setCreatingWord] = useState(false);
const [confirmDelete, setConfirmDelete] = useState(false);
const [deleting, setDeleting] = useState(false);
useEffect(() => { setWordInput(selection); }, [selection]); useEffect(() => { setWordInput(selection); }, [selection]);
async function handleDelete() {
setDeleting(true);
try {
await apiDelete('/pairs', pair.id);
onDeleted(pair.id);
} catch (e) { alert('Fehler beim Löschen: ' + e.message); }
finally { setDeleting(false); }
}
useEffect(() => { useEffect(() => {
async function load() { async function load() {
try { try {
@@ -675,11 +686,30 @@ function EditPairForm({ pair, allObjects, onSaved, onCancel }) {
</div> </div>
)} )}
</div> </div>
<div className="flex gap-2 pt-2 border-t border-amber-100"> <div className="pt-2 border-t border-amber-100 space-y-1.5">
<button onClick={onCancel} className="flex-1 py-1.5 text-xs font-medium rounded-lg border border-slate-300 text-slate-600 hover:bg-slate-50 transition-colors">Abbrechen</button> <div className="flex gap-2">
<button onClick={handleSave} disabled={saving} className="flex-1 py-1.5 text-xs font-medium rounded-lg bg-amber-500 hover:bg-amber-600 disabled:opacity-40 text-white transition-colors"> <button onClick={onCancel} className="flex-1 py-1.5 text-xs font-medium rounded-lg border border-slate-300 text-slate-600 hover:bg-slate-50 transition-colors">Abbrechen</button>
{saving ? 'Speichern' : ' Änderungen speichern'} <button onClick={handleSave} disabled={saving} className="flex-1 py-1.5 text-xs font-medium rounded-lg bg-amber-500 hover:bg-amber-600 disabled:opacity-40 text-white transition-colors">
</button> {saving ? 'Speichern' : ' Speichern'}
</button>
</div>
{!confirmDelete ? (
<button onClick={() => setConfirmDelete(true)}
className="w-full py-1.5 text-xs font-medium rounded-lg border border-red-200 text-red-400 hover:bg-red-50 hover:text-red-600 hover:border-red-300 transition-colors">
🗑 Pair löschen
</button>
) : (
<div className="flex gap-2">
<button onClick={() => setConfirmDelete(false)}
className="flex-1 py-1.5 text-xs rounded-lg border border-slate-300 text-slate-500 hover:bg-slate-50 transition-colors">
Abbrechen
</button>
<button onClick={handleDelete} disabled={deleting}
className="flex-1 py-1.5 text-xs font-semibold rounded-lg bg-red-500 hover:bg-red-600 disabled:opacity-50 text-white transition-colors">
{deleting ? 'Löschen' : ' Wirklich löschen'}
</button>
</div>
)}
</div> </div>
</div> </div>
); );
@@ -848,7 +878,8 @@ function PairsPanel({ selectedObject, allObjects, objectPairs, loadingPairs, onP
{editingId === pair.id ? ( {editingId === pair.id ? (
<EditPairForm pair={pair} allObjects={allObjects} <EditPairForm pair={pair} allObjects={allObjects}
onSaved={() => { setEditingId(null); onPairsReload(); }} onSaved={() => { setEditingId(null); onPairsReload(); }}
onCancel={() => setEditingId(null)} /> onCancel={() => setEditingId(null)}
onDeleted={id => { setEditingId(null); onPairsReload(); }} />
) : ( ) : (
<div className="rounded-lg border border-slate-200 p-3 bg-slate-50 space-y-1.5"> <div className="rounded-lg border border-slate-200 p-3 bg-slate-50 space-y-1.5">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">