import { useState } from "react"; import { AlertTriangle, ArrowRight, Check, ChevronDown, FileJson, ShieldCheck } from "lucide-react"; import Button from "./ui/Button"; import Badge from "./ui/Badge"; import { sampleJson } from "../lib/api"; import { parseJson } from "../lib/format"; function buildPayload(server, parsed) { const entries = Array.isArray(parsed) ? parsed : parsed.servers || []; const services = []; const errors = []; entries.forEach((entry, index) => { const domain = String(entry?.domain || "").trim(); const ports = Array.isArray(entry?.ports) ? entry.ports : []; if (!domain || ports.length === 0) { errors.push({ index, message: "Each entry needs a domain and at least one port." }); return; } ports.forEach((port, portIndex) => { const value = Number(port); if (!Number.isInteger(value) || value < 1 || value > 65535) { errors.push({ index, serviceIndex: portIndex, message: `Port "${port}" is not valid.` }); return; } services.push({ name: domain, port: value, endpoint: "/", method: "POST", notes: entry.is_backup ? "backup" : null, }); }); }); return { payload: { servers: [ { name: server.name, ipAddress: server.ipAddress, description: server.description, proxyPort: server.proxyPort ?? null, proxyPath: server.proxyPort ? server.proxyPath || "/api/nginx/app" : null, services, }, ], }, errors, }; } function ConflictSide({ title, data, highlight = false }) { return (

{title}

{data?.name &&

{data.name}

} {data?.description &&

{data.description}

} {data?.port !== undefined && data?.port !== null && (

port {data.port} {data.method ? ` · ${data.method}` : ""}

)}
); } export default function ImportPanel({ server, onPreview, onApply }) { const [expanded, setExpanded] = useState(false); const [jsonInput, setJsonInput] = useState(sampleJson); const [preview, setPreview] = useState(null); const [jsonError, setJsonError] = useState(""); const [shapeErrors, setShapeErrors] = useState([]); const [busy, setBusy] = useState(""); function prepare() { setJsonError(""); setShapeErrors([]); let parsed; try { parsed = parseJson(jsonInput); } catch { setJsonError("The JSON is not valid."); return null; } const result = buildPayload(server, parsed); setShapeErrors(result.errors); return result.errors.length === 0 ? result.payload : null; } async function previewImport() { const payload = prepare(); if (!payload) return; setBusy("preview"); try { setPreview(await onPreview(payload)); } catch (err) { setJsonError(err.message); } finally { setBusy(""); } } async function apply(mode) { const payload = prepare(); if (!payload) return; setBusy(mode); try { await onApply(payload, mode); setPreview(null); } catch (err) { setJsonError(err.message); if (err.data) setPreview(err.data); } finally { setBusy(""); } } const hasConflicts = preview?.conflicts?.length > 0; return (
{expanded && (
{!preview ? ( <>