254 lines
16 KiB
JavaScript
254 lines
16 KiB
JavaScript
import React, { useState } from 'react';
|
|
import { Head, Link } from '@inertiajs/react';
|
|
import EmployerLayout from '../../Layouts/EmployerLayout';
|
|
import {
|
|
CheckCircle2,
|
|
Globe2,
|
|
Briefcase,
|
|
DollarSign,
|
|
MessageSquare,
|
|
UserCheck,
|
|
Search,
|
|
FileText,
|
|
Download,
|
|
Printer,
|
|
Copy,
|
|
FileSpreadsheet,
|
|
FileJson,
|
|
Filter,
|
|
ChevronRight,
|
|
MoreHorizontal,
|
|
Users,
|
|
Send
|
|
} from 'lucide-react';
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger
|
|
} from '@/components/ui/dropdown-menu';
|
|
|
|
export default function SelectedCandidates({ selectedWorkers }) {
|
|
const [workers, setWorkers] = useState((selectedWorkers || []).filter(w => w.status !== 'Searching'));
|
|
const [searchTerm, setSearchTerm] = useState('');
|
|
|
|
const stats = [
|
|
{
|
|
label: 'Total Candidates',
|
|
count: workers.length,
|
|
icon: Users,
|
|
color: 'text-slate-600',
|
|
bg: 'bg-slate-50'
|
|
},
|
|
{
|
|
label: 'Reviewing',
|
|
count: workers.filter(w => w.status === 'Reviewing' || !w.status).length,
|
|
icon: Search,
|
|
color: 'text-amber-600',
|
|
bg: 'bg-amber-50'
|
|
},
|
|
{
|
|
label: 'Offer Sent',
|
|
count: workers.filter(w => w.status === 'Offer Sent').length,
|
|
icon: Send,
|
|
color: 'text-blue-600',
|
|
bg: 'bg-blue-50'
|
|
},
|
|
{
|
|
label: 'Hired',
|
|
count: workers.filter(w => w.status === 'Hired').length,
|
|
icon: CheckCircle2,
|
|
color: 'text-emerald-600',
|
|
bg: 'bg-emerald-50'
|
|
},
|
|
{
|
|
label: 'Rejected',
|
|
count: workers.filter(w => w.status === 'Rejected').length,
|
|
icon: UserCheck,
|
|
color: 'text-rose-600',
|
|
bg: 'bg-rose-50'
|
|
},
|
|
];
|
|
|
|
return (
|
|
<EmployerLayout>
|
|
<Head title="Candidates - Employer Portal" />
|
|
|
|
<div className="space-y-8 select-none">
|
|
{/* Header Section */}
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-2xl font-black text-slate-900 tracking-tight">Candidates</h1>
|
|
<p className="text-xs font-medium text-slate-500 mt-1">Manage your workforce recruitment pipeline</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Stats Grid */}
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
{stats.map((stat) => (
|
|
<div key={stat.label} className="bg-white p-5 rounded-2xl border border-slate-100 shadow-sm flex items-center space-x-4">
|
|
<div className={`p-3 rounded-xl ${stat.bg}`}>
|
|
<stat.icon className={`w-6 h-6 ${stat.color}`} />
|
|
</div>
|
|
<div>
|
|
<div className="text-2xl font-black text-slate-900 leading-none">{stat.count}</div>
|
|
<div className="text-[10px] font-black text-slate-400 uppercase tracking-widest mt-1">{stat.label}</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Table Section */}
|
|
<div className="bg-white rounded-3xl border border-slate-200 shadow-sm overflow-hidden">
|
|
<div className="p-6 border-b border-slate-100 bg-slate-50/50 flex items-center justify-between">
|
|
<div className="relative w-72">
|
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400" />
|
|
<input
|
|
type="text"
|
|
placeholder="Search by name..."
|
|
className="w-full pl-10 pr-4 py-2 bg-white border border-slate-200 rounded-xl text-sm focus:ring-2 focus:ring-blue-100 focus:border-[#185FA5] transition-all outline-none"
|
|
value={searchTerm}
|
|
onChange={(e) => setSearchTerm(e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex items-center space-x-4">
|
|
<div className="flex items-center bg-white border border-slate-200 rounded-xl p-1">
|
|
{['COPY', 'CSV', 'PDF', 'PRINT'].map(action => (
|
|
<button key={action} className="px-3 py-1.5 text-[10px] font-bold text-slate-500 hover:text-[#185FA5] hover:bg-blue-50 rounded-lg transition-all">
|
|
{action}
|
|
</button>
|
|
))}
|
|
</div>
|
|
<button className="p-2.5 bg-white border border-slate-200 text-slate-400 hover:text-[#185FA5] rounded-xl transition-all shadow-sm">
|
|
<Filter className="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full text-left">
|
|
<thead>
|
|
<tr className="border-b border-slate-100">
|
|
<th className="px-6 py-4 text-[10px] font-black text-slate-400 uppercase tracking-widest">Candidate</th>
|
|
<th className="px-6 py-4 text-[10px] font-black text-slate-400 uppercase tracking-widest">Selected</th>
|
|
<th className="px-6 py-4 text-[10px] font-black text-slate-400 uppercase tracking-widest">Category</th>
|
|
<th className="px-6 py-4 text-[10px] font-black text-slate-400 uppercase tracking-widest">Salary</th>
|
|
<th className="px-6 py-4 text-[10px] font-black text-slate-400 uppercase tracking-widest">Status</th>
|
|
<th className="px-6 py-4 text-[10px] font-black text-slate-400 uppercase tracking-widest text-right">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-slate-50">
|
|
{workers.length > 0 ? (
|
|
workers.filter(w => w.name.toLowerCase().includes(searchTerm.toLowerCase())).map((worker) => (
|
|
<tr key={worker.id} className="group hover:bg-slate-50/50 transition-colors">
|
|
<td className="px-6 py-5">
|
|
<div className="flex items-center space-x-3">
|
|
<div className="w-10 h-10 rounded-full bg-blue-100 text-[#185FA5] flex items-center justify-center font-bold text-sm">
|
|
{worker.name.charAt(0)}
|
|
</div>
|
|
<div>
|
|
<div className="text-sm font-bold text-slate-900">{worker.name}</div>
|
|
<div className="text-[10px] text-slate-400 font-medium">{worker.nationality}</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td className="px-6 py-5 text-[11px] font-bold text-slate-500">Nov 14, 2026</td>
|
|
<td className="px-6 py-5">
|
|
<span className="px-2 py-1 bg-slate-100 text-slate-600 text-[10px] font-bold rounded-lg">{worker.category}</span>
|
|
</td>
|
|
<td className="px-6 py-5">
|
|
<span className="text-sm font-bold text-slate-800">{worker.salary} <span className="text-[10px] text-slate-400">AED</span></span>
|
|
</td>
|
|
<td className="px-6 py-5">
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<button className={`inline-flex items-center px-2.5 py-1 rounded-full text-[10px] font-black tracking-tight hover:ring-2 hover:ring-offset-1 transition-all ${
|
|
worker.status === 'Hired' ? 'bg-emerald-50 text-emerald-700 hover:ring-emerald-200' :
|
|
worker.status === 'Rejected' ? 'bg-rose-50 text-rose-700 hover:ring-rose-200' :
|
|
worker.status === 'Offer Sent' ? 'bg-blue-50 text-blue-700 hover:ring-blue-200' :
|
|
'bg-amber-50 text-amber-700 hover:ring-amber-200'
|
|
}`}>
|
|
<span className={`w-1 h-1 rounded-full mr-1.5 ${
|
|
worker.status === 'Hired' ? 'bg-emerald-500' :
|
|
worker.status === 'Rejected' ? 'bg-rose-500' :
|
|
worker.status === 'Offer Sent' ? 'bg-blue-500' :
|
|
'bg-amber-500'
|
|
}`} />
|
|
{(worker.status || 'Reviewing').toUpperCase()}
|
|
<ChevronRight className="w-3 h-3 ml-1 rotate-90 opacity-50" />
|
|
</button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="start" className="w-44 p-2 rounded-xl">
|
|
<DropdownMenuLabel className="text-[10px] font-black text-slate-400 uppercase tracking-widest px-2 py-1.5">Change Status</DropdownMenuLabel>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem className="text-xs font-bold text-slate-600 focus:text-amber-700 focus:bg-amber-50 rounded-lg">
|
|
Reviewing
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem className="text-xs font-bold text-slate-600 focus:text-blue-700 focus:bg-blue-50 rounded-lg">
|
|
Offer Sent
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem className="text-xs font-bold text-slate-600 focus:text-emerald-700 focus:bg-emerald-50 rounded-lg">
|
|
Hired
|
|
</DropdownMenuItem>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem className="text-xs font-bold text-rose-600 focus:text-rose-700 focus:bg-rose-50 rounded-lg">
|
|
Rejected
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</td>
|
|
<td className="px-6 py-5 text-right">
|
|
<div className="flex items-center justify-end space-x-1">
|
|
<Link
|
|
href={`/employer/messages/${worker.id}`}
|
|
className="p-2 bg-blue-50 text-[#185FA5] hover:bg-[#185FA5] hover:text-white rounded-lg transition-all"
|
|
>
|
|
<MessageSquare className="w-3.5 h-3.5" />
|
|
</Link>
|
|
<Link
|
|
href={`/employer/workers/${worker.id}`}
|
|
className="p-2 bg-slate-50 text-slate-400 hover:text-slate-900 rounded-lg transition-all"
|
|
>
|
|
<MoreHorizontal className="w-3.5 h-3.5" />
|
|
</Link>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
))
|
|
) : (
|
|
<tr>
|
|
<td colSpan="7" className="p-20 text-center">
|
|
<div className="space-y-3">
|
|
<UserCheck className="w-12 h-12 text-slate-200 mx-auto" />
|
|
<div className="text-base font-bold text-slate-400">No candidates found</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{/* Pagination Footer */}
|
|
<div className="px-6 py-4 bg-slate-50/50 border-t border-slate-100 flex items-center justify-between">
|
|
<div className="text-[10px] font-bold text-slate-500 uppercase tracking-widest">
|
|
Showing 1 to {workers.length} of {workers.length} candidates
|
|
</div>
|
|
<div className="flex items-center space-x-2">
|
|
<button className="px-3 py-1.5 bg-white border border-slate-200 text-slate-400 rounded-lg text-[10px] font-black cursor-not-allowed">PREV</button>
|
|
<div className="flex items-center space-x-1">
|
|
<button className="w-8 h-8 flex items-center justify-center bg-[#185FA5] text-white rounded-lg text-[10px] font-black">1</button>
|
|
<button className="w-8 h-8 flex items-center justify-center bg-white border border-slate-200 text-slate-600 hover:border-[#185FA5] rounded-lg text-[10px] font-black transition-colors">2</button>
|
|
</div>
|
|
<button className="px-3 py-1.5 bg-white border border-slate-200 text-[#185FA5] hover:bg-blue-50 rounded-lg text-[10px] font-black transition-colors">NEXT</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</EmployerLayout>
|
|
);
|
|
}
|