"use client"; import { useState } from "react"; import type { ChangeEvent } from "react"; import type { FormEvent } from "react"; type Instance = { id: string; name: string; base_url: string; auth_type: "api_key" | "basic"; status: string; error_message: string | null; last_connected_at: string | null; last_sync_at: string | null; last_sync_status: string | null; last_sync_error: string | null; last_sync_subscriptions: number; last_sync_domains: number; }; type Subscription = { id: string; name: string | null; status: string | null; plesk_subscription_id: string; plesk_instance_id: string; }; type Domain = { id: string; plesk_instance_id: string; domain_name: string; status: string | null; hosting_type: string | null; source_created_at: string | null; aliases_count: number | null; updated_at: string; }; type Props = { instances: Instance[]; subscriptions: Subscription[]; domains: Domain[]; autoSyncByInstance: Record< string, { status: string; created_at: string; error_message: string | null } >; }; export function DashboardControls({ instances, subscriptions, domains, autoSyncByInstance, }: Props) { const [instanceName, setInstanceName] = useState(""); const [baseUrl, setBaseUrl] = useState(""); const [authType, setAuthType] = useState<"api_key" | "basic">("api_key"); const [apiKey, setApiKey] = useState(""); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [actionSubId, setActionSubId] = useState(subscriptions[0]?.id ?? ""); const [actionType, setActionType] = useState<"suspend" | "unsuspend">("suspend"); const [domainSearch, setDomainSearch] = useState(""); const [domainStatus, setDomainStatus] = useState("all"); const [message, setMessage] = useState(null); const [loading, setLoading] = useState(false); const healthCounts = instances.reduce( (acc, instance) => { if (instance.status === "connected") acc.connected += 1; else if (instance.status === "syncing") acc.syncing += 1; else acc.error += 1; return acc; }, { connected: 0, syncing: 0, error: 0 }, ); const domainStatusOptions = Array.from( new Set(domains.map((domain) => (domain.status ?? "unknown").toLowerCase())), ).sort(); const filteredDomains = domains.filter((domain) => { const normalizedStatus = (domain.status ?? "unknown").toLowerCase(); const statusMatches = domainStatus === "all" || normalizedStatus === domainStatus; const term = domainSearch.trim().toLowerCase(); const searchMatches = !term || domain.domain_name.toLowerCase().includes(term) || (domain.hosting_type ?? "").toLowerCase().includes(term); return statusMatches && searchMatches; }); function formatDate(value: string | null) { if (!value) return "—"; const date = new Date(value); return Number.isNaN(date.getTime()) ? "—" : date.toLocaleString(); } async function runRequest(url: string, body?: unknown) { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: body ? JSON.stringify(body) : undefined, }); const payload = await response.json().catch(() => ({})); if (!response.ok) { throw new Error(payload.error ?? "Request failed"); } return payload; } async function onCreateInstance(event: FormEvent) { event.preventDefault(); setLoading(true); setMessage(null); try { await runRequest("/api/plesk/instances", { name: instanceName, base_url: baseUrl, auth_type: authType, api_key: authType === "api_key" ? apiKey : undefined, username: authType === "basic" ? username : undefined, password: authType === "basic" ? password : undefined, }); setMessage("Plesk instance connected."); window.location.reload(); } catch (error) { setMessage(error instanceof Error ? error.message : "Could not connect instance"); } finally { setLoading(false); } } async function onSync(instanceId: string) { setLoading(true); setMessage(null); try { const payload = await runRequest(`/api/plesk/instances/${instanceId}/sync`); setMessage("Plesk sync completed."); if (payload?.skipped) { setMessage(`Sync skipped (${payload.reason ?? "no reason"}).`); } else if (payload?.domainsUpserted != null || payload?.subscriptionsUpserted != null) { setMessage( `Plesk sync completed. Subscriptions: ${payload.subscriptionsUpserted ?? 0}, Domains: ${payload.domainsUpserted ?? 0}`, ); } window.location.reload(); } catch (error) { setMessage(error instanceof Error ? error.message : "Sync failed"); } finally { setLoading(false); } } async function onTestConnection(instanceId: string) { setLoading(true); setMessage(null); try { await runRequest(`/api/plesk/instances/${instanceId}/test`); setMessage("Connection test completed."); window.location.reload(); } catch (error) { setMessage(error instanceof Error ? error.message : "Connection test failed"); } finally { setLoading(false); } } async function onSubscriptionAction() { if (!actionSubId) return; setLoading(true); setMessage(null); try { await runRequest(`/api/plesk/subscriptions/${actionSubId}/action`, { action: actionType }); setMessage(`Subscription ${actionType} completed.`); window.location.reload(); } catch (error) { setMessage(error instanceof Error ? error.message : "Action failed"); } finally { setLoading(false); } } async function onCheckout() { setLoading(true); try { const payload = await runRequest("/api/stripe/checkout"); if (payload.url) window.location.href = payload.url; } finally { setLoading(false); } } async function onPortal() { setLoading(true); try { const payload = await runRequest("/api/stripe/portal"); if (payload.url) window.location.href = payload.url; } finally { setLoading(false); } } return (

Connected

{healthCounts.connected}

Syncing

{healthCounts.syncing}

Error/Other

{healthCounts.error}

Connect Plesk Instance

) => setInstanceName(e.target.value)} className="w-full rounded border border-slate-300 px-3 py-2 text-sm" placeholder="Instance name" /> ) => setBaseUrl(e.target.value)} className="w-full rounded border border-slate-300 px-3 py-2 text-sm" placeholder="https://plesk.example.com" /> {authType === "api_key" ? ( ) => setApiKey(e.target.value)} className="w-full rounded border border-slate-300 px-3 py-2 text-sm" placeholder="Plesk API key" /> ) : (
) => setUsername(e.target.value)} className="w-full rounded border border-slate-300 px-3 py-2 text-sm" placeholder="Plesk username" /> ) => setPassword(e.target.value)} className="w-full rounded border border-slate-300 px-3 py-2 text-sm" placeholder="Plesk password" />
)}

Plesk Instances

{instances.length === 0 ? (

No Plesk instances connected yet.

) : ( instances.map((instance) => (
{autoSyncByInstance[instance.id] ? ( Auto-sync {autoSyncByInstance[instance.id].status} ) : null}

{instance.name}

{instance.base_url}

Status: {instance.status}

Last sync: {formatDate(instance.last_sync_at)} {instance.last_sync_status ? ` (${instance.last_sync_status})` : ""}

Last counts: {instance.last_sync_subscriptions ?? 0} subscriptions, {" "} {instance.last_sync_domains ?? 0} domains

Last connected: {instance.last_connected_at ?? "never"}

{autoSyncByInstance[instance.id] ? (

Last auto-sync: {autoSyncByInstance[instance.id].created_at}

) : null} {instance.error_message ? (

{instance.error_message}

) : null} {instance.last_sync_error ? (

Last sync error: {instance.last_sync_error}

) : null} {autoSyncByInstance[instance.id]?.error_message ? (

Auto-sync error: {autoSyncByInstance[instance.id].error_message}

) : null}
)) )}
{message ?

{message}

: null}
) => setDomainSearch(e.target.value)} className="mt-1 w-full rounded border border-slate-300 px-3 py-2 text-sm" placeholder="Search by domain or hosting type" />
{filteredDomains.length === 0 ? ( ) : ( filteredDomains.map((domain) => ( )) )}
Domain Status Hosting Created Aliases Last seen
No domains found.
{domain.domain_name} {domain.status ?? "unknown"} {domain.hosting_type ?? "unknown"} {formatDate(domain.source_created_at)} {domain.aliases_count ?? 0} {formatDate(domain.updated_at)}
); }