mirror of
https://github.com/jakejarvis/hoot.git
synced 2025-10-18 20:14:25 -04:00
Refactor registration section to improve source display and add hostname extraction utility
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { BadgeCheck, ExternalLink, HatGlasses } from "lucide-react";
|
||||
import { BadgeCheck, HatGlasses, Info } from "lucide-react";
|
||||
import { ErrorWithRetry } from "@/components/domain/error-with-retry";
|
||||
import { Favicon } from "@/components/domain/favicon";
|
||||
import { KeyValue } from "@/components/domain/key-value";
|
||||
@@ -12,28 +12,16 @@ import {
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { formatDate, formatDateTimeUtc } from "@/lib/format";
|
||||
import {
|
||||
extractHostnameFromUrlish,
|
||||
formatDate,
|
||||
formatDateTimeUtc,
|
||||
} from "@/lib/format";
|
||||
import type { Registration } from "@/lib/schemas";
|
||||
import { SECTION_DEFS } from "@/lib/sections-meta";
|
||||
|
||||
type RegistrantView = { organization: string; country: string; state?: string };
|
||||
|
||||
export function formatRegistrant(reg: {
|
||||
organization: string;
|
||||
country: string;
|
||||
state?: string;
|
||||
}) {
|
||||
const org = (reg.organization || "").trim();
|
||||
const country = (reg.country || "").trim();
|
||||
const state = (reg.state || "").trim();
|
||||
const parts = [] as string[];
|
||||
if (org) parts.push(org);
|
||||
const loc = [state, country].filter(Boolean).join(", ");
|
||||
if (loc) parts.push(loc);
|
||||
if (parts.length === 0) return "Unavailable";
|
||||
return parts.join(" — ");
|
||||
}
|
||||
|
||||
export function RegistrationSection({
|
||||
data,
|
||||
isLoading,
|
||||
@@ -67,9 +55,9 @@ export function RegistrationSection({
|
||||
<>
|
||||
<KeyValue
|
||||
label="Registrar"
|
||||
value={data?.registrarProvider?.name || ""}
|
||||
value={data.registrarProvider?.name || ""}
|
||||
leading={
|
||||
data?.registrarProvider?.domain ? (
|
||||
data.registrarProvider?.domain ? (
|
||||
<Favicon
|
||||
domain={data.registrarProvider.domain}
|
||||
size={16}
|
||||
@@ -85,22 +73,27 @@ export function RegistrationSection({
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">
|
||||
<p>
|
||||
Source:{" "}
|
||||
<p className="inline-flex items-center gap-1">
|
||||
<span>
|
||||
Verified by{" "}
|
||||
<span className="font-medium">
|
||||
{formatRegistrationSourceHost(data) ??
|
||||
(data.source === "rdap" ? "RDAP" : "WHOIS")}
|
||||
</span>
|
||||
</span>
|
||||
<a
|
||||
href={
|
||||
data?.source === "rdap"
|
||||
data.source === "rdap"
|
||||
? "https://rdap.rcode3.com/"
|
||||
: "https://en.wikipedia.org/wiki/WHOIS"
|
||||
}
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
className="inline-flex items-center gap-1 font-mono underline underline-offset-2"
|
||||
title={`Learn about ${
|
||||
data.source === "rdap" ? "RDAP" : "WHOIS"
|
||||
}`}
|
||||
>
|
||||
<span>
|
||||
{data?.source === "rdap" ? "RDAP" : "WHOIS"}
|
||||
</span>
|
||||
<ExternalLink className="size-3" />
|
||||
<Info className="size-3" />
|
||||
</a>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
@@ -111,12 +104,12 @@ export function RegistrationSection({
|
||||
<KeyValue
|
||||
label="Registrant"
|
||||
value={
|
||||
data?.privacyEnabled || !registrant
|
||||
data.privacyEnabled || !registrant
|
||||
? "Hidden"
|
||||
: formatRegistrant(registrant)
|
||||
}
|
||||
leading={
|
||||
data?.privacyEnabled || !registrant ? (
|
||||
data.privacyEnabled || !registrant ? (
|
||||
<HatGlasses className="stroke-muted-foreground" />
|
||||
) : undefined
|
||||
}
|
||||
@@ -163,7 +156,25 @@ export function RegistrationSection({
|
||||
);
|
||||
}
|
||||
|
||||
function extractRegistrantView(record: Registration): RegistrantView | null {
|
||||
export function formatRegistrant(reg: {
|
||||
organization: string;
|
||||
country: string;
|
||||
state?: string;
|
||||
}) {
|
||||
const org = (reg.organization || "").trim();
|
||||
const country = (reg.country || "").trim();
|
||||
const state = (reg.state || "").trim();
|
||||
const parts = [] as string[];
|
||||
if (org) parts.push(org);
|
||||
const loc = [state, country].filter(Boolean).join(", ");
|
||||
if (loc) parts.push(loc);
|
||||
if (parts.length === 0) return "Unavailable";
|
||||
return parts.join(" — ");
|
||||
}
|
||||
|
||||
export function extractRegistrantView(
|
||||
record: Registration,
|
||||
): RegistrantView | null {
|
||||
const registrant = record.contacts?.find((c) => c.type === "registrant");
|
||||
if (!registrant) return null;
|
||||
const organization =
|
||||
@@ -177,3 +188,15 @@ function extractRegistrantView(record: Registration): RegistrantView | null {
|
||||
const state = (registrant.state || "").toString() || undefined;
|
||||
return { organization, country, state };
|
||||
}
|
||||
|
||||
export function formatRegistrationSourceHost(
|
||||
data: Registration,
|
||||
): string | undefined {
|
||||
if (data.source === "rdap") {
|
||||
const servers = data.rdapServers;
|
||||
const last =
|
||||
servers && servers.length > 0 ? servers[servers.length - 1] : undefined;
|
||||
return extractHostnameFromUrlish(last);
|
||||
}
|
||||
return extractHostnameFromUrlish(data.whoisServer) ?? data.whoisServer;
|
||||
}
|
||||
|
@@ -36,3 +36,17 @@ export function formatTtl(ttl: number): string {
|
||||
if (!hours && !minutes) parts.push(`${seconds}s`);
|
||||
return parts.join(" ");
|
||||
}
|
||||
|
||||
export function extractHostnameFromUrlish(
|
||||
input: string | undefined | null,
|
||||
): string | undefined {
|
||||
if (!input) return undefined;
|
||||
const value = String(input).trim();
|
||||
if (!value) return undefined;
|
||||
try {
|
||||
const url = new URL(value.includes("://") ? value : `https://${value}`);
|
||||
return url.hostname || undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user