import { A, useLocation } from "@solidjs/router" import { createEffect, createMemo, createSignal, For, onCleanup, Show } from "solid-js" import Fuse from "fuse.js" import { primeProfiles, useProfilePicture, useTenant, useTenantRelays, type Relay } from "@/lib/hooks" import { listTenantInvoices, type Invoice } from "@/lib/api" import { account, eventStore, identity } from "@/lib/state" import serverIcon from "@/assets/server.svg" import Modal from "@/components/Modal" import PaymentDialog from "@/components/PaymentDialog" type Profile = { name?: string display_name?: string nip05?: string } function shortenPubkey(pubkey?: string) { if (!pubkey) return "" return `${pubkey.slice(0, 8)}…${pubkey.slice(-6)}` } function SearchIcon() { return ( ) } function RelayIcon() { return } export default function AppShell(props: { children?: any }) { const location = useLocation() const picture = useProfilePicture(() => account()?.pubkey) const [tenant] = useTenant() const [tenantRelays] = useTenantRelays() const [profile, setProfile] = createSignal({}) const [searchOpen, setSearchOpen] = createSignal(false) const [searchQuery, setSearchQuery] = createSignal("") const [pastDueInvoice, setPastDueInvoice] = createSignal() const [showPaymentDialog, setShowPaymentDialog] = createSignal(false) createEffect(async () => { const t = tenant() if (!t?.past_due_at) { setPastDueInvoice(undefined) return } try { const invoices = await listTenantInvoices(t.pubkey) const openInvoice = invoices.find(inv => inv.status === "open") setPastDueInvoice(openInvoice) } catch { // ignore } }) const username = createMemo(() => profile().name || profile().display_name || shortenPubkey(account()?.pubkey)) const nip05 = createMemo(() => profile().nip05 || "No NIP-05") const searchedRelays = createMemo(() => { const list = tenantRelays() ?? [] const query = searchQuery().trim() if (!query) return list const fuse = new Fuse(list, { keys: ["info_name", "subdomain"], threshold: 0.35, ignoreLocation: true, }) return fuse.search(query).map((result) => result.item) }) createEffect(() => { const pubkey = account()?.pubkey if (!pubkey) { setProfile({}) return } const profileSub = eventStore.profile(pubkey).subscribe((metadata) => { setProfile({ name: metadata?.name, display_name: metadata?.display_name, nip05: metadata?.nip05, }) }) const primeSub = primeProfiles([pubkey]) onCleanup(() => { profileSub.unsubscribe() primeSub.unsubscribe() }) }) const myResources = [{ href: "/relays", label: "My Relays" }] const adminResources = [ { href: "/admin/tenants", label: "Tenants" }, { href: "/admin/relays", label: "Relays" }, ] const navItemClass = (href: string) => { const active = location.pathname === href || location.pathname.startsWith(`${href}/`) return active ? "block rounded-lg bg-white/15 px-3 py-2 text-sm font-medium text-white" : "block rounded-lg px-3 py-2 text-sm text-white/80 hover:bg-white/10 hover:text-white" } const openSearchModal = () => setSearchOpen(true) const closeSearchModal = () => { setSearchOpen(false) setSearchQuery("") } return (
Your account has an overdue balance.
{props.children}
{(_) => { const invoice = pastDueInvoice()! return ( setShowPaymentDialog(false)} /> ) }}
setSearchQuery(e.currentTarget.value)} placeholder="Search your relays" class="w-full rounded-lg border border-gray-300 py-2 pl-10 pr-3" autofocus />
Loading relays...

}> 0} fallback={

No relays found.

}>
) }