import { IconArrowsUpDown as ArrowUpDown, IconBuilding as Building2, IconChevronLeft as ChevronLeft, IconChevronRight as ChevronRight, IconLoader2 as Loader2, IconSearch as Search, IconUsers as Users, } from '@tabler/icons-react'; import { useQuery } from '@tanstack/react-query'; import { useState } from 'react'; import { PageHeader } from '@/components/PageHeader'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { apiJson } from '@/lib/api'; import { ContentPanel } from '../../components/ContentPanel'; type Organization = { id: string; name: string; slug: string; plan: string; memberCount: number; createdAt: string; updatedAt: string; }; type SortField = 'name' | 'slug' | 'plan' | 'created_at'; type SortOrder = 'asc' | 'desc'; async function fetchOrganizations(params: { search: string; sortBy: SortField; sortOrder: SortOrder; page: number; limit: number; }): Promise<{ organizations: Organization[]; pagination: { total: number; totalPages: number } }> { const queryParams = new URLSearchParams({ search: params.search, sortBy: params.sortBy, sortOrder: params.sortOrder, page: params.page.toString(), limit: params.limit.toString(), }); return apiJson<{ organizations: Organization[]; pagination: { total: number; totalPages: number }; }>(`/api/v1/admin/organizations?${queryParams}`, {}, 'Failed to fetch organizations'); } function getPlanBadgeVariant(plan: string) { switch (plan) { case 'ENTERPRISE': return 'default'; case 'PRO': return 'secondary'; case 'STARTER': return 'outline'; default: return 'outline'; } } export default function AdminOrganizations() { const [search, setSearch] = useState(''); const [sortBy, setSortBy] = useState('created_at'); const [sortOrder, setSortOrder] = useState('desc'); const [page, setPage] = useState(1); const limit = 20; const { data, isLoading, error } = useQuery({ queryKey: ['admin-organizations', search, sortBy, sortOrder, page], queryFn: () => fetchOrganizations({ search, sortBy, sortOrder, page, limit }), }); const organizations = data?.organizations || []; const totalPages = data?.pagination.totalPages || 1; const total = data?.pagination.total || 0; const toggleSort = (field: SortField) => { if (sortBy === field) { setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc'); } else { setSortBy(field); setSortOrder('asc'); } setPage(1); }; const handleSearch = (value: string) => { setSearch(value); setPage(1); }; const sortOptions: Record = { 'created_at-desc': 'Newest first', 'created_at-asc': 'Oldest first', 'name-asc': 'Name A-Z', 'name-desc': 'Name Z-A', }; const sortValue = `${sortBy}-${sortOrder}`; return ( <>
Organizations ({total}) A list of all organizations registered in the system.
handleSearch(e.target.value)} className="pl-8 w-64" />
{isLoading ? (
) : error ? (
{error instanceof Error ? error.message : 'Failed to load organizations'}
) : organizations.length === 0 ? (
{search ? 'No organizations match your search.' : 'No organizations found.'}
) : ( <> Members {organizations.map((org) => (
{org.name}
{org.slug} {org.plan}
{org.memberCount}
{new Date(org.createdAt).toLocaleDateString()}
))}
{/* Pagination */} {totalPages > 1 && (

Page {page} of {totalPages}

)} )}
); }