import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Check, Plus, Settings, Users } from 'lucide-react'; import { toast } from 'sonner'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Small } from '@/components/ui/typography'; import { Avatar, AvatarFallback } from '@/components/ui/avatar'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Separator } from '@/components/ui/separator'; import { useNetworks } from '@/hooks/use-networks'; import { useMyInvitations, useAcceptInvitation, } from '@/hooks/use-member-management'; import { apiClient } from '@/api/client'; import { Progress } from '@/components/ui/progress'; import { toUserMessage } from '@/lib/errors'; import type { Network, Invitation } from '@/api/types'; function NetworkRow({ network, onClick, onSettingsClick, }: { network: Network; onClick: () => void; onSettingsClick: () => void; }) { const initials = network.name.slice(0, 2).toUpperCase(); const memberCount = network.humans.length; return ( ); } function InvitationRow({ invitation }: { invitation: Invitation }) { const acceptInvitation = useAcceptInvitation(); const initials = invitation.network_name.slice(0, 2).toUpperCase(); const handleAccept = () => { acceptInvitation.mutate(invitation.network_id, { onSuccess: () => { toast.success(`Joined ${invitation.network_name}`); }, }); }; return (
{initials}

{invitation.network_name}

You've been invited
); } function CreateNetworkDialog({ open, onOpenChange, }: { open: boolean; onOpenChange: (open: boolean) => void; }) { const [name, setName] = useState(''); const navigate = useNavigate(); const queryClient = useQueryClient(); const createNetwork = useMutation({ mutationFn: (networkName: string) => apiClient.createNetwork({ name: networkName }), onSuccess: (network) => { queryClient.invalidateQueries({ queryKey: ['networks'] }); toast.success(`Created ${network.name}`); onOpenChange(false); setName(''); navigate(`/${network.id}/settings?section=members&add=1`); }, }); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); const trimmed = name.trim(); if (!trimmed) return; createNetwork.mutate(trimmed); }; return ( Create a Network Caution: creating a network will create a new billing account. If your team already has a network, ask them for an invite.
setName(e.target.value)} autoFocus />
); } export default function NetworkSelector() { const navigate = useNavigate(); const [createDialogOpen, setCreateDialogOpen] = useState(false); const { data: networks, isPending, error, refetch } = useNetworks(); const { data: invitations } = useMyInvitations(); if (isPending) { return ; } if (error) { return (

Couldn't load your networks

{toUserMessage(error)}

); } const hasInvitations = invitations && invitations.length > 0; const hasNetworks = networks && networks.length > 0; if (!hasNetworks && !hasInvitations) { return (

You don't have access to any networks yet. Create one or ask your admin for an invite.

); } return ( <>
{hasInvitations && ( <>

Pending Invitations

{invitations.length}
{invitations.map((inv, index) => (
{index < invitations.length - 1 && ( )}
))} )} {hasNetworks && ( <> {hasInvitations && (

Your Networks

)} {networks.map((network, index) => (
navigate(`/${network.id}`)} onSettingsClick={() => navigate(`/${network.id}/settings`)} /> {index < networks.length - 1 && ( )}
))} )}
); }