"use client"; import type { UserRole } from "@prisma/client"; import { Activity, BarChart3, Building2, Check, Copy, Database, Plus, Search, Settings, 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 { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { ThemeToggle } from "@/components/ui/theme-toggle"; import { useToast } from "@/hooks/use-toast"; import { authClient } from "@/lib/auth/client"; 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 PlatformUserData { id: string; email: string; name: string | null; role: UserRole; } // Platform roles for checking const PLATFORM_ROLES: UserRole[] = [ "PLATFORM_SUPER_ADMIN", "PLATFORM_ADMIN", "PLATFORM_SUPPORT", ]; function isPlatformRole(role: UserRole): boolean { return PLATFORM_ROLES.includes(role); } // Custom hook for platform user data function usePlatformUser() { const { data: sessionData, isPending } = authClient.useSession(); const [platformUser, setPlatformUser] = useState( null ); const [isLoading, setIsLoading] = useState(true); useEffect(() => { if (isPending) return; if (!sessionData?.session) { setPlatformUser(null); setIsLoading(false); return; } // Fetch user data from our API to get role const fetchUser = async () => { try { const response = await fetch("/api/auth/me"); if (response.ok) { const userData = await response.json(); if (isPlatformRole(userData.role)) { setPlatformUser(userData); } else { setPlatformUser(null); } } else { setPlatformUser(null); } } catch { setPlatformUser(null); } finally { setIsLoading(false); } }; fetchUser(); }, [sessionData, isPending]); return { user: platformUser, isLoading: isPending || isLoading, isAuthenticated: !!platformUser, }; } export default function PlatformDashboard() { const { user, isLoading: userLoading, isAuthenticated } = usePlatformUser(); const router = useRouter(); const { toast } = useToast(); 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: "", maxUsers: 10, }); const companyNameId = useId(); const csvUrlId = useId(); const csvUsernameId = useId(); const csvPasswordId = useId(); const adminNameId = useId(); const adminEmailId = useId(); const maxUsersId = useId(); 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); } }, []); useEffect(() => { if (userLoading) return; if (!isAuthenticated) { router.push("/platform/login"); return; } fetchDashboardData(); }, [userLoading, isAuthenticated, 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 handleCreateCompany = async () => { if ( !newCompanyData.name || !newCompanyData.csvUrl || !newCompanyData.adminEmail || !newCompanyData.adminName ) { toast({ title: "Error", description: "Please fill in all required fields", variant: "destructive", }); return; } setIsCreating(true); try { const response = await fetch("/api/platform/companies", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(newCompanyData), }); if (response.ok) { const result = await response.json(); setShowAddCompany(false); const companyName = newCompanyData.name; setNewCompanyData({ name: "", csvUrl: "", csvUsername: "", csvPassword: "", adminEmail: "", adminName: "", maxUsers: 10, }); fetchDashboardData(); if (result.adminUser) { toast({ title: "Company Created Successfully!", description: (

Company "{companyName}" has been created.

Admin Email:

{result.adminUser.email}

{result.inviteLink && (

Invite Link:

{result.inviteLink}

)}
), duration: 15000, }); } else { toast({ title: "Success", description: `Company "${companyName}" created successfully`, }); } } else { const error = await response.json(); throw new Error(error.error || "Failed to create company"); } } catch (error) { toast({ title: "Error", description: error instanceof Error ? error.message : "Failed to create company", variant: "destructive", }); } 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 (userLoading || isLoading) { return (
Loading platform dashboard...
); } if (!isAuthenticated || !user) { 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 (

Platform Dashboard

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

setSearchTerm(e.target.value)} className="pl-10 w-64" />
Total Companies
{totalCompanies}
Total Users
{totalUsers}
Total Sessions
{totalSessions}
Active Companies
{dashboardData?.companies?.filter((c) => c.status === "ACTIVE") .length || 0}
Companies {searchTerm && ( {filteredCompanies.length} of {totalCompanies} shown )}
{searchTerm && ( Search: "{searchTerm}" )} Add New Company Create a new company and invite the first administrator.
setNewCompanyData((prev) => ({ ...prev, name: e.target.value, })) } placeholder="Acme Corporation" />
setNewCompanyData((prev) => ({ ...prev, csvUrl: e.target.value, })) } placeholder="https://api.company.com/sessions.csv" />
setNewCompanyData((prev) => ({ ...prev, csvUsername: e.target.value, })) } placeholder="Optional HTTP auth username" />
setNewCompanyData((prev) => ({ ...prev, csvPassword: e.target.value, })) } placeholder="Optional HTTP auth password" />
setNewCompanyData((prev) => ({ ...prev, adminName: e.target.value, })) } placeholder="John Doe" />
setNewCompanyData((prev) => ({ ...prev, adminEmail: e.target.value, })) } placeholder="admin@acme.com" />
setNewCompanyData((prev) => ({ ...prev, maxUsers: Number.parseInt(e.target.value) || 10, })) } min="1" max="1000" />
{filteredCompanies.map((company) => (

{company.name}

{company.status}
{company._count.users} users {company._count.sessions} sessions {company._count.imports} imports Created{" "} {new Date(company.createdAt).toLocaleDateString()}
))} {!filteredCompanies.length && (
{searchTerm ? (

No companies match "{searchTerm}".

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