import { Show, createSignal } from "solid-js" import type { Relay, PlanId } from "@/lib/api" import ConfirmDialog from "@/components/ConfirmDialog" import Field from "@/components/Field" import PricingTable from "@/components/PricingTable" import ToggleButton from "@/components/ToggleButton" import ToggleField from "@/components/ToggleField" import RelayCardHeader from "@/components/relay/RelayCardHeader" import PlanGatedToggle from "@/components/relay/PlanGatedToggle" import { setToastMessage } from "@/lib/state" import { useProfileMetadata } from "@/lib/hooks" import { flagToBool } from "@/lib/relayFlags" import { plans } from "@/lib/state" function DetailSection(props: { title: string; children: any }) { return (

{props.title}

{props.children}
) } function MembershipSection(props: { title: string; children: any }) { return (

{props.title}

{props.children}
) } type RelayDetailCardProps = { relay: Relay currentMembers?: number showTenant?: boolean editHref?: string onDeactivate?: () => void | Promise onReactivate?: () => void | Promise deactivating?: boolean reactivating?: boolean onTogglePublicJoin?: () => void onToggleStripSignatures?: () => void onToggleGroups?: () => void onToggleManagement?: () => void onToggleMediaStorage?: () => void onToggleLivekitSupport?: () => void onTogglePushNotifications?: () => void onUpdatePlan?: (planId: PlanId) => Promise enforcePlanLimits?: boolean showPlanActions?: boolean } export default function RelayDetailCard(props: RelayDetailCardProps) { const r = () => props.relay const [planId, setPlanId] = createSignal(props.relay.plan_id) const [pendingAction, setPendingAction] = createSignal<"deactivate" | "reactivate" | null>(null) // Resolve the owning tenant's profile so the Tenant field can show a name and // avatar instead of a raw pubkey. Only relevant in admin (showTenant) views. // This subscription stays in the parent so the header doesn't double-subscribe. const tenantProfile = useProfileMetadata(() => (props.showTenant ? props.relay.tenant_pubkey : undefined)) const memberLimitLabel = () => { const p = plans().find(p => p.id === r().plan_id) if (!p) return "?" return p.members === null ? "∞" : String(p.members) } const planLimited = () => (props.enforcePlanLimits ?? true) && r().plan_id === "free" const showPlanActions = () => props.showPlanActions ?? true const actionBusy = () => pendingAction() === "deactivate" ? !!props.deactivating : pendingAction() === "reactivate" ? !!props.reactivating : false const relayLabel = () => r().info_name || r().subdomain const confirmTitle = () => pendingAction() === "deactivate" ? "Deactivate relay?" : "Reactivate relay?" const confirmDescription = () => pendingAction() === "deactivate" ? `${relayLabel()} will be taken offline immediately.` : `${relayLabel()} will come back online and start accepting connections.` const confirmDetails = () => pendingAction() === "deactivate" ? [ "All client connections will be dropped immediately.", "Members will be unable to read from or publish to the relay.", "Scheduled and automated tasks (billing, syncing) will be paused.", "All relay data, settings, and members are preserved, nothing is deleted.", "You can reactivate at any time from this page.", ] : undefined const confirmLabel = () => pendingAction() === "deactivate" ? "Yes, deactivate" : "Yes, reactivate" const confirmBusyLabel = () => pendingAction() === "deactivate" ? "Deactivating..." : "Reactivating..." const confirmTone = () => pendingAction() === "deactivate" ? "danger" : "primary" async function changePlanId(planId: PlanId) { setPlanId(planId) try { await props.onUpdatePlan?.(planId) setToastMessage(`Plan updated to ${planId}`, "success") } catch { // error is handled by the caller } } function openActionDialog(action: "deactivate" | "reactivate") { setPendingAction(action) } function closeActionDialog() { if (actionBusy()) return setPendingAction(null) } async function confirmAction() { const action = pendingAction() if (!action) return if (action === "deactivate") { await props.onDeactivate?.() } else { await props.onReactivate?.() } setPendingAction(null) } return (
openActionDialog("deactivate") : undefined} onRequestReactivate={props.onReactivate ? () => openActionDialog("reactivate") : undefined} />


{props.currentMembers ?? "—"} {memberLimitLabel()}
{r().plan_id} } >
) }