import { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import Layout from "@/components/Layout"; import { Button } from "@/components/ui/button"; import { useAuth } from "@/contexts/AuthContext"; import { aethexToast } from "@/lib/aethex-toast"; import { supabase } from "@/lib/supabase"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import LoadingScreen from "@/components/LoadingScreen"; import ProjectStatusWidget from "@/components/ProjectStatusWidget"; import { FileText, DollarSign, TrendingUp, Users, Calendar, CheckCircle, AlertCircle, BarChart3, Clock, ArrowRight, MessageSquare, Phone, Briefcase, ArrowDown, MapPin, } from "lucide-react"; const API_BASE = import.meta.env.VITE_API_BASE || ""; export default function ClientHub() { const navigate = useNavigate(); const { user, loading: authLoading } = useAuth(); const [activeTab, setActiveTab] = useState("overview"); const [contracts, setContracts] = useState([]); const [invoices, setInvoices] = useState([]); const [teamMembers, setTeamMembers] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { if (!authLoading && user) { loadDashboardData(); } }, [user, authLoading]); const loadDashboardData = async () => { try { setLoading(true); const { data: { session }, } = await supabase.auth.getSession(); const token = session?.access_token; if (!token) throw new Error("No auth token"); // Load contracts for milestone tracking const contractRes = await fetch( `${API_BASE}/api/corp/contracts?limit=10`, { headers: { Authorization: `Bearer ${token}` }, }, ); if (contractRes.ok) { const data = await contractRes.json(); setContracts(Array.isArray(data) ? data : data.contracts || []); } // Load invoices const invoiceRes = await fetch(`${API_BASE}/api/corp/invoices?limit=20`, { headers: { Authorization: `Bearer ${token}` }, }); if (invoiceRes.ok) { const data = await invoiceRes.json(); setInvoices(Array.isArray(data) ? data : data.invoices || []); } // Load team members (Account Manager, Solutions Architect) const teamRes = await fetch(`${API_BASE}/api/corp/team`, { headers: { Authorization: `Bearer ${token}` }, }); if (teamRes.ok) { const data = await teamRes.json(); setTeamMembers(Array.isArray(data) ? data : data.team || []); } } catch (error: any) { console.error("Failed to load CORP dashboard data", error); aethexToast({ message: "Failed to load some dashboard data", type: "error", }); } finally { setLoading(false); } }; if (authLoading || loading) { return ; } if (!user) { return (

CORP Client Portal

Enterprise solutions for your business

); } const activeContract = contracts.find((c) => c.status === "active"); const completedMilestones = activeContract?.milestones?.filter((m: any) => m.status === "completed") .length || 0; const totalMilestones = activeContract?.milestones?.length || 0; const outstandingInvoices = invoices.filter( (i: any) => i.status === "pending" || i.status === "overdue", ).length; const totalInvoiceValue = invoices.reduce( (acc, inv) => acc + (inv.amount || 0), 0, ); const accountManager = teamMembers.find((t) => t.role === "account_manager"); const solutionsArchitect = teamMembers.find( (t) => t.role === "solutions_architect", ); return (
{/* Header */}

CORP Client Portal

Enterprise solutions, project status, and billing management

{/* Quick Stats */}

Active Projects

{contracts.filter((c) => c.status === "active").length}

Total Invoices

${(totalInvoiceValue / 1000).toFixed(0)}k

0 ? "from-orange-950/40 to-orange-900/20 border-orange-500/20" : "from-green-950/40 to-green-900/20 border-green-500/20"}`} >

Outstanding

{outstandingInvoices}

0 ? "#f97316" : "#22c55e", opacity: 0.5, }} />

Team Members

{teamMembers.length}

{/* Tabs */} Overview Project Status Invoices & Billing My AeThex Team {/* Overview Tab */} {/* QuantumLeap Dashboard */} My QuantumLeap Dashboard Live AI analytics and insights for your project