"use client"; import { Activity, BarChart3, Building2, Check, Copy, Database, LogOut, MoreVertical, Plus, Search, Settings, Shield, User, Users, } from "lucide-react"; import { useRouter } from "next/navigation"; import { useCallback, useEffect, useId, useState } from "react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { ThemeToggle } from "@/components/ui/theme-toggle"; import { useToast } from "@/hooks/use-toast"; interface Company { id: string; name: string; status: string; createdAt: string; _count: { users: number; sessions: number; imports: number; }; } interface DashboardData { companies: Company[]; pagination: { total: number; pages: number; }; } interface PlatformSession { user: { id: string; email: string; name?: string; isPlatformUser: boolean; platformRole: string; }; } interface NewCompanyData { name: string; csvUrl: string; csvUsername: string; csvPassword: string; adminEmail: string; adminName: string; adminPassword: string; maxUsers: number; } interface FormIds { companyNameId: string; csvUrlId: string; csvUsernameId: string; csvPasswordId: string; adminEmailId: string; adminNameId: string; adminPasswordId: string; maxUsersId: string; } // Custom hook for platform session function usePlatformSession() { const [session, setSession] = useState(null); const [status, setStatus] = useState< "loading" | "authenticated" | "unauthenticated" >("loading"); useEffect(() => { const fetchSession = async () => { try { const response = await fetch("/api/platform/auth/session"); const sessionData = await response.json(); if (sessionData?.user?.isPlatformUser) { setSession(sessionData); setStatus("authenticated"); } else { setSession(null); setStatus("unauthenticated"); } } catch (error) { console.error("Platform session fetch error:", error); setSession(null); setStatus("unauthenticated"); } }; fetchSession(); }, []); return { data: session, status }; } /** * Custom hook for managing platform dashboard state */ function usePlatformDashboardState() { const [dashboardData, setDashboardData] = useState( null ); const [isLoading, setIsLoading] = useState(true); const [showAddCompany, setShowAddCompany] = useState(false); const [isCreating, setIsCreating] = useState(false); const [copiedEmail, setCopiedEmail] = useState(false); const [copiedPassword, setCopiedPassword] = useState(false); const [searchTerm, setSearchTerm] = useState(""); const [newCompanyData, setNewCompanyData] = useState({ name: "", csvUrl: "", csvUsername: "", csvPassword: "", adminEmail: "", adminName: "", adminPassword: "", maxUsers: 10, }); return { dashboardData, setDashboardData, isLoading, setIsLoading, showAddCompany, setShowAddCompany, isCreating, setIsCreating, copiedEmail, setCopiedEmail, copiedPassword, setCopiedPassword, searchTerm, setSearchTerm, newCompanyData, setNewCompanyData, }; } /** * Custom hook for form IDs */ function useFormIds() { const companyNameId = useId(); const csvUrlId = useId(); const csvUsernameId = useId(); const csvPasswordId = useId(); const adminEmailId = useId(); const adminNameId = useId(); const adminPasswordId = useId(); const maxUsersId = useId(); return { companyNameId, csvUrlId, csvUsernameId, csvPasswordId, adminEmailId, adminNameId, adminPasswordId, maxUsersId, }; } /** * Render company form fields */ function renderCompanyFormFields( newCompanyData: NewCompanyData, setNewCompanyData: ( updater: (prev: NewCompanyData) => NewCompanyData ) => void, formIds: FormIds ) { return (
setNewCompanyData((prev: NewCompanyData) => ({ ...prev, name: e.target.value, })) } placeholder="Acme Corporation" />
setNewCompanyData((prev: NewCompanyData) => ({ ...prev, csvUrl: e.target.value, })) } placeholder="https://api.company.com/sessions.csv" />
setNewCompanyData((prev: NewCompanyData) => ({ ...prev, csvUsername: e.target.value, })) } placeholder="Optional HTTP auth username" />
setNewCompanyData((prev: NewCompanyData) => ({ ...prev, csvPassword: e.target.value, })) } placeholder="Optional HTTP auth password" />
setNewCompanyData((prev: NewCompanyData) => ({ ...prev, adminName: e.target.value, })) } placeholder="John Doe" />
setNewCompanyData((prev: NewCompanyData) => ({ ...prev, adminEmail: e.target.value, })) } placeholder="admin@acme.com" />
setNewCompanyData((prev: NewCompanyData) => ({ ...prev, adminPassword: e.target.value, })) } placeholder="Leave empty to auto-generate" />
setNewCompanyData((prev: NewCompanyData) => ({ ...prev, maxUsers: Number.parseInt(e.target.value) || 10, })) } min="1" max="1000" />
); } /** * Render company list item */ function renderCompanyListItem( company: Company, getStatusBadgeVariant: (status: string) => string, router: { push: (url: string) => void } ) { return (

{company.name}

{company.status}
{company._count.users} users {company._count.sessions} sessions {company._count.imports} imports Created {new Date(company.createdAt).toLocaleDateString()}
); } /** * Render dashboard header with user info and actions */ function renderDashboardHeader( session: PlatformSession, searchTerm: string, setSearchTerm: (term: string) => void, router: { push: (url: string) => void } ) { return (

Platform Dashboard

Welcome back, {session.user.name || session.user.email}

setSearchTerm(e.target.value)} className="pl-10 w-64" />

{session.user.name || session.user.email}

{session.user.platformRole || "Platform User"}

router.push("/platform/settings")} > Account Settings { await fetch("/api/platform/auth/logout", { method: "POST", }); router.push("/platform/login"); }} className="text-red-600" > Sign Out
); } /** * Render dashboard statistics cards */ function renderDashboardStats( totalCompanies: number, totalUsers: number, totalSessions: number, activeCompanies: number ) { return (
Total Companies
{totalCompanies}
Total Users
{totalUsers}
Total Sessions
{totalSessions}
Active Companies
{activeCompanies}
); } export default function PlatformDashboard() { const { data: session, status } = usePlatformSession(); const router = useRouter(); const { toast } = useToast(); const { dashboardData, setDashboardData, isLoading, setIsLoading, showAddCompany, setShowAddCompany, isCreating, setIsCreating, copiedEmail, setCopiedEmail, copiedPassword, setCopiedPassword, searchTerm, setSearchTerm, newCompanyData, setNewCompanyData, } = usePlatformDashboardState(); const { companyNameId, csvUrlId, csvUsernameId, csvPasswordId, adminEmailId, adminNameId, adminPasswordId, maxUsersId, } = useFormIds(); const fetchDashboardData = useCallback(async () => { try { const response = await fetch("/api/platform/companies"); if (response.ok) { const data = await response.json(); setDashboardData(data); } } catch (error) { console.error("Failed to fetch dashboard data:", error); } finally { setIsLoading(false); } }, [setDashboardData, setIsLoading]); useEffect(() => { if (status === "loading") return; if (status === "unauthenticated" || !session?.user?.isPlatformUser) { router.push("/platform/login"); return; } fetchDashboardData(); }, [session, status, router, fetchDashboardData]); const copyToClipboard = async (text: string, type: "email" | "password") => { try { await navigator.clipboard.writeText(text); if (type === "email") { setCopiedEmail(true); setTimeout(() => setCopiedEmail(false), 2000); } else { setCopiedPassword(true); setTimeout(() => setCopiedPassword(false), 2000); } } catch (err) { console.error("Failed to copy: ", err); } }; const getFilteredCompanies = () => { if (!dashboardData?.companies) return []; return dashboardData.companies.filter((company) => company.name.toLowerCase().includes(searchTerm.toLowerCase()) ); }; const validateCompanyData = () => { return !!( newCompanyData.name && newCompanyData.csvUrl && newCompanyData.adminEmail && newCompanyData.adminName ); }; const showValidationError = () => { toast({ title: "Error", description: "Please fill in all required fields", variant: "destructive", }); }; const createCompanyRequest = async () => { const response = await fetch("/api/platform/companies", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(newCompanyData), }); return response; }; const showCreateSuccessToast = ( result: { adminUser?: { name: string; email: string }; csvImportScheduled?: boolean; }, companyName: string ) => { toast({ title: "Success", description: `${companyName} created successfully! 🎉`, }); if (result.adminUser) { toast({ title: "Admin User Created", description: `Admin user ${result.adminUser.name} (${result.adminUser.email}) has been created`, }); } if (result.csvImportScheduled) { toast({ title: "CSV Import Scheduled", description: "CSV import has been scheduled and will begin processing shortly", }); } }; const showCredentialsToast = ( result: { adminUser: { email: string }; generatedPassword: string }, companyName: string ) => { toast({ title: "Company Created Successfully!", description: (

Company "{companyName}" has been created.

Admin Email:

{result.adminUser.email}

Admin Password:

{result.generatedPassword}

), duration: 15000, // Longer duration for credentials }); }; const showCreateErrorToast = (errorData: { error?: string }) => { toast({ title: "Error", description: errorData.error || "Failed to create company", variant: "destructive", }); }; const resetCreateForm = () => { setNewCompanyData({ name: "", csvUrl: "", csvUsername: "", csvPassword: "", adminEmail: "", adminName: "", adminPassword: "", maxUsers: 10, }); setShowAddCompany(false); }; const handleCreateCompany = async () => { if (!validateCompanyData()) { showValidationError(); return; } const companyName = newCompanyData.name; // Store before reset setIsCreating(true); try { const response = await createCompanyRequest(); if (response.ok) { const result = await response.json(); showCreateSuccessToast(result, companyName); resetCreateForm(); await fetchDashboardData(); if (result.generatedPassword) { showCredentialsToast(result, companyName); } } else { const errorData = await response.json(); showCreateErrorToast(errorData); } } catch (error) { showCreateErrorToast({ error: error instanceof Error ? error.message : "Failed to create company", }); } finally { setIsCreating(false); } }; const getStatusBadgeVariant = (status: string) => { switch (status) { case "ACTIVE": return "default"; case "TRIAL": return "secondary"; case "SUSPENDED": return "destructive"; case "ARCHIVED": return "outline"; default: return "default"; } }; if (status === "loading" || isLoading) { return (
Loading platform dashboard...
); } if (status === "unauthenticated" || !session?.user?.isPlatformUser) { return null; } const filteredCompanies = getFilteredCompanies(); const totalCompanies = dashboardData?.pagination?.total || 0; const totalUsers = dashboardData?.companies?.reduce( (sum, company) => sum + company._count.users, 0 ) || 0; const totalSessions = dashboardData?.companies?.reduce( (sum, company) => sum + company._count.sessions, 0 ) || 0; return (
{renderDashboardHeader(session, searchTerm, setSearchTerm, router)}
{/* Stats Overview */} {renderDashboardStats( totalCompanies, totalUsers, totalSessions, dashboardData?.companies?.filter((c) => c.status === "ACTIVE") .length || 0 )} {/* Companies List */}
Companies {searchTerm && ( {filteredCompanies.length} of {totalCompanies} shown )}
{searchTerm && ( Search: "{searchTerm}" )} Add New Company Create a new company and invite the first administrator. {renderCompanyFormFields( newCompanyData, setNewCompanyData, { companyNameId, csvUrlId, csvUsernameId, csvPasswordId, adminEmailId, adminNameId, adminPasswordId, maxUsersId, } )}
{filteredCompanies.map((company) => renderCompanyListItem(company, getStatusBadgeVariant, router) )} {!filteredCompanies.length && (
{searchTerm ? (

No companies match "{searchTerm}".

) : ( "No companies found. Create your first company to get started." )}
)}
); }