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 (

{title}

{children}
); } 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 | undefined }) { if (!p?.name) return null; return ( {p.icon ? : } {p.name} ); } function ProvTile({ label, p }: { label: string; p: Provider | undefined }) { return (
{p?.icon ? : }
{label}
{p?.name || "—"}
); } 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}
: d.hostingProvider} />
{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) => ( ))} {subs.length === 0 && ( )}
{s.name} {(s.ips ?? []).join(", ") || "—"} {fmtDate(s.lastSeen)}
{t("domains.noSubsFound")}

{t("domains.checkHistory")}

{checks.map((c) => ( ))} {checks.length === 0 && ( )}
{new Date(c.checkedAt ?? "").toLocaleString()} {t("domains.expPrefix")} {fmtDate(c.expiryDate)} {t("domains.sslPrefix")} {fmtDate(c.sslValidTo)} {(c.ipv4 ?? []).join(", ")}
{t("domains.noSnapshots")}
); }