import React, { useState } from 'react'; import { Head, Link, router } from '@inertiajs/react'; import AdminLayout from '@/Layouts/AdminLayout'; import { Users, ShieldCheck, CreditCard, BadgeDollarSign, CheckCircle, ArrowRight, ArrowUpRight, MessageSquare, TrendingUp, Percent, PieChart, Sparkles } from 'lucide-react'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; export default function Dashboard({ stats, recent_verifications, recent_subscriptions }) { const [activeTrendTab, setActiveTrendTab] = useState('All'); const [selectedSlice, setSelectedSlice] = useState(null); // Dynamic trend monthly data for custom SVG Line chart const trendData = stats?.trend_data || [ { month: 'Dec', basic: 0, premium: 0, vip: 0 }, { month: 'Jan', basic: 0, premium: 0, vip: 0 }, { month: 'Feb', basic: 0, premium: 0, vip: 0 }, { month: 'Mar', basic: 0, premium: 0, vip: 0 }, { month: 'Apr', basic: 0, premium: 0, vip: 0 }, { month: 'May', basic: 0, premium: 0, vip: 0 } ]; const maxVal = Math.max( 10, ...trendData.map(d => Math.max(d.basic || 0, d.premium || 0, d.vip || 0)) ); // Compute lines points for SVG Spline const getCoordinatesForLine = (key, height, width, max) => { const points = []; const paddingLeft = 35; const paddingRight = 15; const paddingTop = 20; const paddingBottom = 25; const graphHeight = height - paddingTop - paddingBottom; const graphWidth = width - paddingLeft - paddingRight; trendData.forEach((d, idx) => { const val = d[key] || 0; const x = paddingLeft + (idx / (trendData.length - 1)) * graphWidth; const y = paddingTop + graphHeight - (val / max) * graphHeight; points.push(`${x},${y}`); }); return points.join(' '); }; return ( {/* Welcome banner */}
System Status: Online

Welcome back, Administrator

UAE domestic workers platform is operating optimally. {stats?.verifications_today || 0} automated verifications completed today.

Full Analytics Hub
{/* Stat Cards Row */}
{/* Total Workers & active/inactive */}
Workers Registered

{stats?.total_workers?.toLocaleString() || 0}

{stats?.active_workers || 0} Active {stats?.inactive_workers || 0} Inactive
{/* Verification Stats */}
Verification & OCR Rate

{stats?.verification_rate || 0}%

{stats?.verified_workers_count?.toLocaleString() || 0} Profiles Auto-OCR Verified

{/* Chat-To-Hire and Hiring Conversion */}
Hiring Conversion

{stats?.hiring_conversion_rate || 0}%

{stats?.chat_to_hire_rate || 0}% Chat-to-Hire
{/* Subscription Revenue */}
Monthly Subscription Revenue

AED {stats?.revenue_this_month_aed?.toLocaleString() || 0}

+{stats?.new_employers_this_week || 0} Employers Added This Week

{/* Required Analytics and Graphical reports */}
{/* 1. Subscription Trends Spline Chart */}

Subscription Sign-ups Trend

Growth curves across basic, premium & VIP plans

{/* Selector Tabs */}
{['All', 'Premium', 'VIP'].map((tab) => ( ))}
{/* Custom SVG Line Chart */}
{/* Grid Lines */} {/* Line 1: Basic */} {(activeTrendTab === 'All') && ( )} {/* Line 2: Premium */} {(activeTrendTab === 'All' || activeTrendTab === 'Premium') && ( )} {/* Line 3: VIP */} {(activeTrendTab === 'All' || activeTrendTab === 'VIP') && ( )} {/* X-Axis Labels */} {trendData.map((d, i) => { const x = 35 + (i / 5) * 385; return ( {d.month} ); })} {/* Y-Axis Labels */} {maxVal} {Math.round(maxVal / 2)} {Math.round(maxVal / 4)} 0 {/* Custom Legend */}
Basic Search ({trendData[trendData.length - 1]?.basic || 0})
Premium Pass ({trendData[trendData.length - 1]?.premium || 0})
VIP Concierge ({trendData[trendData.length - 1]?.vip || 0})
{/* 2. Worker Availability Report Donut Chart */}

Worker Availability Status Reports

Real-time availability of candidates pool

{(() => { const activeVal = stats?.worker_availability?.['Active'] || 0; const hiddenVal = stats?.worker_availability?.['Hidden'] || 0; const hiredVal = stats?.worker_availability?.['Hired'] || 0; const totalVal = activeVal + hiddenVal + hiredVal; const activePct = totalVal > 0 ? Math.round((activeVal / totalVal) * 100) : 0; const hiddenPct = totalVal > 0 ? Math.round((hiddenVal / totalVal) * 100) : 0; const hiredPct = totalVal > 0 ? Math.round((hiredVal / totalVal) * 100) : 0; return (
{/* Custom Donut Chart */}
{totalVal > 0 ? ( {/* Segment 1: Active */} setSelectedSlice('Active')} onMouseLeave={() => setSelectedSlice(null)} className="cursor-pointer transition-all duration-300 hover:stroke-[14]" /> {/* Segment 2: Hidden */} setSelectedSlice('Hidden')} onMouseLeave={() => setSelectedSlice(null)} className="cursor-pointer transition-all duration-300 hover:stroke-[14]" /> {/* Segment 3: Hired */} setSelectedSlice('Hired')} onMouseLeave={() => setSelectedSlice(null)} className="cursor-pointer transition-all duration-300 hover:stroke-[14]" /> ) : ( /* Empty State Grey Circle */ )} {/* Inner Text */} {selectedSlice || 'TOTAL'} {selectedSlice === 'Active' ? `${activeVal} Workers` : selectedSlice === 'Hidden' ? `${hiddenVal} Workers` : selectedSlice === 'Hired' ? `${hiredVal} Workers` : `${totalVal} Total`}
{/* Interactive legends */}
Active
{activeVal} ({activePct}%)
Hidden
{hiddenVal} ({hiddenPct}%)
Hired
{hiredVal} ({hiredPct}%)
); })()}
{/* 3. Hiring Funnel & Chat-To-Hire Conversion */}

Hiring Conversion & Chat-to-Hire funnel

Platform-wide worker placement workflow stats

{(() => { const funnelData = stats?.funnel || { profiles_browsed: 0, chats_initiated: 0, candidates_shortlisted: 0, workers_hired: 0 }; const browsed = funnelData.profiles_browsed || 0; const chats = funnelData.chats_initiated || 0; const shortlisted = funnelData.candidates_shortlisted || 0; const hired = funnelData.workers_hired || 0; const funnelSteps = [ { stage: 'Profiles Browsed', val: browsed.toLocaleString(), pct: '100%', bg: 'bg-slate-100 border-slate-200 text-slate-600' }, { stage: 'Chats Initiated', val: chats.toLocaleString(), pct: browsed > 0 ? `${((chats / browsed) * 100).toFixed(1)}%` : '0%', bg: 'bg-teal-50 border-teal-100 text-teal-700' }, { stage: 'Candidates Shortlisted', val: shortlisted.toLocaleString(), pct: browsed > 0 ? `${((shortlisted / browsed) * 100).toFixed(1)}%` : '0%', bg: 'bg-blue-50 border-blue-100 text-blue-700' }, { stage: 'Workers Hired', val: hired.toLocaleString(), pct: browsed > 0 ? `${((hired / browsed) * 100).toFixed(1)}%` : '0%', bg: 'bg-emerald-50 border-emerald-100 text-emerald-700' } ]; return funnelSteps.map((step, i) => (
{i < 3 && (
)}
Step 0{i+1}

{step.stage}

{step.val}
Ratio: {step.pct}
)); })()}
); }