import { useCallback, useEffect, useState } from "react";
import { Link } from "wouter";
import { ArrowLeft, Globe, Pause, Play, RefreshCw, Shield, Trash2 } from "lucide-react";
import { api } from "@/api";
import type { DNSRecord, DomainCheck, DomainView, Provider, Subdomain } from "@/types";
import { DomainDialog } from "@/components/DomainDialog";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { t } from "@/i18n";
function Row({ k, v, mono }: { k: string; v: React.ReactNode; mono?: boolean }) {
if (v === undefined || v === null || v === "") return null;
return (
{k}
{v}
);
}
function Section({ title, children }: { title: string; children: React.ReactNode }) {
return (
);
}
function fmtDate(iso: string | null | undefined) {
if (!iso) return "—";
return new Date(iso).toLocaleDateString(undefined, { year: "numeric", month: "short", day: "numeric" });
}
// Vendor chip shown next to records and inside the provider strip.
function ProviderBadge({ p }: { p?: Provider | null }) {
if (!p?.name) return null;
return (
{p.icon
?
: }
{p.name}
);
}
function ProvTile({ label, p }: { label: string; p?: Provider }) {
return (
{p?.icon
?

:
}
);
}
const recTypeColor = {
A: "text-[var(--chart-1)]",
AAAA: "text-[var(--chart-1)]",
CNAME: "text-[var(--chart-4)]",
NS: "text-[var(--chart-2)]",
MX: "text-[var(--chart-3)]",
TXT: "text-[var(--chart-5)]",
} satisfies Record, string>;
const recOrder = ["A", "AAAA", "CNAME", "NS", "MX", "TXT"];
function RecordRow({ r }: { r: DNSRecord }) {
return (
{r.type}
{r.value}
{r.type === "MX" && r.priority !== null && r.priority !== undefined
? (pri {r.priority})
: null}
);
}
export function DomainDetailPage({ id }: { id: string }) {
const [d, setD] = useState(null);
const [checks, setChecks] = useState([]);
const [subs, setSubs] = useState([]);
const [dlgOpen, setDlgOpen] = useState(false);
const [refreshing, setRefreshing] = useState(false);
const [subScanning, setSubScanning] = useState(false);
const load = useCallback(async () => {
const [{ data: dv }, { data: ck }, { data: sb }] = await Promise.all([
api.GET("/api/domains/{id}", { params: { path: { id } } }),
api.GET("/api/domains/{id}/checks", { params: { path: { id } } }),
api.GET("/api/domains/{id}/subdomains", { params: { path: { id } } }),
]);
if (dv) setD(dv);
if (ck) setChecks(ck);
if (sb) setSubs(sb);
}, [id]);
useEffect(() => { void load(); }, [load]);
if (!d) return {t("common.loading")};
const expiring = d.expiring || (d.daysUntilExpiry ?? Infinity) < 0;
return (
{t("nav.domains")}
{d.faviconUrl ?

: null}
{d.name}
{d.tld ? `.${d.tld}` : ""}
{d.dnssec === "signed" && dnssec}
{d.transferLock ? {t("domains.transferLock")} : null}
{d.privacyEnabled ? {t("domains.whoisPrivacy")} : null}
{d.autoRenew ? {t("domains.autoRenew")} : null}
{d.lookupError ? (
lookup: {d.lookupError}
) : null}
{t("domains.domainExpires")}
{d.daysUntilExpiry !== null && d.daysUntilExpiry !== undefined
? (d.daysUntilExpiry < 0 ? t("domains.expired") : `${d.daysUntilExpiry}d`)
: "—"}
{fmtDate(d.expiryDate)}
{t("domains.sslExpires")}
{d.sslDaysUntilExpiry !== null && d.sslDaysUntilExpiry !== undefined
? (d.sslDaysUntilExpiry < 0 ? t("domains.expired") : `${d.sslDaysUntilExpiry}d`)
: "—"}
{fmtDate(d.sslValidTo)}
{t("domains.registrar")}
{d.registrarName || "—"}
{d.caProvider || "—"}
{t("domains.checked")}
{d.lastChecked ? new Date(d.lastChecked).toLocaleDateString() : "—"}
every {d.intervalH}h
{/* Vendor strip — registrar, DNS, hosting, email, CA */}
{d.statuses && d.statuses.length > 0 ?
: null}
{[...(d.records ?? [])]
.sort((a, b) => recOrder.indexOf(a.type ?? "") - recOrder.indexOf(b.type ?? ""))
.map((r, i) => )}
{(d.records ?? []).length === 0 ? (
—
) : null}
: d.caProvider} />
{d.sslAltNames && d.sslAltNames.length > 0 ? (
5 ? ` +${d.sslAltNames.length - 5}` : "")} mono />
) : null}
{Object.keys(d.headers ?? {}).length > 0 ? (
{t("domains.responseHeaders", { n: Object.keys(d.headers ?? {}).length })}
{Object.entries(d.headers ?? {}).map(([k, v]) => (
{k}
{v}
))}
) : null}
{t("domains.subdomains")}{subs.length > 0 ? ` (${subs.length})` : ""}
{subs.map((s) => (
| {s.name} |
{(s.ips ?? []).join(", ") || "—"}
|
{fmtDate(s.lastSeen)}
|
))}
{subs.length === 0 && (
|
{t("domains.noSubsFound")}
|
)}
{t("domains.checkHistory")}
{checks.map((c) => (
| {new Date(c.checkedAt ?? "").toLocaleString()} |
{t("domains.expPrefix")} {fmtDate(c.expiryDate)} |
{t("domains.sslPrefix")} {fmtDate(c.sslValidTo)} |
{(c.ipv4 ?? []).join(", ")} |
))}
{checks.length === 0 && (
| {t("domains.noSnapshots")} |
)}
);
}