2026-06-03 14:22:56 +05:30

865 lines
53 KiB
JavaScript

import React, { useState, useMemo, useEffect } from 'react';
import { Head, Link, router } from '@inertiajs/react';
import EmployerLayout from '../../../Layouts/EmployerLayout';
import { useTranslation } from '../../../lib/LanguageContext';
import {
Search,
SlidersHorizontal,
CheckCircle2,
MapPin,
Briefcase,
DollarSign,
Calendar,
Bookmark,
RotateCcw,
HeartHandshake,
Globe2,
Sparkles,
Filter,
ArrowUpDown,
Check,
X,
Eye,
ChevronDown,
Layers,
AlertTriangle,
Star,
CheckCircle,
ShieldCheck,
User
} from 'lucide-react';
const getLanguageFlag = (lang) => {
const flags = {
'English': '🇬🇧',
'Arabic': '🇦🇪',
'Tagalog': '🇵🇭',
'Hindi': '🇮🇳',
'Swahili': '🇰🇪',
'French': '🇫🇷',
'Indonesian': '🇮🇩'
};
return flags[lang] || '🌐';
};
export default function Index({ initialWorkers = [], initialShortlistedIds = [], filtersMetadata = {} }) {
const { t } = useTranslation();
// Basic Filters
const [searchQuery, setSearchQuery] = useState('');
const [selectedCategory, setSelectedCategory] = useState('All Categories');
const [selectedNationality, setSelectedNationality] = useState('All Nationalities');
const [selectedExperience, setSelectedExperience] = useState('All Experience');
const [selectedReligion, setSelectedReligion] = useState('All Religions');
const [maxSalary, setMaxSalary] = useState(3000);
// Advanced Multi-Select Filters & Sorting
const [selectedLanguages, setSelectedLanguages] = useState([]);
const [selectedVisaStatuses, setSelectedVisaStatuses] = useState([]);
const [selectedSkills, setSelectedSkills] = useState([]);
const [selectedWorkTypes, setSelectedWorkTypes] = useState([]);
const [sortBy, setSortBy] = useState('default');
// UI Helpers
const [isLangOpen, setIsLangOpen] = useState(false);
const [isVisaOpen, setIsVisaOpen] = useState(false);
const [isSkillsOpen, setIsSkillsOpen] = useState(false);
const [isWorkTypeOpen, setIsWorkTypeOpen] = useState(false);
// Pagination
const [visibleCount, setVisibleCount] = useState(6);
// Shortlist / Favorites
const [shortlistedIds, setShortlistedIds] = useState(initialShortlistedIds || []);
// Saved Presets
const [savedPresets, setSavedPresets] = useState([
{ id: 1, name: 'Live-in Baby Care', category: 'Childcare', workType: 'Live-in', minSalary: 1200 },
{ id: 2, name: 'Experienced Driver', category: 'Driver', experience: '5+ Years' }
]);
const [presetNameInput, setPresetNameInput] = useState('');
const [showPresetModal, setShowPresetModal] = useState(false);
// Worker Comparison & Quick Preview
const [comparisonIds, setComparisonIds] = useState([]);
const [previewWorker, setPreviewWorker] = useState(null);
// Retrieve active preset query if present
useEffect(() => {
const params = new URLSearchParams(window.location.search);
const cat = params.get('category');
const nat = params.get('nationality');
const sal = params.get('max_salary');
if (cat) setSelectedCategory(cat);
if (nat) setSelectedNationality(nat);
if (sal) setMaxSalary(Number(sal));
}, []);
const toggleShortlist = (id) => {
if (shortlistedIds.includes(id)) {
setShortlistedIds(shortlistedIds.filter(i => i !== id));
} else {
setShortlistedIds([...shortlistedIds, id]);
}
router.post('/employer/shortlist/toggle', { worker_id: id }, {
preserveScroll: true,
onSuccess: (page) => {
if (page.props.initialShortlistedIds) {
setShortlistedIds(page.props.initialShortlistedIds);
}
}
});
};
const toggleMultiSelect = (item, selectedList, setSelectedList) => {
if (selectedList.includes(item)) {
setSelectedList(selectedList.filter(x => x !== item));
} else {
setSelectedList([...selectedList, item]);
}
};
const applyPreset = (preset) => {
resetFilters();
if (preset.category) setSelectedCategory(preset.category);
if (preset.workType) setSelectedWorkTypes([preset.workType]);
if (preset.experience) setSelectedExperience(preset.experience);
};
const saveCurrentPreset = (e) => {
e.preventDefault();
if (!presetNameInput.trim()) return;
const newPreset = {
id: Date.now(),
name: presetNameInput,
category: selectedCategory !== 'All Categories' ? selectedCategory : null,
workType: selectedWorkTypes.length > 0 ? selectedWorkTypes[0] : null,
experience: selectedExperience !== 'All Experience' ? selectedExperience : null,
};
setSavedPresets([...savedPresets, newPreset]);
setPresetNameInput('');
setShowPresetModal(false);
};
const resetFilters = () => {
setSearchQuery('');
setSelectedCategory('All Categories');
setSelectedNationality('All Nationalities');
setSelectedExperience('All Experience');
setSelectedReligion('All Religions');
setMaxSalary(3000);
setSelectedLanguages([]);
setSelectedVisaStatuses([]);
setSelectedSkills([]);
setSelectedWorkTypes([]);
setSortBy('default');
setVisibleCount(6);
};
// Filter and Sort Worker List
const filteredWorkers = useMemo(() => {
let workers = initialWorkers.filter(worker => {
// Search Query
if (searchQuery.trim() !== '') {
const query = searchQuery.toLowerCase();
const matchName = worker.name.toLowerCase().includes(query);
const matchBio = worker.bio?.toLowerCase().includes(query) || false;
const matchSkills = worker.skills?.some(s => s.toLowerCase().includes(query)) || false;
if (!matchName && !matchBio && !matchSkills) return false;
}
// Dropdown filters
if (selectedCategory !== 'All Categories' && worker.category !== selectedCategory) return false;
if (selectedNationality !== 'All Nationalities' && worker.nationality !== selectedNationality) return false;
if (selectedExperience !== 'All Experience' && worker.experience !== selectedExperience) return false;
if (selectedReligion !== 'All Religions' && worker.religion !== selectedReligion) return false;
if (worker.salary > maxSalary) return false;
// Multi-select filters
if (selectedLanguages.length > 0) {
const hasLang = worker.languages?.some(l => selectedLanguages.includes(l));
if (!hasLang) return false;
}
if (selectedSkills.length > 0) {
const hasSkill = worker.skills?.some(s => selectedSkills.includes(s.toLowerCase()));
if (!hasSkill) return false;
}
if (selectedVisaStatuses.length > 0) {
if (!selectedVisaStatuses.includes(worker.visa_status)) return false;
}
if (selectedWorkTypes.length > 0 && !selectedWorkTypes.includes(worker.preferred_job_type)) return false;
return true;
});
// Sorting
if (sortBy === 'salary_asc') {
workers.sort((a, b) => a.salary - b.salary);
} else if (sortBy === 'salary_desc') {
workers.sort((a, b) => b.salary - a.salary);
} else if (sortBy === 'rating') {
workers.sort((a, b) => b.rating - a.rating);
} else if (sortBy === 'experience') {
workers.sort((a, b) => b.age - a.age); // approximate experience by age
}
return workers;
}, [
initialWorkers,
searchQuery,
selectedCategory,
selectedNationality,
selectedExperience,
selectedReligion,
maxSalary,
selectedLanguages,
selectedVisaStatuses,
selectedSkills,
selectedWorkTypes,
sortBy
]);
const paginatedWorkers = useMemo(() => {
return filteredWorkers.slice(0, visibleCount);
}, [filteredWorkers, visibleCount]);
const handleToggleComparison = (id) => {
if (comparisonIds.includes(id)) {
setComparisonIds(comparisonIds.filter(i => i !== id));
} else {
if (comparisonIds.length >= 3) {
alert('You can compare a maximum of 3 candidates.');
return;
}
setComparisonIds([...comparisonIds, id]);
}
};
const comparedWorkers = useMemo(() => {
return initialWorkers.filter(w => comparisonIds.includes(w.id));
}, [initialWorkers, comparisonIds]);
return (
<EmployerLayout title={t('find_vetted_workers')}>
<Head title={t('find_workers_platform')} />
<div className="space-y-8 select-none pb-16">
{/* 1. Header Banner */}
<div className="bg-white rounded-3xl p-8 border border-slate-200 shadow-sm relative overflow-hidden flex flex-col md:flex-row md:items-center justify-between gap-6">
<div className="absolute top-0 right-0 w-48 h-48 bg-blue-50 rounded-full -mr-16 -mt-16 opacity-40 pointer-events-none" />
<div className="space-y-2 relative z-10">
<div className="flex items-center space-x-2">
<span className="bg-blue-50 text-[#185FA5] px-3 py-1 rounded-xl text-[10px] font-black uppercase tracking-wider border border-blue-100 flex items-center space-x-1">
<HeartHandshake className="w-3.5 h-3.5" />
<span>{t('no_middlemen_platform')}</span>
</span>
</div>
<h2 className="text-2xl font-black text-slate-900 tracking-tight leading-none">{t('find_verified_candidates')}</h2>
<p className="text-slate-500 font-bold text-xs">{t('connect_vetted_workers_desc')}</p>
</div>
</div>
{/* Filter and Search Panel */}
<div className="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-4">
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-4">
{/* Core Search bar */}
<div className="relative flex-1">
<Search className="absolute left-3.5 top-1/2 -translate-y-1/2 w-5 h-5 text-slate-400" />
<input
type="text"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder={t('search_by_name_skills_bio')}
className="w-full pl-11 pr-4 py-3 rounded-xl border border-slate-300 text-sm focus:outline-none focus:ring-2 focus:ring-[#185FA5]/20 focus:border-[#185FA5]"
/>
</div>
{/* Sort & Reset Actions */}
<div className="flex items-center space-x-3 w-full lg:w-auto justify-end">
{/* Sort Selector */}
<div className="relative flex items-center bg-slate-50 rounded-xl border border-slate-200 px-3 py-2 text-xs font-bold text-slate-700">
<ArrowUpDown className="w-4 h-4 text-slate-400 mr-2" />
<select
value={sortBy}
onChange={(e) => setSortBy(e.target.value)}
className="bg-transparent focus:outline-none cursor-pointer"
>
<option value="default">{t('default_match')}</option>
<option value="salary_asc">{t('salary_low_to_high')}</option>
<option value="salary_desc">{t('salary_high_to_low')}</option>
<option value="rating">{t('rating_high_to_low')}</option>
<option value="experience">{t('experience_level')}</option>
</select>
</div>
<button
type="button"
onClick={resetFilters}
className="flex items-center justify-center space-x-1.5 px-4 py-2.5 rounded-xl border border-slate-200 hover:bg-slate-50 text-xs font-semibold text-slate-600 transition-colors"
>
<RotateCcw className="w-4 h-4 text-slate-400" />
<span>{t('reset')}</span>
</button>
</div>
</div>
{/* Primary filters grid */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 pt-4 border-t border-slate-100">
{/* Nationality */}
<div>
<label className="block text-[10px] font-black text-slate-400 uppercase tracking-widest mb-1.5">{t('nationality')}</label>
<select
value={selectedNationality}
onChange={(e) => setSelectedNationality(e.target.value)}
className="w-full px-3 py-2.5 rounded-xl border border-slate-200 text-xs bg-slate-50/50 focus:bg-white focus:outline-none focus:border-[#185FA5] font-semibold text-slate-700 cursor-pointer"
>
{filtersMetadata.nationalities?.map(nat => (
<option key={nat} value={nat}>{nat}</option>
))}
</select>
</div>
{/* Skills */}
<div className="relative">
<label className="block text-[10px] font-black text-slate-400 uppercase tracking-widest mb-1.5">{t('skills')}</label>
<button
type="button"
onClick={() => {
setIsSkillsOpen(!isSkillsOpen);
setIsLangOpen(false);
setIsVisaOpen(false);
}}
className="w-full px-3 py-2.5 rounded-xl border border-slate-200 text-xs bg-slate-50/50 flex justify-between items-center font-bold text-slate-600"
>
<span className="truncate">
{selectedSkills.length === 0
? t('select_skills')
: `${selectedSkills.length} ${t('selected')}`}
</span>
<ChevronDown className="w-4 h-4 ml-1 flex-shrink-0" />
</button>
{isSkillsOpen && (
<div className="absolute left-0 right-0 mt-1 bg-white border border-slate-200 shadow-lg rounded-xl p-3 z-30 space-y-1.5 max-h-60 overflow-y-auto">
{filtersMetadata.skills?.slice(1).map(skill => (
<label key={skill} className="flex items-center space-x-2 text-xs font-bold text-slate-600 cursor-pointer">
<input
type="checkbox"
checked={selectedSkills.includes(skill.toLowerCase())}
onChange={() => toggleMultiSelect(skill.toLowerCase(), selectedSkills, setSelectedSkills)}
className="rounded text-[#185FA5] focus:ring-[#185FA5]"
/>
<span className="capitalize">{skill}</span>
</label>
))}
</div>
)}
</div>
{/* Language */}
<div className="relative">
<label className="block text-[10px] font-black text-slate-400 uppercase tracking-widest mb-1.5">{t('languages_spoken', 'Language')}</label>
<button
type="button"
onClick={() => {
setIsLangOpen(!isLangOpen);
setIsSkillsOpen(false);
setIsVisaOpen(false);
}}
className="w-full px-3 py-2.5 rounded-xl border border-slate-200 text-xs bg-slate-50/50 flex justify-between items-center font-bold text-slate-600"
>
<span className="truncate">
{selectedLanguages.length === 0
? t('select_languages')
: `${selectedLanguages.length} ${t('selected')}`}
</span>
<ChevronDown className="w-4 h-4 ml-1 flex-shrink-0" />
</button>
{isLangOpen && (
<div className="absolute left-0 right-0 mt-1 bg-white border border-slate-200 shadow-lg rounded-xl p-3 z-30 space-y-1.5">
{filtersMetadata.languages?.slice(1).map(lang => (
<label key={lang} className="flex items-center space-x-2 text-xs font-bold text-slate-600 cursor-pointer">
<input
type="checkbox"
checked={selectedLanguages.includes(lang)}
onChange={() => toggleMultiSelect(lang, selectedLanguages, setSelectedLanguages)}
className="rounded text-[#185FA5] focus:ring-[#185FA5]"
/>
<span>{lang}</span>
</label>
))}
</div>
)}
</div>
{/* Visa Status */}
<div className="relative">
<label className="block text-[10px] font-black text-slate-400 uppercase tracking-widest mb-1.5">{t('visa_status', 'Visa Status')}</label>
<button
type="button"
onClick={() => {
setIsVisaOpen(!isVisaOpen);
setIsSkillsOpen(false);
setIsLangOpen(false);
}}
className="w-full px-3 py-2.5 rounded-xl border border-slate-200 text-xs bg-slate-50/50 flex justify-between items-center font-bold text-slate-600"
>
<span className="truncate">
{selectedVisaStatuses.length === 0
? t('select_visa_status')
: `${selectedVisaStatuses.length} ${t('selected')}`}
</span>
<ChevronDown className="w-4 h-4 ml-1 flex-shrink-0" />
</button>
{isVisaOpen && (
<div className="absolute left-0 right-0 mt-1 bg-white border border-slate-200 shadow-lg rounded-xl p-3 z-30 space-y-1.5">
{filtersMetadata.visaStatuses?.slice(1).map(status => (
<label key={status} className="flex items-center space-x-2 text-xs font-bold text-slate-600 cursor-pointer">
<input
type="checkbox"
checked={selectedVisaStatuses.includes(status)}
onChange={() => toggleMultiSelect(status, selectedVisaStatuses, setSelectedVisaStatuses)}
className="rounded text-[#185FA5] focus:ring-[#185FA5]"
/>
<span>{status}</span>
</label>
))}
</div>
)}
</div>
</div>
</div>
{/* Listing metadata bar */}
<div className="flex items-center justify-between px-1">
<div className="text-xs font-semibold text-slate-500">
{t('found_workers_matching').split('{count}')[0]}
<span className="text-slate-900 font-bold">{filteredWorkers.length}</span>
{t('found_workers_matching').split('{count}')[1]}
</div>
<div className="flex items-center space-x-2 text-xs font-medium text-slate-600">
<CheckCircle className="w-3.5 h-3.5 text-emerald-600" />
<span>{t('direct_sponsoring_active')}</span>
</div>
</div>
{/* Marketplace Workers Grid */}
{paginatedWorkers.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{paginatedWorkers.map((worker) => {
const isShortlisted = shortlistedIds.includes(worker.id);
const isComparing = comparisonIds.includes(worker.id);
return (
<div key={worker.id} className="bg-white rounded-2xl border border-slate-200 shadow-sm hover:shadow-md transition-all flex flex-col justify-between overflow-hidden group relative">
{/* Card Header with Photo Option and Availability indicator */}
<div className="bg-slate-50/50 p-6 border-b border-slate-100 flex items-start justify-between relative">
<div className="flex items-center space-x-3.5">
{/* Photo (optional) container */}
<div className="w-14 h-14 rounded-2xl bg-blue-100 text-[#185FA5] flex items-center justify-center font-bold text-xl border border-blue-200 shadow-inner flex-shrink-0 overflow-hidden relative">
{worker.photo ? (
<img src={worker.photo} alt={worker.name} className="w-full h-full object-cover" />
) : (
<User className="w-6 h-6 text-slate-400" />
)}
</div>
<div className="truncate">
<div className="font-extrabold text-base text-slate-900 group-hover:text-[#185FA5] transition-colors truncate flex items-center space-x-1.5">
<span>{worker.name}</span>
{worker.verified && (
<span className="inline-flex items-center px-1.5 py-0.5 rounded-full text-[8px] font-black uppercase tracking-wider bg-emerald-500 text-white shadow-xs gap-0.5 animate-pulse" title="OCR Verified">
<CheckCircle2 className="w-3 h-3" />
<span>{t('verified')}</span>
</span>
)}
</div>
{/* Passport Status Verification Badge & Visa Status */}
<div className="flex flex-wrap gap-1 mt-0.5">
<div className={`flex items-center space-x-1 text-[9px] font-black uppercase px-1.5 py-0.5 rounded border ${
worker.passport_status.toLowerCase().includes('pending')
? 'text-amber-700 bg-amber-50 border-amber-200'
: 'text-emerald-700 bg-emerald-50 border-emerald-100'
}`}>
<ShieldCheck className={`w-3 h-3 flex-shrink-0 ${
worker.passport_status.toLowerCase().includes('pending')
? 'text-amber-600'
: 'text-emerald-600'
}`} />
<span>{worker.passport_status}</span>
</div>
{worker.visa_status && (worker.visa_status.toLowerCase().includes('tourist') || worker.visa_status.toLowerCase().includes('visit')) ? (
<div className="flex items-center space-x-1 text-[9px] font-black uppercase text-amber-700 bg-amber-50 px-1.5 py-0.5 rounded border border-amber-200">
<AlertTriangle className="w-3 h-3 text-amber-600 flex-shrink-0 animate-bounce" />
<span>{worker.visa_status} ({t('warning', 'Warning')})</span>
</div>
) : worker.visa_status && worker.visa_status.toLowerCase().includes('cancelled') ? (
<div className="flex items-center space-x-1 text-[9px] font-black uppercase text-rose-700 bg-rose-50 px-1.5 py-0.5 rounded border border-rose-200 animate-pulse">
<AlertTriangle className="w-3 h-3 text-rose-600 flex-shrink-0" />
<span>{worker.visa_status} ({t('warning', 'Warning')})</span>
</div>
) : (
<div className="flex items-center space-x-1 text-[9px] font-black uppercase text-blue-700 bg-blue-50 px-1.5 py-0.5 rounded border border-blue-100">
<span>{worker.visa_status}</span>
</div>
)}
</div>
<div className="flex items-center space-x-1.5 text-xs text-slate-500 mt-1">
<Globe2 className="w-3.5 h-3.5 text-slate-400" />
<span className="font-bold">{worker.nationality}</span>
<span></span>
<span>{worker.age} {t('yrs', 'yrs')}</span>
</div>
</div>
</div>
{/* Top Right Availability status and bookmark */}
<div className="flex flex-col items-end space-y-2">
<button
type="button"
onClick={() => toggleShortlist(worker.id)}
className={`p-2 rounded-xl transition-all ${
isShortlisted
? 'bg-blue-50 text-[#185FA5] hover:bg-blue-100'
: 'bg-white text-slate-400 hover:text-[#185FA5] border border-slate-200'
}`}
>
<Bookmark className={`w-3.5 h-3.5 ${isShortlisted ? 'fill-[#185FA5]' : ''}`} />
</button>
</div>
</div>
{/* Card Body */}
<div className="p-6 space-y-4 flex-1 flex flex-col justify-between">
<div className="space-y-4">
{/* Category Pill, Ratings & Cost */}
<div className="flex items-center justify-between text-xs">
<span className="px-2.5 py-1 bg-blue-50 text-[#185FA5] font-black rounded-lg border border-blue-100 uppercase tracking-wider text-[9px]">
{worker.category}
</span>
<div className="flex items-center space-x-1 font-bold text-slate-800">
<DollarSign className="w-3.5 h-3.5 text-emerald-600" />
<span className="text-sm font-black">{worker.salary} {t('aed', 'AED')}</span>
<span className="text-[10px] text-slate-400 font-medium">/{t('mo', 'mo')}</span>
</div>
</div>
{/* Details Table */}
<div className="grid grid-cols-2 gap-2.5 p-3.5 bg-slate-50 rounded-xl text-[11px] text-slate-600 font-bold">
<div className="flex items-center space-x-1.5 truncate">
<Briefcase className="w-3.5 h-3.5 text-slate-400 flex-shrink-0" />
<span className="truncate">{t('experience', 'Exp')}: {worker.experience}</span>
</div>
<div className="flex items-center space-x-1.5 truncate">
<Sparkles className="w-3.5 h-3.5 text-slate-400 flex-shrink-0" />
<span className="truncate uppercase text-[10px]">{worker.preferred_job_type}</span>
</div>
<div className="flex items-center space-x-1.5 truncate col-span-2">
<Star className="w-3.5 h-3.5 text-amber-500 flex-shrink-0 fill-amber-500" />
<span className="truncate">{worker.rating} ({worker.reviews_count} {t('reviews', 'reviews')})</span>
</div>
</div>
{/* Core exact platform Skills List */}
<div className="space-y-1">
<div className="text-[9px] font-black text-slate-400 uppercase tracking-widest">{t('platform_skills', 'Platform Skills')}</div>
<div className="flex flex-wrap gap-1">
{worker.skills?.map(skill => (
<span key={skill} className="px-2.5 py-0.5 bg-blue-50 border border-blue-100 text-[#185FA5] text-[9px] font-black rounded-lg uppercase tracking-wider">
{skill}
</span>
))}
</div>
</div>
{/* Languages Badges with Visual Flags */}
<div className="space-y-1">
<div className="text-[9px] font-black text-slate-400 uppercase tracking-widest">{t('languages_spoken', 'Languages Spoken')}</div>
<div className="flex flex-wrap gap-1.5">
{worker.languages?.map(lang => (
<span key={lang} className="text-[9px] bg-slate-100 text-slate-700 px-2 py-0.5 rounded font-bold uppercase flex items-center space-x-1 border border-slate-200">
<span>{getLanguageFlag(lang)}</span>
<span>{lang}</span>
</span>
))}
</div>
</div>
</div>
{/* Actions block */}
<div className="pt-4 border-t border-slate-100 space-y-2">
<div className="grid grid-cols-2 gap-2">
<button
type="button"
onClick={() => setPreviewWorker(worker)}
className="w-full bg-slate-50 border border-slate-200 hover:bg-slate-100 text-slate-700 rounded-xl h-10 font-bold text-xs flex items-center justify-center transition-colors space-x-1"
>
<Eye className="w-3.5 h-3.5" />
<span>{t('quick_preview')}</span>
</button>
<button
type="button"
onClick={() => handleToggleComparison(worker.id)}
className={`w-full rounded-xl h-10 font-bold text-xs flex items-center justify-center transition-colors border ${
isComparing
? 'bg-purple-600 border-purple-600 text-white hover:bg-purple-700'
: 'bg-white border-slate-200 hover:bg-slate-50 text-slate-700'
}`}
>
{isComparing ? t('comparing', 'Comparing ✓') : t('compare_candidate', 'Compare Candidate')}
</button>
</div>
<Link
href={`/employer/workers/${worker.id}`}
className="w-full bg-[#185FA5] hover:bg-[#144f8a] text-white rounded-xl h-10 font-bold text-xs flex items-center justify-center transition-colors shadow-xs"
>
{t('open_full_profile')}
</Link>
</div>
</div>
</div>
);
})}
</div>
) : (
<div className="text-center py-20 bg-white rounded-2xl border border-slate-200 shadow-sm space-y-4">
<SlidersHorizontal className="w-14 h-14 text-slate-300 mx-auto" />
<h4 className="text-base font-bold text-slate-800">{t('no_candidates_matching')}</h4>
<p className="text-xs text-slate-500 max-w-sm mx-auto leading-relaxed">
{t('adjust_filters_desc')}
</p>
<button
type="button"
onClick={resetFilters}
className="bg-[#185FA5] text-white px-5 py-2.5 rounded-xl text-xs font-bold hover:bg-[#144f8a] transition-all shadow-sm"
>
{t('reset_filters')}
</button>
</div>
)}
{/* Load More Pagination */}
{filteredWorkers.length > visibleCount && (
<div className="text-center pt-6">
<button
onClick={() => setVisibleCount(visibleCount + 6)}
className="bg-white border border-slate-200 hover:bg-slate-50 text-[#185FA5] px-8 py-3 rounded-xl text-xs font-bold transition-all shadow-xs"
>
{t('load_more_workers')}
</button>
</div>
)}
{/* 5. Worker Comparison Drawer (Col 12 Fixed bottom) */}
{comparisonIds.length > 0 && (
<div className="fixed bottom-0 left-0 right-0 bg-white border-t-2 border-[#185FA5] shadow-2xl p-6 z-50 animate-slide-up flex flex-col space-y-4 max-w-7xl mx-auto rounded-t-3xl">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<span className="w-2.5 h-2.5 rounded-full bg-[#185FA5] animate-ping" />
<h4 className="font-extrabold text-sm text-slate-900">
{t('comparing_workers_count').replace('{count}', comparedWorkers.length)}
</h4>
</div>
<button
onClick={() => setComparisonIds([])}
className="text-xs font-bold text-rose-600 hover:underline flex items-center space-x-1"
>
<X className="w-4 h-4" />
<span>{t('clear_all', 'Clear all')}</span>
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{comparedWorkers.map(w => (
<div key={w.id} className="bg-slate-50 border border-slate-200 rounded-2xl p-4 space-y-3 relative">
<button
onClick={() => handleToggleComparison(w.id)}
className="absolute top-2 right-2 text-slate-400 hover:text-slate-600"
>
<X className="w-4 h-4" />
</button>
<div className="flex items-center space-x-2">
<div className="w-8 h-8 rounded-full bg-blue-100 text-[#185FA5] font-black text-xs flex items-center justify-center overflow-hidden">
{w.photo ? (
<img src={w.photo} alt={w.name} className="w-full h-full object-cover" />
) : (
<span>{w.name.charAt(0)}</span>
)}
</div>
<div>
<div className="font-bold text-xs text-slate-900 truncate max-w-[120px]">{w.name}</div>
<div className="text-[10px] text-slate-500 font-bold">{w.nationality} {w.category}</div>
</div>
</div>
<div className="grid grid-cols-2 gap-2 text-[10px] bg-white p-2.5 rounded-xl border border-slate-100 font-bold text-slate-600">
<div>{t('salary', 'Salary')}: <span className="text-slate-800">{w.salary} {t('aed', 'AED')}</span></div>
<div>{t('age', 'Age')}: <span className="text-slate-800">{w.age} {t('yrs', 'yrs')}</span></div>
<div>{t('job_type', 'Job Type')}: <span className="text-slate-800 uppercase">{w.preferred_job_type}</span></div>
<div>{t('status', 'Status')}: <span className="text-slate-800 font-black">{w.availability_status}</span></div>
</div>
<div className="space-y-1">
<div className="text-[8px] font-black text-slate-400 uppercase tracking-wider">{t('skills')}</div>
<div className="flex flex-wrap gap-1">
{w.skills?.map(skill => (
<span key={skill} className="px-1.5 py-0.5 bg-blue-50 border border-blue-100 text-[#185FA5] text-[8px] font-black rounded uppercase tracking-wider">
{skill}
</span>
))}
</div>
</div>
</div>
))}
</div>
</div>
)}
{/* 6. Quick Preview Modal overlay */}
{previewWorker && (
<div className="fixed inset-0 bg-slate-900/60 backdrop-blur-xs flex items-center justify-center p-4 z-50 animate-fade-in">
<div className="bg-white rounded-3xl w-full max-w-lg border border-slate-200 shadow-2xl p-6 relative animate-zoom-in space-y-6">
<button
onClick={() => setPreviewWorker(null)}
className="absolute top-4 right-4 p-2 bg-slate-50 hover:bg-slate-100 rounded-full text-slate-400 hover:text-slate-600 transition-colors"
>
<X className="w-5 h-5" />
</button>
<div className="flex items-center space-x-4">
<div className="w-16 h-16 bg-blue-50 text-[#185FA5] rounded-2xl border border-blue-100 font-black text-2xl flex items-center justify-center shadow-inner overflow-hidden flex-shrink-0">
{previewWorker.photo ? (
<img src={previewWorker.photo} alt={previewWorker.name} className="w-full h-full object-cover" />
) : (
<User className="w-8 h-8 text-slate-400" />
)}
</div>
<div>
<div className="flex items-center space-x-1">
<h4 className="font-extrabold text-lg text-slate-900">{previewWorker.name}</h4>
{previewWorker.verified && <CheckCircle2 className="w-4 h-4 text-emerald-600" />}
</div>
<div className={`flex items-center space-x-1 font-black text-[9px] uppercase tracking-wider ${
previewWorker.passport_status?.toLowerCase().includes('pending')
? 'text-amber-700 bg-amber-50 border border-amber-200 px-1.5 py-0.5 rounded'
: 'text-emerald-700 bg-emerald-50 border border-emerald-100 px-1.5 py-0.5 rounded'
}`}>
<ShieldCheck className={`w-3.5 h-3.5 flex-shrink-0 ${
previewWorker.passport_status?.toLowerCase().includes('pending')
? 'text-amber-600'
: 'text-emerald-600'
}`} />
<span>{previewWorker.passport_status}</span>
</div>
<div className="text-xs text-slate-500 font-bold">{previewWorker.nationality} {previewWorker.category}</div>
</div>
</div>
<p className="text-xs text-slate-600 italic bg-slate-50 p-4 rounded-xl leading-relaxed">
"{previewWorker.bio}"
</p>
<div className="grid grid-cols-2 gap-4 text-xs font-bold text-slate-600">
<div className="p-3 bg-slate-50/50 rounded-xl">
<div className="text-[10px] text-slate-400 uppercase tracking-widest mb-0.5">{t('expectations', 'Expectations')}</div>
<div className="text-slate-800">{previewWorker.salary} {t('aed', 'AED')} / {t('mo', 'mo')}</div>
</div>
<div className="p-3 bg-slate-50/50 rounded-xl">
<div className="text-[10px] text-slate-400 uppercase tracking-widest mb-0.5">{t('job_preference', 'Job Preference')}</div>
<div className="text-slate-800 uppercase text-[10px] mt-1">{previewWorker.preferred_job_type}</div>
</div>
<div className="p-3 bg-slate-50/50 rounded-xl col-span-2">
<div className="text-[10px] text-slate-400 uppercase tracking-widest mb-0.5">{t('languages_spoken', 'Languages')}</div>
<div className="flex flex-wrap gap-1.5 mt-1">
{previewWorker.languages?.map(lang => (
<span key={lang} className="text-[9px] bg-white border border-slate-200 text-slate-700 px-2 py-0.5 rounded font-bold flex items-center space-x-1">
<span>{getLanguageFlag(lang)}</span>
<span>{lang}</span>
</span>
))}
</div>
</div>
</div>
{/* Core Platform Skills inside Quick Preview */}
<div className="space-y-1 pt-1">
<div className="text-[9px] font-black text-slate-400 uppercase tracking-widest">{t('platform_skills', 'Platform Skills')}</div>
<div className="flex flex-wrap gap-1">
{previewWorker.skills?.map(skill => (
<span key={skill} className="px-2.5 py-0.5 bg-blue-50 border border-blue-100 text-[#185FA5] text-[9px] font-black rounded-lg uppercase tracking-wider">
{skill}
</span>
))}
</div>
</div>
<div className="flex items-center space-x-3 pt-2">
<button
onClick={() => toggleShortlist(previewWorker.id)}
className="flex-1 border border-slate-200 hover:bg-slate-50 rounded-xl h-11 text-xs font-bold text-slate-700 flex items-center justify-center space-x-2"
>
<Bookmark className="w-4 h-4" />
<span>{shortlistedIds.includes(previewWorker.id) ? t('shortlisted', 'Shortlisted ✓') : t('add_to_shortlist', 'Add to Shortlist')}</span>
</button>
<Link
href={`/employer/workers/${previewWorker.id}`}
className="flex-1 bg-[#185FA5] hover:bg-[#144f8a] text-white rounded-xl h-11 text-xs font-black flex items-center justify-center shadow-xs"
>
{t('view_full_details', 'View Full Details')}
</Link>
</div>
</div>
</div>
)}
{/* Preset Modal */}
{showPresetModal && (
<div className="fixed inset-0 bg-slate-900/60 backdrop-blur-xs flex items-center justify-center p-4 z-50">
<form onSubmit={saveCurrentPreset} className="bg-white rounded-3xl w-full max-w-sm p-6 relative animate-zoom-in space-y-4 border border-slate-200 shadow-2xl">
<h4 className="font-extrabold text-sm text-slate-900">Name this search preset</h4>
<input
type="text"
placeholder="e.g. Filipino Nannies, Drivers..."
value={presetNameInput}
onChange={(e) => setPresetNameInput(e.target.value)}
className="w-full p-2.5 border border-slate-300 rounded-xl text-xs focus:outline-none focus:border-[#185FA5]"
required
/>
<div className="flex justify-end space-x-2 pt-2 text-xs font-bold">
<button
type="button"
onClick={() => setShowPresetModal(false)}
className="px-4 py-2 border border-slate-200 hover:bg-slate-50 rounded-lg"
>
{t('cancel', 'Cancel')}
</button>
<button
type="submit"
className="px-4 py-2 bg-[#185FA5] text-white hover:bg-[#144f8a] rounded-lg"
>
Save Filter Preset
</button>
</div>
</form>
</div>
)}
</div>
</EmployerLayout>
);
}