"use client"; import { useState, useEffect, useCallback, useMemo } from "react"; import { Card, CardHeader, CardTitle, CardDescription, CardContent, Button, FormField, FormInput, FormSelect, Icon } from "@/app/components/ui"; import { StatusMappingDto } from "@/lib/api"; import { useTranslation } from "@/lib/i18n/context"; export function StatusMappingsCard() { const { t } = useTranslation(); const [mappings, setMappings] = useState([]); const [targetStatuses, setTargetStatuses] = useState([]); const [providerStatuses, setProviderStatuses] = useState([]); const [newTargetName, setNewTargetName] = useState(""); const [loading, setLoading] = useState(true); const loadData = useCallback(async () => { try { const [mRes, sRes, pRes] = await Promise.all([ fetch("/api/settings/status-mappings").then((r) => r.ok ? r.json() : []), fetch("/api/series/statuses").then((r) => r.ok ? r.json() : []), fetch("/api/series/provider-statuses").then((r) => r.ok ? r.json() : []), ]); setMappings(mRes); setTargetStatuses(sRes); setProviderStatuses(pRes); } catch { // ignore } finally { setLoading(false); } }, []); useEffect(() => { loadData(); }, [loadData]); // Group mappings by target status (only those with a non-null mapped_status) const grouped = useMemo(() => { const map = new Map(); for (const m of mappings) { if (m.mapped_status) { const list = map.get(m.mapped_status) || []; list.push(m); map.set(m.mapped_status, list); } } return map; }, [mappings]); // Unmapped = mappings with null mapped_status + provider statuses not in status_mappings at all const knownProviderStatuses = useMemo( () => new Set(mappings.map((m) => m.provider_status)), [mappings], ); const unmappedMappings = useMemo( () => mappings.filter((m) => !m.mapped_status), [mappings], ); const newProviderStatuses = useMemo( () => providerStatuses.filter((ps) => !knownProviderStatuses.has(ps)), [providerStatuses, knownProviderStatuses], ); // All possible targets = existing statuses from DB + custom ones added locally const [customTargets, setCustomTargets] = useState([]); const allTargets = useMemo(() => { const set = new Set([...targetStatuses, ...customTargets]); return [...set].sort(); }, [targetStatuses, customTargets]); async function handleAssign(providerStatus: string, targetStatus: string) { if (!providerStatus || !targetStatus) return; try { const res = await fetch("/api/settings/status-mappings", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ provider_status: providerStatus, mapped_status: targetStatus }), }); if (res.ok) { const created: StatusMappingDto = await res.json(); setMappings((prev) => [...prev.filter((m) => m.provider_status !== created.provider_status), created]); } } catch { // ignore } } async function handleUnmap(id: string) { try { const res = await fetch(`/api/settings/status-mappings/${id}`, { method: "DELETE" }); if (res.ok) { const updated: StatusMappingDto = await res.json(); setMappings((prev) => prev.map((m) => (m.id === id ? updated : m))); } } catch { // ignore } } function handleCreateTarget() { const name = newTargetName.trim().toLowerCase(); if (!name || allTargets.includes(name)) return; setCustomTargets((prev) => [...prev, name]); setNewTargetName(""); } function statusLabel(status: string) { const key = `seriesStatus.${status}` as Parameters[0]; const translated = t(key); return translated !== key ? translated : status; } if (loading) { return (

{t("common.loading")}

); } return ( {t("settings.statusMappings")} {t("settings.statusMappingsDesc")}
{/* Create new target status */}
setNewTargetName(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") handleCreateTarget(); }} className="max-w-[250px]" />
{/* Grouped by target status */} {allTargets.map((target) => { const items = grouped.get(target) || []; return (
{statusLabel(target)} ({target})
{items.map((m) => ( {m.provider_status} ))} {items.length === 0 && ( {t("settings.noMappings")} )}
); })} {/* Unmapped provider statuses (null mapped_status + brand new from providers) */} {(unmappedMappings.length > 0 || newProviderStatuses.length > 0) && (

{t("settings.unmappedSection")}

{unmappedMappings.map((m) => (
{m.provider_status} { if (e.target.value) handleAssign(m.provider_status, e.target.value); }} > {allTargets.map((s) => ( ))}
))} {newProviderStatuses.map((ps) => (
{ps} { if (e.target.value) handleAssign(ps, e.target.value); }} > {allTargets.map((s) => ( ))}
))}
)}
); }