feat: Initialize monorepo structure and comprehensive documentation

This commit establishes the new monorepo architecture for the KROW Workforce platform.

Key changes include:
- Reorganized project into `frontend-web`, `mobile-apps`, `firebase`, `scripts`, and `secrets` directories.
- Updated `Makefile` to support the new monorepo layout and automate Base44 export integration.
- Fixed `scripts/prepare-export.js` for ES module compatibility and global component import resolution.
- Created and updated `CONTRIBUTING.md` for developer onboarding.
- Restructured, renamed, and translated all `docs/` files for clarity and consistency.
- Implemented an interactive internal launchpad with diagram viewing capabilities.
- Configured base Firebase project files (`firebase.json`, security rules).
- Updated `README.md` to reflect the new project structure and documentation overview.
This commit is contained in:
bwnyasse
2025-11-12 12:50:55 -05:00
parent 92fd0118be
commit 554dc9f9e3
203 changed files with 1414 additions and 732 deletions

View File

@@ -0,0 +1,740 @@
import React, { useState, useMemo } from "react";
import { base44 } from "@/api/base44Client";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Link, useNavigate } from "react-router-dom";
import { createPageUrl } from "@/utils";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Award, TrendingUp, Users, DollarSign, CheckCircle2, Clock, UserCheck, Mail, Edit, Bot, ArrowRight, Rocket, Star, Brain, Check, Sparkles, Zap, Calendar, Package, MessageSquare, AlertTriangle, MapPin, BarChart3, RefreshCw, Download, X, Lightbulb, TrendingDown, Timer } from "lucide-react";
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, BarChart, Bar } from 'recharts';
import { format, startOfMonth, endOfMonth, subMonths, differenceInHours, parseISO } from "date-fns";
import { useToast } from "@/components/ui/use-toast";
const mockWorkers = [
{ id: 1, name: "Maria G.", skill: "Server", rating: 4.9, distance: 3.2, reliability: 0.99, pro: 2 },
{ id: 2, name: "Andre P.", skill: "Culinary", rating: 4.8, distance: 5.5, reliability: 0.96, pro: 3 },
{ id: 3, name: "Jae L.", skill: "Dishwasher", rating: 4.6, distance: 1.1, reliability: 0.93, pro: 1 },
{ id: 4, name: "Rita C.", skill: "Server", rating: 4.7, distance: 4.0, reliability: 0.95, pro: 2 },
{ id: 5, name: "Luis M.", skill: "Culinary", rating: 4.5, distance: 7.4, reliability: 0.9, pro: 1 },
];
const proColors = {
1: "bg-slate-200 text-slate-800",
2: "bg-blue-100 text-blue-900",
3: "bg-amber-100 text-amber-900",
};
const formatPct = (v) => `${Math.round(v * 100)}%`;
function AINudge({ text, cta, onCta, type = "success", onDismiss }) {
const [dismissed, setDismissed] = useState(false);
const handleDismiss = () => {
setDismissed(true);
if (onDismiss) onDismiss();
};
if (dismissed) return null;
const typeConfig = {
success: {
icon: Sparkles,
gradient: "from-emerald-500 via-teal-500 to-cyan-500",
bgGradient: "from-emerald-50/80 via-teal-50/80 to-cyan-50/80",
iconBg: "from-emerald-400 to-teal-500",
textColor: "text-emerald-900",
subTextColor: "text-emerald-700",
buttonColor: "from-emerald-600 to-teal-600 hover:from-emerald-700 hover:to-teal-700",
borderColor: "border-emerald-200/60",
glowColor: "shadow-emerald-200/50"
},
insight: {
icon: Lightbulb,
gradient: "from-amber-500 via-orange-500 to-yellow-500",
bgGradient: "from-amber-50/80 via-orange-50/80 to-yellow-50/80",
iconBg: "from-amber-400 to-orange-500",
textColor: "text-amber-900",
subTextColor: "text-amber-700",
buttonColor: "from-amber-600 to-orange-600 hover:from-amber-700 hover:to-orange-700",
borderColor: "border-amber-200/60",
glowColor: "shadow-amber-200/50"
},
achievement: {
icon: Award,
gradient: "from-purple-500 via-pink-500 to-rose-500",
bgGradient: "from-purple-50/80 via-pink-50/80 to-rose-50/80",
iconBg: "from-purple-400 to-pink-500",
textColor: "text-purple-900",
subTextColor: "text-purple-700",
buttonColor: "from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700",
borderColor: "border-purple-200/60",
glowColor: "shadow-purple-200/50"
}
};
const config = typeConfig[type];
const IconComponent = config.icon;
return (
<div className={`relative overflow-hidden rounded-2xl bg-gradient-to-r ${config.bgGradient} backdrop-blur-sm border-2 ${config.borderColor} shadow-lg ${config.glowColor} transition-all duration-300 hover:shadow-xl hover:scale-[1.02]`}>
<div className={`absolute top-0 left-0 right-0 h-1 bg-gradient-to-r ${config.gradient}`} />
<div className="flex items-start gap-4 p-5">
<div className={`flex-shrink-0 w-12 h-12 rounded-xl bg-gradient-to-br ${config.iconBg} flex items-center justify-center shadow-lg`}>
<IconComponent className="w-6 h-6 text-white" />
</div>
<div className="flex-1 min-w-0 pt-1">
<div className="flex items-start gap-2 mb-2">
<Badge className={`bg-gradient-to-r ${config.gradient} text-white border-0 shadow-md text-xs font-bold px-2 py-0.5`}>
AI INSIGHT
</Badge>
</div>
<p className={`${config.textColor} font-semibold text-base leading-relaxed`}>
{text}
</p>
</div>
<div className="flex items-center gap-2 flex-shrink-0">
{cta && (
<Button
size="sm"
onClick={onCta}
className={`bg-gradient-to-r ${config.buttonColor} text-white shadow-lg rounded-xl font-semibold px-4 py-2 transition-all duration-200`}
>
{cta}
<ArrowRight className="w-4 h-4 ml-2" />
</Button>
)}
<Button
size="icon"
variant="ghost"
onClick={handleDismiss}
className={`h-8 w-8 rounded-lg ${config.subTextColor} hover:bg-white/50 transition-colors`}
>
<X className="w-4 h-4" />
</Button>
</div>
</div>
</div>
);
}
export default function VendorDashboard() {
const navigate = useNavigate();
const queryClient = useQueryClient();
const { toast } = useToast();
const { data: user } = useQuery({
queryKey: ['current-user-vendor'],
queryFn: () => base44.auth.me(),
});
const { data: events } = useQuery({
queryKey: ['vendor-events'],
queryFn: async () => {
const allEvents = await base44.entities.Event.list('-date');
if (!user?.email) return [];
return allEvents.filter(e =>
e.vendor_name === user?.company_name ||
e.vendor_id === user?.id ||
e.created_by === user?.email
);
},
initialData: [],
enabled: !!user
});
const { data: staff } = useQuery({
queryKey: ['vendor-staff'],
queryFn: async () => {
const allStaff = await base44.entities.Staff.list();
if (!user?.company_name) return allStaff.slice(0, 10);
return allStaff.filter(s => s.vendor_name === user?.company_name);
},
initialData: [],
enabled: !!user
});
// Calculations
const todayOrders = events.filter(e => {
const eventDate = new Date(e.date);
const today = new Date();
return eventDate.toDateString() === today.toDateString();
});
const activeOrders = events.filter(e => e.status === "Active" || e.status === "Confirmed" || e.status === "In Progress");
const completedOrders = events.filter(e => e.status === "Completed");
const totalRevenue = completedOrders.reduce((sum, e) => sum + (e.total || 0), 0);
const currentMonth = new Date().getMonth();
const currentYear = new Date().getFullYear();
const thisMonthOrders = events.filter(e => {
const eventDate = new Date(e.date);
return eventDate.getMonth() === currentMonth &&
eventDate.getFullYear() === currentYear &&
(e.status === "Completed" || e.status === "Active");
});
const thisMonthRevenue = thisMonthOrders.reduce((sum, e) => sum + (e.total || 0), 0);
const activeStaff = staff.filter(s => s.employment_type !== "Medical Leave" && s.action !== "Inactive").length;
const avgRating = staff.reduce((sum, s) => sum + (s.rating || 0), 0) / (staff.length || 1);
const reliabilityScore = staff.reduce((sum, s) => sum + (s.reliability_score || 0), 0) / (staff.length || 1);
// Rapid Orders (urgent orders within 24 hours)
const rapidOrders = events
.filter(e => {
const eventDate = new Date(e.date);
const now = new Date();
const hoursUntil = differenceInHours(eventDate, now);
return hoursUntil > 0 && hoursUntil <= 24 &&
(e.status === "Active" || e.status === "Confirmed" || e.status === "Pending");
})
.sort((a, b) => new Date(a.date) - new Date(b.date))
.slice(0, 3);
// 6-month revenue and payroll trend
const last6Months = Array.from({ length: 6 }, (_, i) => {
const date = subMonths(new Date(), 5 - i);
return {
month: format(date, 'MMM'),
fullDate: date
};
});
const salesPayrollTrend = last6Months.map(({ month, fullDate }) => {
const monthStart = startOfMonth(fullDate);
const monthEnd = endOfMonth(fullDate);
const monthOrders = events.filter(e => {
const eventDate = new Date(e.date);
return eventDate >= monthStart && eventDate <= monthEnd && e.status === "Completed";
});
const sales = monthOrders.reduce((sum, e) => sum + (e.total || 0), 0);
const payroll = sales * 0.68; // Assume 68% payroll ratio
return { month, sales, payroll };
});
// Top clients with fill rates
const clientRevenue = completedOrders.reduce((acc, event) => {
const client = event.business_name || "Unknown";
if (!acc[client]) {
acc[client] = { name: client, revenue: 0, orders: 0, requested: 0, assigned: 0 };
}
acc[client].revenue += (event.total || 0);
acc[client].orders++;
acc[client].requested += (event.requested || 0);
acc[client].assigned += (event.assigned_staff?.length || 0);
return acc;
}, {});
const topClients = Object.values(clientRevenue)
.map(c => ({
...c,
fillRate: c.requested > 0 ? (c.assigned / c.requested) * 100 : 0
}))
.sort((a, b) => b.revenue - a.revenue)
.slice(0, 4);
// Top performers with shift counts
const topPerformers = staff
.filter(s => s.rating > 0)
.sort((a, b) => (b.rating || 0) - (a.rating || 0))
.slice(0, 3)
.map(s => ({
...s,
shifts: s.total_shifts || Math.floor(Math.random() * 30) + 5
}));
// Staff assigned today
const staffAssignedToday = todayOrders.reduce((sum, e) => sum + (e.requested || 0), 0);
// Avg speed to fill (mock calculation)
const avgSpeedToFill = "1h 12m";
const speedChange = "-14m";
const hour = new Date().getHours();
const greeting = hour < 12 ? "Good morning" : hour < 18 ? "Good afternoon" : "Good evening";
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50/20 to-slate-50">
<div className="max-w-[1800px] mx-auto p-6 space-y-6">
{/* Header */}
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold text-[#1C323E] mb-1">
{greeting}, {user?.full_name?.split(' ')[0] || 'Partner'}
</h1>
<p className="text-slate-600">Here's your performance overview</p>
</div>
<div className="flex items-center gap-3">
<Button variant="outline">
<RefreshCw className="w-4 h-4 mr-2" />
Refresh
</Button>
<Button className="bg-[#0A39DF] hover:bg-[#0A39DF]/90">
<Download className="w-4 h-4 mr-2" />
Export
</Button>
</div>
</div>
{/* Top KPI Metrics - NEW DESIGN */}
<div className="grid grid-cols-4 gap-4">
{/* Sales */}
<Card className="bg-gradient-to-br from-white to-slate-50 border-slate-200 shadow-sm hover:shadow-md transition-all">
<CardContent className="p-6">
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 bg-slate-100 rounded-lg flex items-center justify-center">
<TrendingUp className="w-5 h-5 text-slate-700" />
</div>
<div>
<p className="text-xs text-slate-500 font-medium">Sales (M1D)</p>
</div>
</div>
<p className="text-4xl font-bold text-[#1C323E] mb-1">
${Math.round(thisMonthRevenue / 1000)},000
</p>
<p className="text-sm text-emerald-600 font-medium">+5% vs last month</p>
</CardContent>
</Card>
{/* Payroll */}
<Card className="bg-gradient-to-br from-white to-slate-50 border-slate-200 shadow-sm hover:shadow-md transition-all">
<CardContent className="p-6">
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 bg-slate-100 rounded-lg flex items-center justify-center">
<DollarSign className="w-5 h-5 text-slate-700" />
</div>
<div>
<p className="text-xs text-slate-500 font-medium">Payroll (M1D)</p>
</div>
</div>
<p className="text-4xl font-bold text-[#1C323E] mb-1">
${Math.round(thisMonthRevenue * 0.68 / 1000)},000
</p>
<p className="text-sm text-slate-600 font-medium">68% of sales</p>
</CardContent>
</Card>
{/* Active Workforce */}
<Card className="bg-gradient-to-br from-white to-slate-50 border-slate-200 shadow-sm hover:shadow-md transition-all">
<CardContent className="p-6">
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 bg-slate-100 rounded-lg flex items-center justify-center">
<Users className="w-5 h-5 text-slate-700" />
</div>
<div>
<p className="text-xs text-slate-500 font-medium">Active Workforce</p>
</div>
</div>
<p className="text-4xl font-bold text-[#1C323E] mb-1">
{activeStaff}
</p>
<p className="text-sm text-slate-600 font-medium">+3 this week</p>
</CardContent>
</Card>
{/* Avg Speed to Fill */}
<Card className="bg-gradient-to-br from-white to-slate-50 border-slate-200 shadow-sm hover:shadow-md transition-all">
<CardContent className="p-6">
<div className="flex items-center gap-3 mb-3">
<div className="w-10 h-10 bg-slate-100 rounded-lg flex items-center justify-center">
<Timer className="w-5 h-5 text-slate-700" />
</div>
<div>
<p className="text-xs text-slate-500 font-medium">Avg Speed-to-Fill</p>
</div>
</div>
<p className="text-4xl font-bold text-[#1C323E] mb-1">
{avgSpeedToFill}
</p>
<p className="text-sm text-emerald-600 font-medium">{speedChange} vs last week</p>
</CardContent>
</Card>
</div>
{/* AI Insights */}
<div className="space-y-4">
<AINudge
text="Assigned 6 top-fit workers. Consider adding 1 trainee for fairness and skill development."
cta="Add Trainee"
type="success"
onCta={() => {}}
/>
<AINudge
text="You're outperforming 82% of vendors in your region. Share your Gold badge to attract premium clients!"
cta="Share Badge"
type="achievement"
onCta={() => {}}
/>
</div>
{/* Main Content Grid */}
<div className="grid grid-cols-3 gap-6">
{/* Left Column (2 cols) */}
<div className="col-span-2 space-y-6">
{/* RAPID ORDERS - NEW SECTION */}
<Card className="bg-white border-slate-200 shadow-sm">
<CardHeader className="border-b border-slate-100 pb-4">
<div className="flex items-center justify-between">
<div>
<CardTitle className="text-base flex items-center gap-2">
<Zap className="w-5 h-5 text-amber-500" />
Rapid Orders
</CardTitle>
<p className="text-xs text-slate-600 mt-1">Urgent orders within 24 hours</p>
</div>
{rapidOrders.length > 0 && (
<Badge className="bg-red-100 text-red-700 border-red-200 font-bold">
{rapidOrders.length} Urgent
</Badge>
)}
</div>
</CardHeader>
<CardContent className="p-5">
{rapidOrders.length > 0 ? (
<div className="space-y-4">
{rapidOrders.map((order) => {
const eventDate = order.date ? parseISO(order.date) : new Date();
const hoursUntil = differenceInHours(eventDate, new Date());
const assignedCount = order.assigned_staff?.length || 0;
const requestedCount = order.requested || 0;
const fillPercentage = requestedCount > 0 ? Math.round((assignedCount / requestedCount) * 100) : 0;
return (
<div key={order.id} className="p-4 rounded-xl bg-gradient-to-r from-red-50 to-orange-50 border-2 border-red-200 hover:border-red-300 transition-all">
<div className="flex items-start justify-between mb-3">
<div>
<div className="flex items-center gap-2 mb-1">
<h3 className="font-bold text-[#1C323E]">{order.business_name || "Client"} {order.event_name}</h3>
<Badge className="bg-red-500 text-white font-bold text-xs">
{hoursUntil}h left
</Badge>
</div>
<div className="flex items-center gap-4 text-sm text-slate-600">
<div className="flex items-center gap-1">
<Users className="w-4 h-4" />
<span>{assignedCount}/{requestedCount} filled</span>
</div>
<div className="flex items-center gap-1">
<Calendar className="w-4 h-4" />
<span>{format(eventDate, "h:mm a")}</span>
</div>
</div>
</div>
<div className="flex gap-2">
<Link to={createPageUrl(`EventDetail?id=${order.id}`)}>
<Button size="sm" variant="outline" className="rounded-lg">
View
</Button>
</Link>
<Button size="sm" className="bg-red-600 hover:bg-red-700 text-white rounded-lg font-semibold">
Quick Assign
</Button>
</div>
</div>
<div className="flex items-center gap-2">
<div className="flex-1 h-2 bg-white rounded-full overflow-hidden">
<div
className={`h-full transition-all duration-500 ${
fillPercentage < 60 ? 'bg-red-500' :
fillPercentage < 90 ? 'bg-amber-500' :
'bg-green-500'
}`}
style={{ width: `${fillPercentage}%` }}
/>
</div>
<span className="text-sm font-bold text-slate-700">{fillPercentage}%</span>
</div>
</div>
);
})}
</div>
) : (
<div className="text-center py-12">
<Zap className="w-12 h-12 mx-auto text-slate-300 mb-3" />
<p className="text-sm text-slate-500 font-medium">No urgent orders</p>
<p className="text-xs text-slate-400 mt-1">Orders within 24h will appear here</p>
</div>
)}
</CardContent>
</Card>
{/* Sales vs Payroll Chart */}
<Card className="bg-white border-slate-200 shadow-sm">
<CardHeader className="border-b border-slate-100 pb-4">
<CardTitle className="text-base flex items-center gap-2">
<TrendingUp className="w-5 h-5 text-[#0A39DF]" />
Sales vs Payroll
</CardTitle>
</CardHeader>
<CardContent className="p-6">
<ResponsiveContainer width="100%" height={280}>
<BarChart data={salesPayrollTrend}>
<CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" vertical={false} />
<XAxis
dataKey="month"
tick={{ fontSize: 12 }}
stroke="#94a3b8"
axisLine={false}
tickLine={false}
/>
<YAxis
tick={{ fontSize: 12 }}
stroke="#94a3b8"
axisLine={false}
tickLine={false}
tickFormatter={(value) => `${(value / 1000).toFixed(0)}k`}
/>
<Tooltip
contentStyle={{
fontSize: '12px',
backgroundColor: 'white',
border: '1px solid #e2e8f0',
borderRadius: '12px',
padding: '8px 12px'
}}
formatter={(value) => [`$${Math.round(value).toLocaleString()}`, '']}
/>
<Bar dataKey="payroll" fill="#1C323E" radius={[4, 4, 0, 0]} />
<Bar dataKey="sales" fill="#000000" radius={[4, 4, 0, 0]} />
</BarChart>
</ResponsiveContainer>
</CardContent>
</Card>
{/* Client Analysis */}
<Card className="bg-white border-slate-200 shadow-sm">
<CardHeader className="border-b border-slate-100 pb-4">
<CardTitle className="text-base flex items-center gap-2">
<BarChart3 className="w-5 h-5 text-[#0A39DF]" />
Client Analysis
</CardTitle>
</CardHeader>
<CardContent className="p-6">
{topClients.length > 0 ? (
<div className="space-y-5">
{topClients.map((client) => (
<div key={client.name} className="space-y-2">
<div className="flex items-center justify-between">
<div>
<h4 className="font-bold text-[#1C323E]">{client.name}</h4>
<p className="text-xs text-slate-500">Fill</p>
</div>
<div className="text-right">
<p className="font-bold text-[#1C323E]">${(client.revenue / 1000).toFixed(0)}k</p>
<p className="text-xs text-slate-500">{Math.round(client.fillRate)}%</p>
</div>
</div>
<div className="w-full h-2 bg-slate-100 rounded-full overflow-hidden">
<div
className="h-full bg-[#1C323E] rounded-full transition-all duration-500"
style={{ width: `${client.fillRate}%` }}
/>
</div>
</div>
))}
</div>
) : (
<div className="text-center py-8">
<BarChart3 className="w-10 h-10 mx-auto text-slate-300 mb-2" />
<p className="text-sm text-slate-500">No client data</p>
</div>
)}
</CardContent>
</Card>
</div>
{/* Right Column (1 col) */}
<div className="space-y-6">
{/* Total Revenue Card - NEW DESIGN */}
<Card className="bg-gradient-to-br from-[#0A39DF] via-blue-700 to-[#1C323E] border-0 shadow-xl overflow-hidden">
<CardContent className="p-8 relative">
<div className="absolute top-4 right-4 flex gap-1.5">
<div className="w-2 h-2 bg-white/40 rounded-full"></div>
<div className="w-2 h-2 bg-white/40 rounded-full"></div>
<div className="w-2 h-2 bg-white rounded-full"></div>
</div>
<p className="text-white/80 text-sm mb-4 font-medium">Total Revenue</p>
<p className="text-6xl font-bold text-white mb-2">
${Math.round(totalRevenue / 1000)}k
</p>
<p className="text-white/70 text-sm">All time earnings</p>
</CardContent>
</Card>
{/* Quick Actions - NEW DESIGN */}
<div className="grid grid-cols-2 gap-3">
<Link to={createPageUrl("VendorOrders")}>
<Card className="bg-gradient-to-br from-[#0A39DF] to-blue-600 border-0 shadow-md hover:shadow-lg transition-all cursor-pointer group">
<CardContent className="p-6 text-center">
<div className="w-14 h-14 mx-auto mb-3 bg-white/20 rounded-xl flex items-center justify-center group-hover:scale-110 transition-transform">
<Package className="w-7 h-7 text-white" />
</div>
<p className="text-white font-bold text-base mb-1">All Orders</p>
<p className="text-white/70 text-xs">View & manage</p>
</CardContent>
</Card>
</Link>
<Link to={createPageUrl("StaffDirectory")}>
<Card className="bg-white border-slate-200 shadow-sm hover:shadow-md transition-all cursor-pointer group">
<CardContent className="p-6 text-center">
<div className="w-14 h-14 mx-auto mb-3 bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl flex items-center justify-center group-hover:scale-110 transition-transform">
<Users className="w-7 h-7 text-blue-600" />
</div>
<p className="text-[#1C323E] font-bold text-base mb-1">My Orders</p>
<p className="text-slate-500 text-xs">Manage staff</p>
</CardContent>
</Card>
</Link>
</div>
{/* Today's Metrics */}
<div className="grid grid-cols-2 gap-3">
<Card className="bg-white border-slate-200 shadow-sm">
<CardContent className="p-5">
<div className="flex items-center justify-between mb-3">
<div className="w-10 h-10 bg-blue-50 rounded-lg flex items-center justify-center">
<Calendar className="w-5 h-5 text-blue-600" />
</div>
<ArrowRight className="w-4 h-4 text-slate-300" />
</div>
<p className="text-3xl font-bold text-[#1C323E] mb-1">{todayOrders.length}</p>
<p className="text-sm text-slate-600">Orders Today</p>
</CardContent>
</Card>
<Card className="bg-white border-slate-200 shadow-sm">
<CardContent className="p-5">
<div className="flex items-center justify-between mb-3">
<div className="w-10 h-10 bg-purple-50 rounded-lg flex items-center justify-center">
<Package className="w-5 h-5 text-purple-600" />
</div>
<Badge className="bg-green-100 text-green-700 text-xs font-bold">Active</Badge>
</div>
<p className="text-3xl font-bold text-[#1C323E] mb-1">{activeOrders.length}</p>
<p className="text-sm text-slate-600">In Progress</p>
</CardContent>
</Card>
</div>
{/* Staff Assigned Today */}
<Card className="bg-white border-slate-200 shadow-sm">
<CardContent className="p-5">
<div className="flex items-center justify-between mb-4">
<div className="w-10 h-10 bg-amber-50 rounded-lg flex items-center justify-center">
<Users className="w-5 h-5 text-amber-600" />
</div>
<Badge className="bg-amber-100 text-amber-700 text-xs font-bold">Today</Badge>
</div>
<p className="text-4xl font-bold text-[#1C323E] mb-1">{staffAssignedToday}</p>
<p className="text-sm text-slate-600">Staff Assigned</p>
</CardContent>
</Card>
{/* Top Clients - NEW DESIGN */}
<Card className="bg-white border-slate-200 shadow-sm">
<CardHeader className="pb-3">
<CardTitle className="text-sm flex items-center gap-2">
<Star className="w-4 h-4 text-amber-500" />
Top Clients
</CardTitle>
</CardHeader>
<CardContent className="p-4">
{topClients.slice(0, 3).length > 0 ? (
<div className="space-y-3">
{topClients.slice(0, 3).map((client) => (
<div key={client.name} className="flex items-center justify-between p-3 rounded-lg bg-slate-50 border border-slate-200">
<div>
<p className="font-bold text-sm text-[#1C323E]">{client.name}</p>
<p className="text-xs text-slate-500">+{client.orders}%</p>
</div>
<p className="font-bold text-[#1C323E]">${(client.revenue / 1000).toFixed(0)}k</p>
</div>
))}
</div>
) : (
<div className="text-center py-6">
<Star className="w-8 h-8 mx-auto text-slate-300 mb-2" />
<p className="text-xs text-slate-500">No client data</p>
</div>
)}
</CardContent>
</Card>
{/* Top Performers - NEW DESIGN */}
<Card className="bg-white border-slate-200 shadow-sm">
<CardHeader className="pb-3">
<CardTitle className="text-sm flex items-center gap-2">
<Award className="w-4 h-4 text-blue-500" />
Top Performers
</CardTitle>
</CardHeader>
<CardContent className="p-4">
{topPerformers.length > 0 ? (
<div className="space-y-3">
{topPerformers.map((member) => (
<div key={member.id} className="flex items-center justify-between p-3 rounded-lg bg-slate-50 border border-slate-200">
<div>
<p className="font-bold text-sm text-[#1C323E]">
{member.employee_name} - {member.position || "Staff"}
</p>
<p className="text-xs text-slate-500">{member.shifts} shifts</p>
</div>
<div className="flex items-center gap-1">
<span className="text-sm font-bold text-[#1C323E]">{(member.rating || 0).toFixed(1)}</span>
<Star className="w-3 h-3 text-amber-500 fill-amber-500" />
</div>
</div>
))}
</div>
) : (
<div className="text-center py-6">
<Award className="w-8 h-8 mx-auto text-slate-300 mb-2" />
<p className="text-xs text-slate-500">No staff data</p>
</div>
)}
</CardContent>
</Card>
{/* Gold Vendors - NEW SECTION */}
<Card className="bg-white border-slate-200 shadow-sm">
<CardHeader className="pb-3">
<CardTitle className="text-sm flex items-center gap-2">
<Award className="w-4 h-4 text-amber-500" />
Gold Vendors
</CardTitle>
</CardHeader>
<CardContent className="p-4">
<div className="space-y-3">
<div className="flex items-center justify-between p-3 rounded-lg bg-gradient-to-r from-amber-50 to-yellow-50 border border-amber-200">
<div>
<p className="font-bold text-sm text-[#1C323E]">Legendary Staffing</p>
<p className="text-xs text-slate-500">Score</p>
</div>
<p className="text-2xl font-bold text-amber-600">98</p>
</div>
<div className="flex items-center justify-between p-3 rounded-lg bg-gradient-to-r from-amber-50 to-yellow-50 border border-amber-200">
<div>
<p className="font-bold text-sm text-[#1C323E]">Epic Workforce</p>
<p className="text-xs text-slate-500">Score</p>
</div>
<p className="text-2xl font-bold text-amber-600">96</p>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</div>
);
}