'use client'; import { useState, useEffect } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Plus, Search, Building2, Users, Cpu, Activity, CheckCircle, Clock, XCircle, AlertTriangle, Play, Pause, Archive, Settings, Eye, Rocket, Timer, Shield, Database, Cloud, MoreVertical, } from 'lucide-react'; interface Tenant { id: number; name: string; domain: string; template: string; status: 'active' | 'pending' | 'suspended' | 'archived'; max_users: number; current_users: number; namespace: string; resource_count: number; created_at: string; last_activity?: string; deployment_status?: 'deployed' | 'deploying' | 'failed' | 'not_deployed'; storage_used_gb?: number; api_calls_today?: number; } export default function TenantsPage() { const [tenants, setTenants] = useState([]); const [filteredTenants, setFilteredTenants] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [statusFilter, setStatusFilter] = useState('all'); const [selectedTenants, setSelectedTenants] = useState>(new Set()); // Mock data for development useEffect(() => { const mockTenants: Tenant[] = [ { id: 1, name: 'Acme Corporation', domain: 'acme', template: 'enterprise', status: 'active', max_users: 500, current_users: 247, namespace: 'gt-tenant-acme', resource_count: 12, created_at: '2024-01-15T10:00:00Z', last_activity: new Date().toISOString(), deployment_status: 'deployed', storage_used_gb: 45.2, api_calls_today: 15234, }, { id: 2, name: 'TechStart Inc', domain: 'techstart', template: 'startup', status: 'pending', max_users: 100, current_users: 0, namespace: 'gt-tenant-techstart', resource_count: 8, created_at: '2024-01-14T14:30:00Z', deployment_status: 'deploying', storage_used_gb: 0, api_calls_today: 0, }, { id: 3, name: 'Global Solutions', domain: 'global', template: 'enterprise', status: 'active', max_users: 1000, current_users: 623, namespace: 'gt-tenant-global', resource_count: 24, created_at: '2024-01-13T09:15:00Z', last_activity: new Date(Date.now() - 3600000).toISOString(), deployment_status: 'deployed', storage_used_gb: 128.7, api_calls_today: 42156, }, { id: 4, name: 'Education First', domain: 'edufirst', template: 'education', status: 'active', max_users: 2000, current_users: 1456, namespace: 'gt-tenant-edufirst', resource_count: 18, created_at: '2024-01-10T11:00:00Z', last_activity: new Date(Date.now() - 600000).toISOString(), deployment_status: 'deployed', storage_used_gb: 89.3, api_calls_today: 28934, }, { id: 5, name: 'CyberDefense Corp', domain: 'cyberdef', template: 'cybersecurity', status: 'active', max_users: 300, current_users: 189, namespace: 'gt-tenant-cyberdef', resource_count: 21, created_at: '2024-01-08T08:45:00Z', last_activity: new Date(Date.now() - 1800000).toISOString(), deployment_status: 'deployed', storage_used_gb: 67.4, api_calls_today: 19876, }, { id: 6, name: 'Beta Testers LLC', domain: 'betatest', template: 'development', status: 'suspended', max_users: 10, current_users: 12, namespace: 'gt-tenant-betatest', resource_count: 5, created_at: '2024-01-05T15:20:00Z', last_activity: new Date(Date.now() - 86400000).toISOString(), deployment_status: 'deployed', storage_used_gb: 12.1, api_calls_today: 0, }, ]; setTenants(mockTenants); setFilteredTenants(mockTenants); setLoading(false); }, []); // Filter tenants based on search and status useEffect(() => { let filtered = tenants; // Filter by status if (statusFilter !== 'all') { filtered = filtered.filter(t => t.status === statusFilter); } // Filter by search query if (searchQuery) { filtered = filtered.filter(t => t.name.toLowerCase().includes(searchQuery.toLowerCase()) || t.domain.toLowerCase().includes(searchQuery.toLowerCase()) || t.template.toLowerCase().includes(searchQuery.toLowerCase()) ); } setFilteredTenants(filtered); }, [statusFilter, searchQuery, tenants]); const getStatusBadge = (status: string) => { switch (status) { case 'active': return Active; case 'pending': return Pending; case 'suspended': return Suspended; case 'archived': return Archived; default: return {status}; } }; const getDeploymentBadge = (status?: string) => { switch (status) { case 'deployed': return Deployed; case 'deploying': return Deploying; case 'failed': return Failed; default: return Not Deployed; } }; const getTemplateBadge = (template: string) => { const colors: Record = { enterprise: 'bg-purple-600', startup: 'bg-blue-600', education: 'bg-green-600', cybersecurity: 'bg-red-600', development: 'bg-yellow-600', }; return ( {template.charAt(0).toUpperCase() + template.slice(1)} ); }; const statusTabs = [ { id: 'all', label: 'All Tenants', count: tenants.length }, { id: 'active', label: 'Active', count: tenants.filter(t => t.status === 'active').length }, { id: 'pending', label: 'Pending', count: tenants.filter(t => t.status === 'pending').length }, { id: 'suspended', label: 'Suspended', count: tenants.filter(t => t.status === 'suspended').length }, ]; return (

Tenant Management

Manage tenant deployments with 5-minute onboarding

{/* Quick Stats */}
Total Tenants
{tenants.length}

{tenants.filter(t => t.status === 'active').length} active

Total Users
{tenants.reduce((sum, t) => sum + t.current_users, 0).toLocaleString()}

Across all tenants

Storage Used
{(tenants.reduce((sum, t) => sum + (t.storage_used_gb || 0), 0) / 1024).toFixed(1)} TB

Total consumption

API Calls Today
{tenants.reduce((sum, t) => sum + (t.api_calls_today || 0), 0).toLocaleString()}

All tenants combined

{/* Status Tabs */}
{statusTabs.map(tab => ( ))}
{/* Search */}
setSearchQuery((e as React.ChangeEvent).target.value)} className="pl-10" />
{/* Bulk Actions */} {selectedTenants.size > 0 && ( {selectedTenants.size} tenant{selectedTenants.size > 1 ? 's' : ''} selected
)} {/* Tenants Table */} {loading ? (
) : (
{filteredTenants.map(tenant => ( ))}
{ if (e.target.checked) { setSelectedTenants(new Set(filteredTenants.map(t => t.id))); } else { setSelectedTenants(new Set()); } }} checked={selectedTenants.size === filteredTenants.length && filteredTenants.length > 0} /> Tenant Status Template Users Resources Usage Activity Actions
{ const newSelected = new Set(selectedTenants); if (e.target.checked) { newSelected.add(tenant.id); } else { newSelected.delete(tenant.id); } setSelectedTenants(newSelected); }} />
{tenant.name}
{tenant.domain}.gt2.com
{tenant.namespace}
{getStatusBadge(tenant.status)} {getDeploymentBadge(tenant.deployment_status)}
{getTemplateBadge(tenant.template)}
{tenant.current_users}
of {tenant.max_users}
{tenant.resource_count}
{tenant.storage_used_gb && (
{tenant.storage_used_gb.toFixed(1)} GB
)} {tenant.api_calls_today && (
{tenant.api_calls_today.toLocaleString()}
)}
{tenant.last_activity && (
{new Date(tenant.last_activity).toLocaleTimeString()}
)}
)}
); }