import { useCallback, useEffect, useState } from "react"; import { Link } from "wouter"; import { ArrowLeft, Pause, Play, RefreshCw, Shield, Trash2 } from "lucide-react"; import { api } from "@/api"; import type { DomainCheck, DomainView, 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" }); } 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.providers")}
{d.dnsProvider || "—"}
{d.hostingProvider || d.emailProvider || "—"}
{d.statuses && d.statuses.length > 0 ? : null}
{d.nameServers?.map((n) => )} {d.mxRecords?.map((m) => )} {d.ipv4?.map((a) => )} {d.ipv6?.map((a) => )} {d.cname ? : null} {d.txtRecords?.slice(0, 4).map((t, i) => 60 ? t.slice(0, 60) + "…" : t} mono />)} {d.dnsProvider ? : null} {d.emailProvider ? : null}
{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) => ( ))} {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")}
); }