320 lines
18 KiB
JavaScript
320 lines
18 KiB
JavaScript
import React, { useState } from 'react';
|
|
import { Head, Link } from '@inertiajs/react';
|
|
import EmployerMobileLayout from './Layouts/EmployerMobileLayout';
|
|
import {
|
|
Search,
|
|
Filter,
|
|
Globe,
|
|
Briefcase,
|
|
DollarSign,
|
|
Star,
|
|
Heart,
|
|
MapPin,
|
|
ArrowRight,
|
|
ChevronLeft,
|
|
Bookmark,
|
|
CheckCircle2,
|
|
Calendar,
|
|
Sparkles,
|
|
X,
|
|
RotateCcw
|
|
} from 'lucide-react';
|
|
|
|
export default function EmployerWorkers() {
|
|
const [searchQuery, setSearchQuery] = useState('');
|
|
const [showFilters, setShowFilters] = useState(false);
|
|
const [activeCat, setActiveCat] = useState('All');
|
|
|
|
const [filters, setFilters] = useState({
|
|
nationality: 'All Nationalities',
|
|
availability: 'All Availabilities',
|
|
experience: 'All Experience',
|
|
religion: 'All Religions',
|
|
maxSalary: 3000
|
|
});
|
|
|
|
const categories = ['All', 'Housemaid', 'Nanny', 'Cook', 'Driver', 'Gardener'];
|
|
|
|
const filterOptions = {
|
|
nationalities: ['All Nationalities', 'Philippines', 'India', 'Sri Lanka', 'Kenya', 'Ethiopia', 'Indonesia'],
|
|
availabilities: ['All Availabilities', 'Available Now', 'Available in 1 week', 'Available in 1 month'],
|
|
experienceLevels: ['All Experience', '0-2 Years', '2-5 Years', '5-10 Years', '10+ Years'],
|
|
religions: ['All Religions', 'Christianity', 'Islam', 'Hinduism', 'Other']
|
|
};
|
|
|
|
const workers = [
|
|
{
|
|
id: 1,
|
|
name: 'Maria Santos',
|
|
role: 'Childcare',
|
|
salary: '1800 AED / mo',
|
|
nationality: 'Philippines',
|
|
initial: 'M',
|
|
bio: '"Experienced nanny with 6 years working with expatriate families in Dubai. Certified in pediatric first aid."',
|
|
exp: '5+ Years',
|
|
avail: 'Immediate',
|
|
religion: 'Christian',
|
|
age: '32 yrs',
|
|
skills: ['Childcare', 'Cooking', 'Housekeeping', 'Ironing']
|
|
},
|
|
{
|
|
id: 2,
|
|
name: 'Elena Gilbert',
|
|
role: 'Housemaid',
|
|
salary: '2500 AED / mo',
|
|
nationality: 'Kenya',
|
|
initial: 'E',
|
|
bio: '"Professional housekeeper with expertise in deep cleaning and organizing. Fluent in English and Swahili."',
|
|
exp: '3+ Years',
|
|
avail: 'Immediate',
|
|
religion: 'Christian',
|
|
age: '28 yrs',
|
|
skills: ['Cleaning', 'Ironing', 'Bilingual']
|
|
}
|
|
];
|
|
|
|
const resetFilters = () => {
|
|
setFilters({
|
|
nationality: 'All Nationalities',
|
|
availability: 'All Availabilities',
|
|
experience: 'All Experience',
|
|
religion: 'All Religions',
|
|
maxSalary: 3000
|
|
});
|
|
setSearchQuery('');
|
|
};
|
|
|
|
return (
|
|
<EmployerMobileLayout>
|
|
<Head title="Find Workers" />
|
|
|
|
<div className="flex flex-col h-full bg-[#F8FAFC]">
|
|
{/* Header */}
|
|
<div className="pt-12 pb-6 px-6 space-y-6 bg-white sticky top-0 z-40 shadow-sm">
|
|
<div className="flex items-center space-x-4">
|
|
<button onClick={() => window.history.back()} className="p-2 bg-slate-50 rounded-xl text-slate-400 border border-slate-100">
|
|
<ChevronLeft className="w-5 h-5" />
|
|
</button>
|
|
<h1 className="text-2xl font-bold text-slate-900 tracking-tight">Find Workers</h1>
|
|
</div>
|
|
|
|
{/* Search Bar */}
|
|
<div className="flex items-center space-x-3">
|
|
<div className="flex-1 relative group">
|
|
<Search className="absolute left-4 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-300 group-focus-within:text-[#185FA5] transition-colors" />
|
|
<input
|
|
type="text"
|
|
placeholder="Search by name or skill..."
|
|
value={searchQuery}
|
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
className="w-full pl-12 pr-4 py-4 bg-slate-50 border border-slate-100 rounded-2xl text-sm focus:ring-4 focus:ring-blue-500/10 focus:border-[#185FA5] outline-none transition-all"
|
|
/>
|
|
</div>
|
|
<button
|
|
onClick={() => setShowFilters(true)}
|
|
className={`w-14 h-14 rounded-2xl flex items-center justify-center border transition-all ${
|
|
showFilters ? 'bg-[#185FA5] text-white border-[#185FA5]' : 'bg-white text-slate-400 border-slate-100'
|
|
}`}
|
|
>
|
|
<Filter className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
|
|
{/* Category Tabs */}
|
|
<div className="flex space-x-2 overflow-x-auto no-scrollbar pb-1">
|
|
{categories.map((cat) => (
|
|
<button
|
|
key={cat}
|
|
onClick={() => setActiveCat(cat)}
|
|
className={`shrink-0 px-5 py-2.5 rounded-full text-[10px] font-bold uppercase tracking-widest transition-all ${
|
|
activeCat === cat
|
|
? 'bg-[#185FA5] text-white shadow-lg'
|
|
: 'bg-white text-slate-400 border border-slate-100 hover:bg-slate-50'
|
|
}`}
|
|
>
|
|
{cat}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Worker Listing */}
|
|
<div className="px-6 py-8 space-y-8 pb-32">
|
|
{workers.map((worker) => (
|
|
<div key={worker.id} className="bg-white rounded-[32px] border border-slate-100 shadow-sm overflow-hidden flex flex-col">
|
|
{/* Card Header Section */}
|
|
<div className="p-6 bg-[#F8FAFC] flex items-center justify-between border-b border-slate-50">
|
|
<div className="flex items-center space-x-4">
|
|
<div className="w-16 h-16 rounded-full bg-[#D8F3FF] flex items-center justify-center text-[#185FA5] font-black text-2xl shadow-inner">
|
|
{worker.initial}
|
|
</div>
|
|
<div className="space-y-1">
|
|
<div className="flex items-center space-x-1.5">
|
|
<h4 className="font-bold text-slate-900 text-lg tracking-tight">{worker.name}</h4>
|
|
<CheckCircle2 className="w-4 h-4 text-emerald-500" />
|
|
</div>
|
|
<div className="flex items-center space-x-1.5 text-slate-400 font-semibold text-xs tracking-wide">
|
|
<Globe className="w-3.5 h-3.5" />
|
|
<span>{worker.nationality}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<button className="w-10 h-10 rounded-full bg-[#EBF5FF] flex items-center justify-center text-[#185FA5]">
|
|
<Bookmark className="w-5 h-5 fill-current" />
|
|
</button>
|
|
</div>
|
|
|
|
{/* Card Body Section */}
|
|
<div className="p-6 space-y-6">
|
|
<div className="flex items-center justify-between">
|
|
<div className="px-4 py-2 bg-[#F0F7FF] text-[#185FA5] rounded-xl text-xs font-bold border border-[#E1EFFF]">
|
|
{worker.role}
|
|
</div>
|
|
<div className="flex items-center space-x-1.5">
|
|
<DollarSign className="w-4 h-4 text-emerald-500" />
|
|
<span className="text-sm font-bold text-slate-900">{worker.salary}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<p className="text-[13px] text-slate-500 font-medium leading-relaxed italic">
|
|
{worker.bio}
|
|
</p>
|
|
|
|
{/* Stats Grid 2x2 */}
|
|
<div className="bg-[#F8FAFC] p-4 rounded-2xl grid grid-cols-2 gap-4 border border-slate-50">
|
|
<div className="flex items-center space-x-2.5">
|
|
<Briefcase className="w-4 h-4 text-slate-400" />
|
|
<div className="text-[11px] font-bold text-slate-600">Exp: {worker.exp}</div>
|
|
</div>
|
|
<div className="flex items-center space-x-2.5">
|
|
<Calendar className="w-4 h-4 text-slate-400" />
|
|
<div className="text-[11px] font-bold text-slate-600">Avail: {worker.avail}</div>
|
|
</div>
|
|
<div className="flex items-center space-x-2.5">
|
|
<Heart className="w-4 h-4 text-slate-400" />
|
|
<div className="text-[11px] font-bold text-slate-600">{worker.religion}</div>
|
|
</div>
|
|
<div className="flex items-center space-x-2.5">
|
|
<Sparkles className="w-4 h-4 text-slate-400" />
|
|
<div className="text-[11px] font-bold text-slate-600">Age: {worker.age}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Skills Tags */}
|
|
<div className="flex flex-wrap gap-2">
|
|
{worker.skills.map((skill) => (
|
|
<span key={skill} className="px-3 py-1.5 bg-slate-50 text-slate-500 text-[10px] font-bold rounded-lg border border-slate-100">
|
|
{skill}
|
|
</span>
|
|
))}
|
|
</div>
|
|
|
|
<Link
|
|
href={`/mobile/employer/workers/${worker.id}`}
|
|
className="w-full py-4 bg-[#185FA5] text-white rounded-2xl font-bold text-sm tracking-tight active:scale-[0.98] transition-all flex items-center justify-center shadow-lg shadow-blue-500/20"
|
|
>
|
|
View Full Profile
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Filter Drawer - Simple UI Style */}
|
|
{showFilters && (
|
|
<div className="fixed inset-0 z-[100] flex items-end justify-center px-4 sm:px-0">
|
|
<div className="absolute inset-0 bg-slate-900/40 backdrop-blur-sm" onClick={() => setShowFilters(false)} />
|
|
<div className="relative w-full max-w-md bg-white rounded-t-[40px] shadow-2xl p-8 pb-12 animate-in slide-in-from-bottom duration-300 overflow-y-auto max-h-[85vh] no-scrollbar">
|
|
<div className="flex items-center justify-between mb-8">
|
|
<div className="flex items-center space-x-3">
|
|
<button onClick={resetFilters} className="p-2 text-slate-400 hover:text-[#185FA5] transition-colors">
|
|
<RotateCcw className="w-5 h-5" />
|
|
</button>
|
|
<h2 className="text-xl font-bold">Filters</h2>
|
|
</div>
|
|
<button onClick={() => setShowFilters(false)} className="w-10 h-10 bg-slate-100 rounded-full flex items-center justify-center text-slate-500 hover:text-rose-500 transition-all">
|
|
<X className="w-5 h-5" strokeWidth={3} />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="space-y-8">
|
|
{/* Nationality */}
|
|
<div className="space-y-3">
|
|
<label className="text-[11px] font-bold text-slate-400 uppercase tracking-widest ml-1">Nationality</label>
|
|
<select
|
|
value={filters.nationality}
|
|
onChange={(e) => setFilters({...filters, nationality: e.target.value})}
|
|
className="w-full px-5 py-4 bg-slate-50 border border-slate-100 rounded-2xl text-sm font-bold appearance-none focus:bg-white focus:border-[#185FA5] outline-none transition-all"
|
|
>
|
|
{filterOptions.nationalities.map(n => <option key={n} value={n}>{n}</option>)}
|
|
</select>
|
|
</div>
|
|
|
|
{/* Availability */}
|
|
<div className="space-y-3">
|
|
<label className="text-[11px] font-bold text-slate-400 uppercase tracking-widest ml-1">Availability</label>
|
|
<div className="grid grid-cols-2 gap-2">
|
|
{filterOptions.availabilities.map(av => (
|
|
<button
|
|
key={av}
|
|
onClick={() => setFilters({...filters, availability: av})}
|
|
className={`px-3 py-3 rounded-xl text-[10px] font-bold text-center border transition-all ${
|
|
filters.availability === av
|
|
? 'bg-[#185FA5] border-[#185FA5] text-white shadow-lg shadow-blue-500/20'
|
|
: 'bg-white border-slate-100 text-slate-400'
|
|
}`}
|
|
>
|
|
{av === 'All Availabilities' ? 'Any' : av.replace('Available ', '')}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Experience */}
|
|
<div className="space-y-3">
|
|
<label className="text-[11px] font-bold text-slate-400 uppercase tracking-widest ml-1">Experience</label>
|
|
<select
|
|
value={filters.experience}
|
|
onChange={(e) => setFilters({...filters, experience: e.target.value})}
|
|
className="w-full px-5 py-4 bg-slate-50 border border-slate-100 rounded-2xl text-sm font-bold appearance-none focus:bg-white focus:border-[#185FA5] outline-none transition-all"
|
|
>
|
|
{filterOptions.experienceLevels.map(ex => <option key={ex} value={ex}>{ex}</option>)}
|
|
</select>
|
|
</div>
|
|
|
|
{/* Salary Slider */}
|
|
<div className="space-y-4 pt-2">
|
|
<div className="flex items-center justify-between px-1">
|
|
<label className="text-[11px] font-bold text-slate-400 uppercase tracking-widest">Max Salary</label>
|
|
<span className="text-sm font-bold text-[#185FA5]">{filters.maxSalary} AED</span>
|
|
</div>
|
|
<input
|
|
type="range"
|
|
min="1200"
|
|
max="3000"
|
|
step="100"
|
|
value={filters.maxSalary}
|
|
onChange={(e) => setFilters({...filters, maxSalary: Number(e.target.value)})}
|
|
className="w-full h-2 bg-slate-100 rounded-full appearance-none cursor-pointer accent-[#185FA5]"
|
|
/>
|
|
<div className="flex justify-between text-[10px] font-bold text-slate-300 uppercase px-1">
|
|
<span>1200 AED</span>
|
|
<span>3000 AED</span>
|
|
</div>
|
|
</div>
|
|
|
|
<button
|
|
onClick={() => setShowFilters(false)}
|
|
className="w-full py-5 bg-[#185FA5] text-white rounded-3xl font-bold text-base shadow-xl shadow-blue-500/30 active:scale-[0.98] transition-all mt-4"
|
|
>
|
|
Apply Filters
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</EmployerMobileLayout>
|
|
);
|
|
}
|