feat: 'Übersetzungen nachholen' + 'Audios nachholen' immer verfügbar
Beide Nachhol-Aktionen jetzt dauerhaft im Karten-Header (nicht nur bei unvollständigen Pairs) — Reihenfolge Übersetzen → Audio, da Audio alle Sprachen braucht. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -167,6 +167,7 @@ function ReadyCard({ bundle, onPublished, onRefresh }) {
|
||||
const [done, setDone] = useState(null);
|
||||
const [assigning, setAssigning] = useState(null);
|
||||
const [audioFilling, setAudioFilling] = useState(false);
|
||||
const [translateFilling, setTranslateFilling] = useState(false);
|
||||
|
||||
if (!bundle) {
|
||||
return (
|
||||
@@ -209,6 +210,16 @@ function ReadyCard({ bundle, onPublished, onRefresh }) {
|
||||
finally { setAssigning(null); }
|
||||
}
|
||||
|
||||
async function fillTranslations() {
|
||||
setTranslateFilling(true); setError(null);
|
||||
try {
|
||||
const res = await apiPost(`/pipeline/picture/${bundle.picture.id}/translate-fill`, {});
|
||||
if (res.failed) setError(`${res.translated} Pairs übersetzt, ${res.failed} fehlgeschlagen: ${res.errors?.[0]?.error || ''}`);
|
||||
await onRefresh?.();
|
||||
} catch (e) { setError(e.payload?.error || e.message); }
|
||||
finally { setTranslateFilling(false); }
|
||||
}
|
||||
|
||||
async function fillAudio() {
|
||||
setAudioFilling(true); setError(null);
|
||||
try {
|
||||
@@ -261,16 +272,21 @@ function ReadyCard({ bundle, onPublished, onRefresh }) {
|
||||
{bundle.objects.length} Objekt{bundle.objects.length !== 1 ? 'e' : ''} · {allPairs.length} Pairs · {wordCount} Wörter
|
||||
</div>
|
||||
{incompletePairs.length > 0 && (
|
||||
<div className="flex items-center gap-2 mt-1">
|
||||
<span className="text-xs text-amber-600">
|
||||
⚠ {incompletePairs.length} Pair{incompletePairs.length !== 1 ? 's' : ''} unvollständig (Text/Audio)
|
||||
</span>
|
||||
<button onClick={fillAudio} disabled={audioFilling}
|
||||
className="text-[11px] px-2 py-0.5 rounded-full border border-amber-300 bg-amber-50 text-amber-700 hover:bg-amber-100 disabled:opacity-50">
|
||||
{audioFilling ? 'Generiere…' : '🔊 Fehlende Audios generieren'}
|
||||
</button>
|
||||
<div className="text-xs text-amber-600 mt-1">
|
||||
⚠ {incompletePairs.length} Pair{incompletePairs.length !== 1 ? 's' : ''} unvollständig (Text/Audio) — erst Übersetzungen, dann Audios nachholen
|
||||
</div>
|
||||
)}
|
||||
{/* Nachhol-Aktionen immer verfügbar: Reihenfolge Übersetzen → Audio (Audio braucht alle Sprachen) */}
|
||||
<div className="flex flex-wrap items-center gap-1.5 mt-2">
|
||||
<button onClick={fillTranslations} disabled={translateFilling || audioFilling}
|
||||
className="text-[11px] px-2 py-0.5 rounded-full border border-indigo-200 bg-indigo-50 text-indigo-700 hover:bg-indigo-100 disabled:opacity-50">
|
||||
{translateFilling ? 'Übersetze…' : '🌍 Übersetzungen nachholen'}
|
||||
</button>
|
||||
<button onClick={fillAudio} disabled={audioFilling || translateFilling}
|
||||
className="text-[11px] px-2 py-0.5 rounded-full border border-amber-300 bg-amber-50 text-amber-700 hover:bg-amber-100 disabled:opacity-50">
|
||||
{audioFilling ? 'Generiere…' : '🔊 Fehlende Audios generieren'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<span className="shrink-0 text-xs font-medium bg-emerald-100 text-emerald-700 rounded-full px-2.5 py-1">bereit</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user