'use client'; import { useEffect, useState } from 'react'; import { useParams, useRouter } from 'next/navigation'; import api from '@/lib/api'; interface TenantUser { id: string; email: string; firstName: string; lastName: string; isActive: boolean; roles: { role: string }[]; tenantRoles: { tenantRole: { name: string; slug: string } }[]; } interface Tenant { id: string; name: string; slug: string; isActive: boolean; settings: Record; createdAt: string; updatedAt: string; users: TenantUser[]; _count: { clients: number; subscriptions: number; invoices: number; payments: number; tickets: number; }; totalRevenue: number; } export default function TenantDetailPage() { const params = useParams(); const router = useRouter(); const tenantId = params.id as string; const [tenant, setTenant] = useState(null); const [loading, setLoading] = useState(true); const [impersonating, setImpersonating] = useState(false); useEffect(() => { loadTenant(); }, [tenantId]); async function loadTenant() { setLoading(true); try { const res = await api.get(`/tenants/${tenantId}`); setTenant(res.data.data); } catch { // tenant not found } finally { setLoading(false); } } async function handleToggleActive() { if (!tenant) return; const action = tenant.isActive ? 'deactivate' : 'activate'; try { await api.patch(`/tenants/${tenantId}/${action}`); loadTenant(); } catch (err) { console.error(`Failed to ${action} tenant:`, err); } } async function handleImpersonate() { setImpersonating(true); try { const adminId = (JSON.parse(localStorage.getItem('admin_user') || '{}')).id; const adminName = 'Super Admin'; const res = await api.post(`/impersonate/${tenantId}`, { adminId, adminName }); const { accessToken, impersonatedUser, tenant: t } = res.data.data; // Open tenant app with impersonation token const url = new URL('http://localhost:3000/impersonate'); url.searchParams.set('token', accessToken); url.searchParams.set('user', JSON.stringify(impersonatedUser)); url.searchParams.set('tenant', JSON.stringify(t)); window.open(url.toString(), '_blank'); } catch (err) { console.error('Failed to impersonate:', err); } finally { setImpersonating(false); } } if (loading) return
Loading...
; if (!tenant) return
Tenant not found
; const statCards = [ { label: 'Users', value: tenant.users.length }, { label: 'Clients', value: tenant._count.clients }, { label: 'Subscriptions', value: tenant._count.subscriptions }, { label: 'Invoices', value: tenant._count.invoices }, { label: 'Payments', value: tenant._count.payments }, { label: 'Tickets', value: tenant._count.tickets }, { label: 'Revenue', value: `₱${Number(tenant.totalRevenue).toLocaleString()}` }, ]; return (
{/* Header */}

{tenant.name}

{tenant.isActive ? 'Active' : 'Inactive'}

{tenant.slug}

Created {new Date(tenant.createdAt).toLocaleDateString()} · Updated {new Date(tenant.updatedAt).toLocaleDateString()}

{/* Stats */}
{statCards.map((card) => (

{card.label}

{card.value}

))}
{/* Users */}

Users ({tenant.users.length})

{tenant.users.map((u) => ( ))}
Name Email Roles Status
{u.firstName} {u.lastName} {u.email}
{u.roles.map((r, i) => ( {r.role} ))} {u.tenantRoles.map((tr, i) => ( {tr.tenantRole.name} ))}
{u.isActive ? 'Active' : 'Inactive'}
{/* Settings */}

Settings

{tenant.settings && Object.entries(tenant.settings).map(([key, value]) => (
{key.replace(/([A-Z])/g, ' $1')}: {String(value)}
))}
); }