diff --git a/client/pages/hub/ClientHub.tsx b/client/pages/hub/ClientHub.tsx index d5fb4cc4..8661768b 100644 --- a/client/pages/hub/ClientHub.tsx +++ b/client/pages/hub/ClientHub.tsx @@ -1,378 +1,466 @@ import { useState, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; import Layout from "@/components/Layout"; import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { useNavigate } from "react-router-dom"; import { useAuth } from "@/contexts/AuthContext"; +import { aethexToast } from "@/lib/aethex-toast"; +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 { FileText, - Briefcase, - Clock, - AlertCircle, + DollarSign, TrendingUp, + Users, + Calendar, + CheckCircle, + AlertCircle, BarChart3, - Settings, - LogOut, + Clock, + ArrowRight, + MessageSquare, + Phone, } from "lucide-react"; -import { Badge } from "@/components/ui/badge"; + +const API_BASE = import.meta.env.VITE_API_BASE || ""; export default function ClientHub() { const navigate = useNavigate(); - const { user, signOut } = useAuth(); - const [isLoading, setIsLoading] = useState(true); + const { user, loading: authLoading } = useAuth(); + const [activeTab, setActiveTab] = useState("overview"); + const [opportunities, setOpportunities] = useState([]); + const [contracts, setContracts] = useState([]); + const [loading, setLoading] = useState(true); useEffect(() => { - // Simulate loading - const timer = setTimeout(() => { - setIsLoading(false); - }, 500); - return () => clearTimeout(timer); - }, []); + if (!authLoading && user) { + loadDashboardData(); + } + }, [user, authLoading]); + + const loadDashboardData = async () => { + try { + setLoading(true); + const token = (await (window as any).supabaseClient.auth.getSession()).data?.session?.access_token; + if (!token) throw new Error("No auth token"); + + // Load opportunities + const oppRes = await fetch(`${API_BASE}/api/nexus/client/opportunities`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (oppRes.ok) { + const data = await oppRes.json(); + setOpportunities(data.opportunities || []); + } + + // Load contracts + const contractRes = await fetch(`${API_BASE}/api/nexus/client/contracts`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (contractRes.ok) { + const data = await contractRes.json(); + setContracts(data.contracts || []); + } + } catch (error: any) { + console.error("Failed to load hub data", error); + } finally { + setLoading(false); + } + }; + + if (authLoading || loading) { + return ; + } if (!user) { return ( -
- - - Client Portal Access Required - - -

- You must be signed in to access the Client Hub. -

-
- - -
-
-
+
+
+

+ Client Hub +

+

Enterprise collaboration & hiring

+ +
); } - // Mock data for demonstration - const stats = [ - { - label: "Active Projects", - value: "3", - icon: Briefcase, - color: "bg-blue-500/10 text-blue-400", - }, - { - label: "Pending Invoices", - value: "$24,500", - icon: FileText, - color: "bg-amber-500/10 text-amber-400", - }, - { - label: "Active Contracts", - value: "5", - icon: FileText, - color: "bg-green-500/10 text-green-400", - }, - { - label: "Support Tickets", - value: "2", - icon: AlertCircle, - color: "bg-red-500/10 text-red-400", - }, - ]; - - const recentProjects = [ - { - id: 1, - name: "Roblox Game Development", - status: "In Progress", - progress: 65, - dueDate: "2025-02-28", - team: ["Alex Chen", "Jordan Smith"], - }, - { - id: 2, - name: "AI Integration Project", - status: "In Progress", - progress: 45, - dueDate: "2025-03-15", - team: ["Taylor Brown", "Casey Johnson"], - }, - { - id: 3, - name: "Mobile App Launch", - status: "On Hold", - progress: 30, - dueDate: "2025-04-01", - team: ["Morgan Davis"], - }, - ]; - - const menuItems = [ - { - icon: BarChart3, - label: "Dashboard", - path: "/hub/client/dashboard", - description: "Overview of all projects", - }, - { - icon: Briefcase, - label: "Projects", - path: "/hub/client/projects", - description: "View and manage projects", - }, - { - icon: FileText, - label: "Invoices", - path: "/hub/client/invoices", - description: "Track invoices and payments", - }, - { - icon: FileText, - label: "Contracts", - path: "/hub/client/contracts", - description: "Review contracts and agreements", - }, - { - icon: TrendingUp, - label: "Reports", - path: "/hub/client/reports", - description: "Project reports and analytics", - }, - { - icon: Settings, - label: "Settings", - path: "/hub/client/settings", - description: "Manage account preferences", - }, - ]; + const openOpportunities = opportunities.filter((o: any) => o.status === "open"); + const totalSpent = contracts.reduce((sum: number, c: any) => sum + (c.total_amount || 0), 0); + const activeContracts = contracts.filter((c: any) => c.status === "active"); + const pendingApplications = openOpportunities.reduce((sum: number, o: any) => sum + (o.application_count || 0), 0); return ( -
- {/* Background */} -
-
-
-
- -
+
+
{/* Header */} -
-
-
-

- Client Portal +
+
+
+

+ Client Hub

+

+ Enterprise hiring & project management +

+
+
-

- Welcome, {user?.email || "Client"}. Manage your projects, - invoices, and agreements. -

-

- {/* Quick Stats */} -
-
-
- {stats.map((stat) => { - const Icon = stat.icon; - return ( - - -
-
-

- {stat.label} -

-

- {stat.value} -

-
-
- -
-
-
-
- ); - })} -
-
-
- - {/* Main Navigation Grid */} -
-
-

Quick Access

-
- {menuItems.map((item) => { - const Icon = item.icon; - return ( - navigate(item.path)} - > - -
-
- -
-
-

- {item.label} -

-

- {item.description} -

-
-
-
-
- ); - })} -
-
-
- - {/* Recent Projects */} -
-
-
-

Recent Projects

- -
-
- {recentProjects.map((project) => ( - - -
-
-

- {project.name} -

-
- - {project.status} - -
- - Due {project.dueDate} -
-
-
-
- - {/* Progress Bar */} -
-
- - Progress - - - {project.progress}% - -
-
-
-
-
- - {/* Team */} -
-
- {project.team.map((member) => ( -
- {member} -
- ))} -
- -
- - - ))} -
-
-
- - {/* Support Section */} -
-
- - - Need Help? - - -

- Contact our support team for assistance with your projects, - invoices, or any questions about your contracts. -

-
- - + {/* Quick Stats */} +
+ + +
+

Open Opportunities

+
+

{openOpportunities.length}

+
+
+ + + +
+

Applications

+ +
+

{pendingApplications}

+
+
+ + + +
+

Active Contracts

+ +
+

{activeContracts.length}

+
+
+ + + +
+

Total Spent

+ +
+

+ ${totalSpent.toLocaleString('en-US', { maximumFractionDigits: 0 })} +

-
-
+
+ + {/* Tabs */} + + + Overview + Opportunities + Contracts + Support + + + {/* Overview Tab */} + + {/* Account Manager Card */} + + + + + Your AeThex Team + + + +
+ {/* Account Manager */} +
+

Account Manager

+
+
+ AC +
+
+

Account Manager

+

account@aethex.dev

+
+
+ +
+ + {/* Solutions Architect */} +
+

Solutions Architect

+
+
+ SA +
+
+

Solutions Architect

+

architect@aethex.dev

+
+
+ +
+
+
+
+ + {/* Recent Activity */} +
+ {/* Recent Opportunities */} + + + Recent Opportunities + Latest job postings + + + {openOpportunities.length === 0 ? ( +
+ +

No opportunities posted yet

+
+ ) : ( +
+ {openOpportunities.slice(0, 3).map((opp: any) => ( +
+
+

{opp.title}

+ {opp.status} +
+

{opp.application_count} applications

+
+ ))} +
+ )} +
+
+ + {/* Recent Contracts */} + + + Active Contracts + Your current projects + + + {contracts.length === 0 ? ( +
+ +

No active contracts

+
+ ) : ( +
+ {contracts.slice(0, 3).map((contract: any) => ( +
+
+

{contract.title}

+ {contract.status} +
+

${contract.total_amount?.toLocaleString()}

+
+ ))} +
+ )} +
+
+
+
+ + {/* Opportunities Tab */} + + + +
+
+ Your Opportunities + Job postings and projects +
+ +
+
+ + {opportunities.length === 0 ? ( +
+ +

No opportunities posted yet

+ +
+ ) : ( +
+ {opportunities.map((opp: any) => ( +
+
+
+

{opp.title}

+

{opp.description?.substring(0, 100)}...

+
+ {opp.status} +
+
+ ${opp.budget_min?.toLocaleString()} - ${opp.budget_max?.toLocaleString()} + {opp.application_count} applications +
+
+ ))} +
+ )} +
+
+
+ + {/* Contracts Tab */} + + + + Contracts & Invoices + Payment history and status + + + {contracts.length === 0 ? ( +
+ +

No contracts yet

+
+ ) : ( +
+ {contracts.map((contract: any) => ( +
+
+
+

{contract.title}

+

Contract Type: {contract.contract_type}

+
+ {contract.status} +
+
+
+

Total Amount

+

${contract.total_amount?.toLocaleString()}

+
+
+

Your Cost

+

${(contract.total_amount - (contract.aethex_commission_amount || 0))?.toLocaleString()}

+
+
+

Creator Payout

+

${contract.creator_payout_amount?.toLocaleString()}

+
+
+
+ ))} +
+ )} +
+
+
+ + {/* Support Tab */} + + + + Support & Resources + + + + + + + + + + + {/* Request New SOW */} + + + Request New Scope + + +

+ Need a new Statement of Work (SOW) or to modify an existing contract? Contact your account manager. +

+ +
+
+
+
+
);