import { For, Show, createMemo, createSignal, onMount } from 'solid-js'; import AdminShell from '~/components/AdminShell'; import type { CrudRecord } from '~/lib/admin/types'; const API = '/api/gateway'; type CompanyRecord = CrudRecord & { industry?: string; city?: string; email?: string; status: 'ACTIVE' | 'INACTIVE' | 'PENDING' | 'SUSPENDED'; }; const FALLBACK_COMPANIES: CompanyRecord[] = [ { id: 'cp1', name: 'Tech Solutions Inc', industry: 'Software', city: 'Mumbai', email: 'contact@techsolutions.com', status: 'ACTIVE', updatedAt: '2026-03-27' }, { id: 'cp2', name: 'Creative Designs', industry: 'Design', city: 'Bangalore', email: 'hello@creativedesigns.in', status: 'ACTIVE', updatedAt: '2026-03-27' }, { id: 'cp3', name: 'Global Logistics', industry: 'Logistics', city: 'Chennai', email: 'info@globallogistics.com', status: 'PENDING', updatedAt: '2026-03-27' }, ]; function StatusBadge(props: { status: string }) { const active = () => props.status === 'ACTIVE'; const pending = () => props.status === 'PENDING'; return ( {props.status.charAt(0) + props.status.slice(1).toLowerCase()} ); } export default function CompanyManagementPage() { const [view, setView] = createSignal<'list' | 'detail' | 'form'>('list'); const [listTab, setListTab] = createSignal<'all' | 'create' | 'view'>('all'); const [detailTab, setDetailTab] = createSignal<'overview' | 'employees' | 'verification'>('overview'); const [search, setSearch] = createSignal(''); const [statusFilter, setStatusFilter] = createSignal('all'); const [sortBy, setSortBy] = createSignal<'name_asc' | 'name_desc' | 'industry_asc' | 'industry_desc'>('name_asc'); const [sortMenuOpen, setSortMenuOpen] = createSignal(false); const [filterMenuOpen, setFilterMenuOpen] = createSignal(false); const [rows, setRows] = createSignal([]); const [selectedCompany, setSelectedCompany] = createSignal(null); const [openMenuId, setOpenMenuId] = createSignal(null); const load = async () => { try { const res = await fetch(`${API}/api/admin/companies`); if (!res.ok) throw new Error(); const data = await res.json(); const list = Array.isArray(data) ? data : (data.companies || []); if (list.length === 0) setRows(FALLBACK_COMPANIES); else setRows(list.map((c: any) => ({ id: c.id, name: c.company_name || c.companyName || c.name || '—', industry: c.industry, city: c.city, email: c.email, status: (c.status || 'ACTIVE').toUpperCase(), updatedAt: c.updated_at || c.createdAt || '' } as CompanyRecord))); } catch { setRows(FALLBACK_COMPANIES); } }; onMount(() => void load()); const filteredRows = createMemo(() => { let r = rows(); if (statusFilter() !== 'all') r = r.filter((d) => d.status === statusFilter().toUpperCase()); const q = search().toLowerCase(); if (q) { r = r.filter(r => r.name.toLowerCase().includes(q) || (r.email || '').toLowerCase().includes(q)); } const sorted = [...r]; const mode = sortBy(); sorted.sort((a, b) => { if (mode === 'name_desc') return b.name.localeCompare(a.name); if (mode === 'industry_desc') return (b.industry || '').localeCompare(a.industry || ''); if (mode === 'industry_asc') return (a.industry || '').localeCompare(b.industry || ''); return a.name.localeCompare(b.name); }); return sorted; }); const exportCsv = () => { const headers = ['Company Name', 'Industry', 'City', 'Email', 'Status']; const body = filteredRows().map((row) => [ row.name || '', row.industry || '', row.city || '', row.email || '', row.status || '', ]); const csv = [headers, ...body] .map((line) => line.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(',')) .join('\n'); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = 'companies.csv'; link.click(); URL.revokeObjectURL(url); }; const openDetail = (row: CompanyRecord) => { setSelectedCompany(row); setListTab('view'); setOpenMenuId(null); }; return ( Company Management Manage and monitor all corporate accounts and business entities {/* ── LIST VIEW ── */} {/* Tabs */} {([ { key: 'all', label: 'All Companies', action: () => { setListTab('all'); setStatusFilter('all'); } }, { key: 'create', label: 'Create Company', action: () => { setListTab('create'); setView('form'); } }, { key: 'view', label: 'View Profile', action: () => setListTab('view') }, ] as const).map((tab) => ( {tab.label} ))} {/* View Profile panel */} No company selected Click the ⋮ menu on any company row and choose View Profile. {selectedCompany()!.name} {selectedCompany()!.industry} • {selectedCompany()!.city} {(['overview', 'employees', 'verification'] as const).map((tab, i) => { const labels = ['Overview', 'Employee List', 'Verification']; const active = () => detailTab() === tab; return ( setDetailTab(tab)} style={`position:relative;padding:14px 12px;font-size:13px;font-weight:600;background:none;border:none;cursor:pointer;color:${active() ? '#FF5E13' : '#6B7280'}`}> {labels[i]} ); })} Company Profile {[ { l: 'Industry', v: selectedCompany()!.industry || '—' }, { l: 'City', v: selectedCompany()!.city || '—' }, { l: 'Email', v: selectedCompany()!.email || '—' }, { l: 'Last Updated', v: selectedCompany()!.updatedAt || '—' }, ].map(item => ( {item.l} {item.v} ))} Edit Company { setSelectedCompany(null); setListTab('all'); }} style="height:36px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 16px;font-size:13px;font-weight:600;color:#374151;cursor:pointer">Back to List setSearch(e.currentTarget.value)} placeholder="Search companies..." style="height:34px;flex:1;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:13px;color:#111827;outline:none" /> { setSortMenuOpen((v) => !v); setFilterMenuOpen(false); }} style="display:inline-flex;height:34px;align-items:center;gap:6px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:500;color:#374151;cursor:pointer" > Sort {(['name_asc', 'name_desc', 'industry_asc', 'industry_desc'] as const).map((s, i) => ( { setSortBy(s); setSortMenuOpen(false); }} style={`display:block;width:100%;border-radius:8px;padding:8px 12px;text-align:left;font-size:13px;background:none;border:none;cursor:pointer;color:${sortBy() === s ? '#FF5E13' : '#374151'};background:${sortBy() === s ? '#FFF1EB' : 'transparent'}`}> {['Name (A-Z)', 'Name (Z-A)', 'Industry (A-Z)', 'Industry (Z-A)'][i]} ))} { setFilterMenuOpen((v) => !v); setSortMenuOpen(false); }} style="display:inline-flex;height:34px;align-items:center;gap:6px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:500;color:#374151;cursor:pointer" > Filters {(['all', 'active', 'pending', 'inactive'] as const).map((s) => ( { setStatusFilter(s); setFilterMenuOpen(false); }} style={`display:block;width:100%;border-radius:8px;padding:8px 12px;text-align:left;font-size:13px;background:none;border:none;cursor:pointer;color:${statusFilter() === s ? '#FF5E13' : '#374151'};background:${statusFilter() === s ? '#FFF1EB' : 'transparent'}`}> {s === 'all' ? 'All Status' : s === 'active' ? 'Active' : s === 'pending' ? 'Pending' : 'Inactive'} ))} Export {['Company Name', 'Industry', 'City', 'Email', 'Status', 'Actions'].map(h => ( {h} ))} {(row) => ( {row.name} {row.industry || '—'} {row.city || '—'} {row.email || '—'} setOpenMenuId(openMenuId() === row.id ? null : row.id)} style="display:inline-flex;height:32px;width:32px;align-items:center;justify-content:center;border-radius:8px;color:#9CA3AF;background:none;border:none;cursor:pointer"> openDetail(row)} style="display:flex;width:100%;align-items:center;gap:10px;border-radius:8px;padding:8px 12px;font-size:13px;color:#374151;background:none;border:none;cursor:pointer;text-align:left">View Profile Edit Company Deactivate )} ); }
Manage and monitor all corporate accounts and business entities
No company selected
Click the ⋮ menu on any company row and choose View Profile.
{selectedCompany()!.industry} • {selectedCompany()!.city}