refactor(nip-66): extract relay kinds display into reusable component

Create RelayKindsDisplay component to show accepted/rejected kinds in a
consistent format across detail views. Used in RelayDiscoveryDetailRenderer
to reduce code duplication and improve maintainability.
This commit is contained in:
Claude
2026-01-22 12:07:35 +00:00
parent d5e9748e17
commit 195ef3f62b
2 changed files with 63 additions and 38 deletions

View File

@@ -0,0 +1,60 @@
import { Badge } from "@/components/ui/badge";
import { Label } from "@/components/ui/label";
import { Filter, XCircle } from "lucide-react";
interface RelayKindsDisplayProps {
accepted: number[];
rejected: number[];
}
/**
* Relay Kinds Display Component
* Shows accepted and rejected event kinds for a relay in a consistent format
* Used in both Relay Discovery and Monitor Announcement detail views
*/
export function RelayKindsDisplay({
accepted,
rejected,
}: RelayKindsDisplayProps) {
return (
<>
{/* Accepted Kinds */}
{accepted.length > 0 && (
<div className="space-y-2">
<Label className="flex items-center gap-2 text-muted-foreground">
<Filter className="size-4" />
Accepted Kinds ({accepted.length})
</Label>
<div className="flex flex-wrap gap-1.5">
{accepted.map((kind) => (
<Badge key={kind} variant="outline" className="font-mono text-xs">
{kind}
</Badge>
))}
</div>
</div>
)}
{/* Rejected Kinds */}
{rejected.length > 0 && (
<div className="space-y-2">
<Label className="flex items-center gap-2 text-muted-foreground">
<XCircle className="size-4" />
Rejected Kinds ({rejected.length})
</Label>
<div className="flex flex-wrap gap-1.5">
{rejected.map((kind) => (
<Badge
key={kind}
variant="outline"
className="font-mono text-xs text-red-600 border-red-600/30"
>
!{kind}
</Badge>
))}
</div>
</div>
)}
</>
);
}

View File

@@ -5,6 +5,7 @@ import { Label } from "@/components/ui/label";
import { JsonViewer } from "@/components/JsonViewer";
import { UserName } from "../UserName";
import { NIPBadge } from "@/components/NIPBadge";
import { RelayKindsDisplay } from "../RelayKindsDisplay";
import {
getRelayUrl,
getRttMetrics,
@@ -28,7 +29,6 @@ import {
MapPin,
Shield,
Tag,
Filter,
Clock,
CheckCircle,
XCircle,
@@ -240,43 +240,8 @@ export function RelayDiscoveryDetailRenderer({ event }: { event: NostrEvent }) {
</div>
)}
{/* Accepted Kinds */}
{kinds.accepted.length > 0 && (
<div className="space-y-2">
<Label className="flex items-center gap-2 text-muted-foreground">
<Filter className="size-4" />
Accepted Kinds ({kinds.accepted.length})
</Label>
<div className="flex flex-wrap gap-1.5">
{kinds.accepted.map((kind) => (
<Badge key={kind} variant="outline" className="font-mono text-xs">
{kind}
</Badge>
))}
</div>
</div>
)}
{/* Rejected Kinds */}
{kinds.rejected.length > 0 && (
<div className="space-y-2">
<Label className="flex items-center gap-2 text-muted-foreground">
<XCircle className="size-4" />
Rejected Kinds ({kinds.rejected.length})
</Label>
<div className="flex flex-wrap gap-1.5">
{kinds.rejected.map((kind) => (
<Badge
key={kind}
variant="outline"
className="font-mono text-xs text-red-600 border-red-600/30"
>
!{kind}
</Badge>
))}
</div>
</div>
)}
{/* Relay Kinds */}
<RelayKindsDisplay accepted={kinds.accepted} rejected={kinds.rejected} />
{/* Topics */}
{topics.length > 0 && (