diff --git a/client/pages/dashboards/StaffDashboard.tsx b/client/pages/dashboards/StaffDashboard.tsx index 9e59e6da..df9c9b73 100644 --- a/client/pages/dashboards/StaffDashboard.tsx +++ b/client/pages/dashboards/StaffDashboard.tsx @@ -1,100 +1,340 @@ +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 } from "@/components/ui/card"; -import { Shield, ArrowRight, FileText, MessageSquare, Zap } from "lucide-react"; +import { useAuth } from "@/contexts/AuthContext"; +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 { Shield, Target, DollarSign, FileText, Users, Link as LinkIcon, Calendar, Book, AlertCircle, Search, ExternalLink } from "lucide-react"; + +const API_BASE = import.meta.env.VITE_API_BASE || ""; export default function StaffDashboard() { + const navigate = useNavigate(); + const { user, loading: authLoading } = useAuth(); + const [activeTab, setActiveTab] = useState("overview"); + const [staffMember, setStaffMember] = useState(null); + const [okrs, setOkrs] = useState([]); + const [invoices, setInvoices] = useState([]); + const [directory, setDirectory] = useState([]); + const [searchQuery, setSearchQuery] = 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"); + + const memberRes = await fetch(`${API_BASE}/api/staff/me`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (memberRes.ok) setStaffMember(await memberRes.json()); + + const okrRes = await fetch(`${API_BASE}/api/staff/okrs`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (okrRes.ok) setOkrs(await okrRes.json()); + + const invRes = await fetch(`${API_BASE}/api/staff/invoices`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (invRes.ok) setInvoices(await invRes.json()); + + const dirRes = await fetch(`${API_BASE}/api/staff/directory`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (dirRes.ok) setDirectory(await dirRes.json()); + } catch (error) { + console.error("Failed to load STAFF data", error); + } finally { + setLoading(false); + } + }; + + const isEmployee = staffMember?.employment_type === "employee"; + const isContractor = staffMember?.employment_type === "contractor"; + const filteredDirectory = directory.filter(member => + member.full_name?.toLowerCase().includes(searchQuery.toLowerCase()) || + member.role?.toLowerCase().includes(searchQuery.toLowerCase()) + ); + + if (authLoading || loading) { + return ; + } + + if (!user) { + return ( + +
+
+

+ STAFF Portal +

+

Employee & Contractor Hub

+ +
+
+
+ ); + } + return ( -
-
+
+
{/* Header */} -
-
-
-
- -
-
-

- STAFF Employee Portal -

-

- This is the future A-Corp internal dashboard for OKRs, benefits, and HR tools. -

-
- - {/* Coming Soon Card */} - - - {/* Status */} -
-
-

Coming Soon

-
-

- The full bespoke STAFF dashboard with OKR tracking, benefits management, and HR tools is currently in development per our Phase 3 Roadmap. -

-
- - {/* Guiding CTA */} -
-
-

- - Access Internal Resources -

-

- All A-Corp SOPs, Handbooks, and Benefit Guides are located in our Internal Doc Hub. All team chat happens in our private Slack. -

-
-
- - -
-
-
-
- - {/* Features Coming */} -
- - -

🎯

-

OKRs & Goals

-

Track quarterly objectives

-
-
- - -

💰

-

Benefits & Payroll

-

Manage compensation & benefits

-
-
- - -

📚

-

Company Resources

-

SOPs, handbooks & guides

-
-
-
+
+

+ STAFF Portal +

+

Employee & Contractor Management | Professional Utility Purple

+ + {/* Tabs */} + + + Overview + {isEmployee && OKRs} + {isEmployee && Pay & Benefits} + {isContractor && Invoices} + Directory + + + {/* Overview Tab */} + +
+ + +

Employment Type

+

{staffMember?.employment_type || "—"}

+
+
+ + +

Department

+

{staffMember?.department || "—"}

+
+
+ + +

Start Date

+

{staffMember?.start_date ? new Date(staffMember.start_date).toLocaleDateString() : "—"}

+
+
+
+ + {/* Quick Links */} + + + Quick Actions + + + + + + + +
+ + {/* OKRs Tab - Employee Only */} + {isEmployee && ( + + + + My OKRs + Quarterly Objectives & Key Results + + + {okrs.length === 0 ? ( +
+ +

No OKRs set for this quarter

+
+ ) : ( +
+ {okrs.map((okr: any) => ( +
+
+
+

{okr.objective}

+

{okr.description}

+
+ + {okr.status} + +
+
+ {okr.key_results?.map((kr: any) => ( +
+ +
+

{kr.title}

+
+ Progress + {kr.progress}% +
+
+
+
+
+
+ ))} +
+
+ ))} +
+ )} + + + + )} + + {/* Pay & Benefits Tab - Employee Only */} + {isEmployee && ( + + + + Pay & Benefits + Payroll and compensation information + + +
+

Base Salary

+

${staffMember?.salary?.toLocaleString() || "—"}

+
+ +

+ View your paystubs, tax documents, and benefits in the Rippling employee portal. +

+
+
+
+ )} + + {/* Invoices Tab - Contractor Only */} + {isContractor && ( + + + + My Invoices + SOP-301: Contractor Invoice Portal + + + {invoices.length === 0 ? ( +
+ +

No invoices submitted

+
+ ) : ( +
+ {invoices.map((invoice: any) => ( +
+
+
+

{invoice.invoice_number}

+

{new Date(invoice.date).toLocaleDateString()}

+
+
+

${invoice.amount?.toLocaleString()}

+ + {invoice.status} + +
+
+
+ ))} +
+ )} +
+
+
+ )} + + {/* Directory Tab */} + + + + Internal Directory + Find employees and contractors + + + {/* Search Bar */} +
+ + setSearchQuery(e.target.value)} + className="w-full pl-10 pr-4 py-2 bg-black/30 border border-purple-500/20 rounded-lg text-white placeholder-gray-500" + /> +
+ + {/* Directory List */} + {filteredDirectory.length === 0 ? ( +
+ +

{searchQuery ? "No results found" : "No team members"}

+
+ ) : ( +
+ {filteredDirectory.map((member: any) => ( +
navigate(`/passport/${member.username}`)}> +
+ {member.full_name} +
+

{member.full_name}

+

{member.role}

+ + {member.employment_type === "employee" ? "👨‍💼 Employee" : "📋 Contractor"} + +
+
+
+ ))} +
+ )} +
+
+
+