"use client"; import * as React from "react"; import { useRouter } from "next/navigation"; import { RefreshCw, RotateCcw, Save } from "lucide-react"; import { resetCircuit, runProviderProbe, updateProviderConfig, type AdminActionResult, type ProviderConfigInput } from "@/actions/admin"; import { Button } from "@/components/ui/button"; import { Input, Textarea } from "@/components/ui/input"; import { Field, Hint, Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { Badge, StatusBadge } from "@/components/ui/badge"; import { ActionButton, ResultMessage } from "./action-button"; const ALL_NETWORKS = ["datacenter", "residential", "isp", "mobile"] as const; export interface ProviderConfigFormProps { id: string; label: string; enabled: boolean; networks: string[]; pricePerGbUsd: Record; weight: number; maxConcurrency: number; notes: string | null; /** Prices reported live by the API (fallback when no config row exists). */ livePrices: Record; liveNetworks: string[]; hasConfigRow: boolean; } export function ProviderConfigForm(p: ProviderConfigFormProps) { const router = useRouter(); const [pending, start] = React.useTransition(); const [result, setResult] = React.useState(null); const [enabled, setEnabled] = React.useState(p.enabled); const [networks, setNetworks] = React.useState(p.networks.length ? p.networks : p.liveNetworks); const [prices, setPrices] = React.useState>(() => { const out: Record = {}; for (const n of ALL_NETWORKS) { const v = p.pricePerGbUsd[n] ?? p.livePrices[n]; if (v !== undefined) out[n] = String(v); } return out; }); const [weight, setWeight] = React.useState(String(p.weight)); const [maxConcurrency, setMaxConcurrency] = React.useState(String(p.maxConcurrency)); const [notes, setNotes] = React.useState(p.notes ?? ""); const submit = (e: React.FormEvent) => { e.preventDefault(); start(async () => { const pricePerGbUsd: Record = {}; for (const [k, v] of Object.entries(prices)) if (v.trim() !== "" && networks.includes(k)) pricePerGbUsd[k] = Number(v); const input: ProviderConfigInput = { label: p.label, enabled, networks: networks as ProviderConfigInput["networks"], pricePerGbUsd, weight: Number(weight), maxConcurrency: Number(maxConcurrency), notes: notes.trim() || null, }; const r = await updateProviderConfig(p.id, input); setResult(r); if (r.ok) router.refresh(); }); }; return (
{!p.hasConfigRow ? no config row yet — defaults shown : null}
Networks and price per GB (USD)
{ALL_NETWORKS.map((n) => { const on = networks.includes(n); return (
setNetworks((cur) => (e.target.checked ? [...cur, n] : cur.filter((x) => x !== n)))} /> $ setPrices((cur) => ({ ...cur, [n]: e.target.value }))} className="h-7 w-24 font-mono text-[12.5px]" placeholder="—" /> /GB
); })}
setWeight(e.target.value)} className="font-mono" /> Relative preference multiplier (1 = neutral). setMaxConcurrency(e.target.value)} className="font-mono" /> Upstream connection ceiling for this provider.