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:
@@ -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,12 +686,31 @@ 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">
|
||||||
|
<div className="flex gap-2">
|
||||||
<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>
|
<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>
|
||||||
<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={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">
|
||||||
{saving ? 'Speichern…' : '✓ Änderungen speichern'}
|
{saving ? 'Speichern…' : '✓ Speichern'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -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">
|
||||||
|
|||||||
Reference in New Issue
Block a user