feat: implement Entity and Nameserver cards with type safety improvements

- Add EntityCard component to display entity information with handle, roles, and public IDs
- Add NameserverCard component to display nameserver details
- Integrate new cards into Generic component for proper object rendering
- Remove unused dependencies (immutability-helper, type-fest)
- Enhance type safety in LookupInput with Zod validation
- Replace console.log statements with appropriate comments
- Initialize registryDataRef with proper typed default values
- Remove unused code and debug logging from rdap.ts and useLookup hook
- Update Object.entries type definition without external dependency
This commit is contained in:
2025-10-22 11:02:50 -05:00
parent 92fcef8fe2
commit 611074b546
10 changed files with 106 additions and 785 deletions

View File

@@ -47,7 +47,7 @@ const AbstractCard: FunctionComponent<AbstractCardProps> = ({
.writeText(JSON.stringify(data, null, 4))
.then(
() => {
console.log("Copied to clipboard.");
// Successfully copied to clipboard
},
(err) => {
if (err instanceof Error)

View File

@@ -3,6 +3,7 @@ import type { FunctionComponent } from "react";
import { Fragment, useState } from "react";
import { onPromise, preventDefault } from "@/helpers";
import type { SimplifiedTargetType, SubmitProps, TargetType } from "@/types";
import { TargetTypeEnum } from "@/schema";
import {
CheckIcon,
ChevronUpDownIcon,
@@ -109,7 +110,9 @@ const LookupInput: FunctionComponent<LookupInputProps> = ({
// 'auto' means 'do whatever' so we return null.
if (value == "auto") return null;
return value as TargetType;
// Validate the value is a valid TargetType
const result = TargetTypeEnum.safeParse(value);
return result.success ? result.data : null;
}
const searchIcon = (
@@ -250,7 +253,7 @@ const LookupInput: FunctionComponent<LookupInputProps> = ({
<button
onClick={(e) => {
e.preventDefault();
console.log("TODO: Show Help Explanation");
// TODO: Show Help Explanation
}}
className="absolute inset-y-0 left-0 flex items-center pl-4 text-lg font-bold opacity-20 hover:animate-pulse"
>

View File

@@ -0,0 +1,50 @@
import type { FunctionComponent } from "react";
import React from "react";
import type { Entity } from "@/types";
import Property from "@/components/common/Property";
import PropertyList from "@/components/common/PropertyList";
import AbstractCard from "@/components/common/AbstractCard";
export type EntityCardProps = {
data: Entity;
url?: string;
};
const EntityCard: FunctionComponent<EntityCardProps> = ({ data, url }: EntityCardProps) => {
return (
<AbstractCard
data={data}
url={url}
header={
<>
<span className="font-mono tracking-tighter">ENTITY</span>
<span className="font-mono tracking-wide">
{data.handle || data.roles.join(", ")}
</span>
</>
}
>
<dl>
{data.handle && <Property title="Handle">{data.handle}</Property>}
<PropertyList title="Roles">
{data.roles.map((role, index) => (
<PropertyList.Item key={index} title={role}>
{role}
</PropertyList.Item>
))}
</PropertyList>
{data.publicIds && data.publicIds.length > 0 && (
<PropertyList title="Public IDs">
{data.publicIds.map((publicId, index) => (
<PropertyList.Item key={index} title={publicId.type}>
{`${publicId.identifier} (${publicId.type})`}
</PropertyList.Item>
))}
</PropertyList>
)}
</dl>
</AbstractCard>
);
};
export default EntityCard;

View File

@@ -2,6 +2,8 @@ import type { FunctionComponent } from "react";
import DomainCard from "@/components/lookup/DomainCard";
import IPCard from "@/components/lookup/IPCard";
import AutnumCard from "@/components/lookup/AutnumCard";
import EntityCard from "@/components/lookup/EntityCard";
import NameserverCard from "@/components/lookup/NameserverCard";
import type { Domain, AutonomousNumber, Entity, Nameserver, IpNetwork } from "@/types";
import AbstractCard from "@/components/common/AbstractCard";
@@ -13,7 +15,9 @@ export type ObjectProps = {
};
const Generic: FunctionComponent<ObjectProps> = ({ data, url }: ObjectProps) => {
switch (data.objectClassName) {
const objectClassName = data.objectClassName;
switch (objectClassName) {
case "domain":
return <DomainCard url={url} data={data} />;
case "ip network":
@@ -21,11 +25,13 @@ const Generic: FunctionComponent<ObjectProps> = ({ data, url }: ObjectProps) =>
case "autnum":
return <AutnumCard url={url} data={data} />;
case "entity":
return <EntityCard url={url} data={data} />;
case "nameserver":
return <NameserverCard url={url} data={data} />;
default:
return (
<AbstractCard url={url}>
Not implemented. (<pre>{data.objectClassName ?? "null"}</pre>)
Not implemented. (<pre>{objectClassName ?? "null"}</pre>)
</AbstractCard>
);
}

View File

@@ -0,0 +1,34 @@
import type { FunctionComponent } from "react";
import React from "react";
import type { Nameserver } from "@/types";
import Property from "@/components/common/Property";
import AbstractCard from "@/components/common/AbstractCard";
export type NameserverCardProps = {
data: Nameserver;
url?: string;
};
const NameserverCard: FunctionComponent<NameserverCardProps> = ({
data,
url,
}: NameserverCardProps) => {
return (
<AbstractCard
data={data}
url={url}
header={
<>
<span className="font-mono tracking-tighter">NAMESERVER</span>
<span className="font-mono tracking-wide">{data.ldhName}</span>
</>
}
>
<dl>
<Property title="LDH Name">{data.ldhName}</Property>
</dl>
</AbstractCard>
);
};
export default NameserverCard;