568 lines
37 KiB
JavaScript
568 lines
37 KiB
JavaScript
import React, { useState } from 'react';
|
|
import { Head, Link, router } from '@inertiajs/react';
|
|
import EmployerLayout from '../../Layouts/EmployerLayout';
|
|
import { useTranslation } from '../../lib/LanguageContext';
|
|
import {
|
|
User,
|
|
ShieldCheck,
|
|
Mail,
|
|
Phone,
|
|
Globe,
|
|
MapPin,
|
|
Home,
|
|
Edit3,
|
|
Calendar,
|
|
Briefcase,
|
|
Building,
|
|
FileText,
|
|
MessageSquare,
|
|
AlertCircle,
|
|
CheckCircle2,
|
|
Lock,
|
|
ExternalLink,
|
|
Compass,
|
|
FileSpreadsheet,
|
|
Eye,
|
|
Bell,
|
|
Camera,
|
|
Save,
|
|
XCircle
|
|
} from 'lucide-react';
|
|
import { toast } from 'sonner';
|
|
|
|
export default function Profile({ employerProfile }) {
|
|
const { t } = useTranslation();
|
|
const [showConfirmPopup, setShowConfirmPopup] = useState(false);
|
|
|
|
const handleEditClick = () => {
|
|
setShowConfirmPopup(true);
|
|
};
|
|
|
|
const handleConfirmEdit = () => {
|
|
setShowConfirmPopup(false);
|
|
router.get('/employer/profile/edit');
|
|
};
|
|
|
|
const handleCancelEdit = () => {
|
|
setShowConfirmPopup(false);
|
|
};
|
|
|
|
const [showRenewModal, setShowRenewModal] = useState(false);
|
|
const [frontFile, setFrontFile] = useState(null);
|
|
const [backFile, setBackFile] = useState(null);
|
|
const [frontPreview, setFrontPreview] = useState(null);
|
|
const [backPreview, setBackPreview] = useState(null);
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
|
|
const expiryDateStr = employerProfile?.emirates_id?.expiry_date;
|
|
const isExpired = expiryDateStr ? new Date(expiryDateStr) <= new Date() : false;
|
|
|
|
const handleRenewalSubmit = (e) => {
|
|
e.preventDefault();
|
|
if (!frontFile || !backFile) {
|
|
toast.error(t('upload_both_sides', 'Please upload both front and back sides of your Emirates ID.'));
|
|
return;
|
|
}
|
|
|
|
setIsSubmitting(true);
|
|
|
|
router.post('/employer/profile/update', {
|
|
name: employerProfile.name,
|
|
email: employerProfile.email,
|
|
phone: employerProfile.phone,
|
|
emirates_id_front: frontFile,
|
|
emirates_id_back: backFile,
|
|
}, {
|
|
forceFormData: true,
|
|
onSuccess: () => {
|
|
toast.success(t('document_renewed', 'Emirates ID renewed successfully!'));
|
|
setShowRenewModal(false);
|
|
setFrontFile(null);
|
|
setBackFile(null);
|
|
setFrontPreview(null);
|
|
setBackPreview(null);
|
|
setIsSubmitting(false);
|
|
},
|
|
onError: (errs) => {
|
|
toast.error(Object.values(errs)[0] || t('renewal_failed', 'Failed to renew Emirates ID.'));
|
|
setIsSubmitting(false);
|
|
}
|
|
});
|
|
};
|
|
|
|
const toggleNotification = (type, currentVal) => {
|
|
router.post('/employer/profile/update', {
|
|
name: employerProfile.name,
|
|
email: employerProfile.email,
|
|
phone: employerProfile.phone,
|
|
email_notifications: type === 'email' ? !currentVal : employerProfile.email_notifications,
|
|
push_notifications: type === 'push' ? !currentVal : employerProfile.push_notifications,
|
|
}, {
|
|
preserveScroll: true,
|
|
onSuccess: () => {
|
|
toast.success(t('preferences_updated', 'Preferences updated successfully'));
|
|
}
|
|
});
|
|
};
|
|
|
|
const profilePhoto = employerProfile?.profile_photo_url;
|
|
|
|
return (
|
|
<EmployerLayout title={t('employer_profile_details', 'Profile Details')}>
|
|
<Head title={`${t('profile', 'Profile')} - ${t('employer_portal', 'Sponsor Portal')}`} />
|
|
|
|
<div className="max-w-5xl mx-auto pb-16 space-y-8 select-none animate-in fade-in duration-500">
|
|
{isExpired && (
|
|
<div className="bg-rose-50 border border-rose-200 rounded-3xl p-6 shadow-sm flex flex-col md:flex-row md:items-center justify-between gap-4 animate-in slide-in-from-top duration-300">
|
|
<div className="flex items-start gap-4">
|
|
<div className="p-3 bg-rose-100 text-rose-600 rounded-2xl">
|
|
<AlertCircle className="w-6 h-6 animate-pulse" />
|
|
</div>
|
|
<div className="space-y-1">
|
|
<h4 className="text-sm font-black text-rose-950 uppercase tracking-wide">Emirates ID Expired</h4>
|
|
<p className="text-xs text-rose-700/90 font-bold leading-normal">
|
|
Your Emirates ID card expired on <span className="font-extrabold">{employerProfile?.emirates_id?.expiry_date}</span>. Please upload a renewed document to maintain compliance and system access.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<button
|
|
onClick={() => setShowRenewModal(true)}
|
|
className="bg-rose-600 hover:bg-rose-700 text-white px-5 py-3 rounded-2xl text-xs font-black uppercase tracking-wider transition-all shadow-md shadow-rose-200/50 flex items-center justify-center gap-2 whitespace-nowrap self-start md:self-center"
|
|
>
|
|
<span>Renew Emirates ID</span>
|
|
</button>
|
|
</div>
|
|
)}
|
|
|
|
{/* Premium Banner & Cover Section */}
|
|
<div className="relative bg-white rounded-3xl border border-slate-200 shadow-sm overflow-hidden">
|
|
{/* Artistic Enterprise Gradient Header Cover */}
|
|
<div className="h-40 bg-gradient-to-r from-[#185FA5] via-[#2d7ad6] to-[#0f62ac] relative">
|
|
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_right,rgba(255,255,255,0.15),transparent)] pointer-events-none" />
|
|
<div className="absolute -bottom-8 left-8 flex items-center gap-2 text-white/10 select-none">
|
|
<Compass className="w-32 h-32 stroke-[0.5]" />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Profile Header Details Row */}
|
|
<div className="px-8 pb-8 pt-4 relative flex flex-col md:flex-row items-center md:items-end justify-between gap-6">
|
|
<div className="flex flex-col md:flex-row items-center md:items-end gap-6 -mt-16 relative z-10 text-center md:text-left">
|
|
{/* Profile Image with Glow Ring */}
|
|
<div className="relative">
|
|
<div className="w-28 h-28 rounded-2xl bg-white p-1.5 shadow-xl border border-slate-100">
|
|
{profilePhoto ? (
|
|
<img
|
|
src={profilePhoto}
|
|
alt={employerProfile?.name}
|
|
className="w-full h-full rounded-xl object-cover"
|
|
/>
|
|
) : (
|
|
<div className="w-full h-full rounded-xl bg-gradient-to-br from-[#185FA5]/10 to-[#185FA5]/20 text-[#185FA5] flex items-center justify-center font-black text-4xl border border-blue-100">
|
|
{employerProfile?.name?.charAt(0)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
<span className="absolute bottom-1 right-1 w-4 h-4 bg-emerald-500 rounded-full border-2 border-white shadow-sm" />
|
|
</div>
|
|
|
|
<div className="space-y-1.5 pb-2">
|
|
<div className="flex flex-wrap items-center justify-center md:justify-start gap-2.5">
|
|
<h2 className="text-2xl font-black text-slate-900 tracking-tight leading-none">{employerProfile?.name}</h2>
|
|
</div>
|
|
<p className="text-slate-500 font-bold text-xs">{employerProfile?.email}</p>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
{/* Edit Button */}
|
|
<button
|
|
onClick={handleEditClick}
|
|
className="bg-[#185FA5] hover:bg-[#144f8a] text-white px-6 py-3.5 rounded-2xl text-xs font-black uppercase tracking-wider flex items-center space-x-2 transition-all shadow-lg shadow-blue-200/50 hover:shadow-blue-300/60 active:scale-95 group"
|
|
>
|
|
<Edit3 className="w-4 h-4 transition-transform group-hover:rotate-12" />
|
|
<span>{t('edit_profile_details', 'Edit Profile')}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Grid Layout: Left Details Column & Right Digital Card Column */}
|
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8">
|
|
|
|
{/* Left Column: General & Invoicing Info (7/12 width) */}
|
|
<div className="lg:col-span-7 space-y-8">
|
|
|
|
{/* Account & Contact Settings */}
|
|
<div className="bg-white rounded-3xl border border-slate-200 p-8 shadow-sm space-y-6">
|
|
<div className="border-b border-slate-100 pb-4">
|
|
<h3 className="text-base font-black text-slate-900">{t('account_contact_info', 'Account & Contact Information')}</h3>
|
|
<p className="text-[10px] font-bold text-slate-400 uppercase tracking-widest mt-1">
|
|
{t('manage_contact_desc', 'Contact and notification channels')}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<div className="p-4 bg-slate-50 hover:bg-slate-100/50 rounded-2xl border border-slate-150 transition-colors">
|
|
<div className="flex items-center space-x-2 text-slate-400">
|
|
<User className="w-4 h-4 text-[#185FA5]" />
|
|
<span className="text-[9px] font-black uppercase tracking-wider">{t('full_name', 'Full Name')}</span>
|
|
</div>
|
|
<div className="text-xs font-black text-slate-800 mt-2">{employerProfile?.name}</div>
|
|
</div>
|
|
|
|
<div className="p-4 bg-slate-50 hover:bg-slate-100/50 rounded-2xl border border-slate-150 transition-colors">
|
|
<div className="flex items-center space-x-2 text-slate-400">
|
|
<Mail className="w-4 h-4 text-[#185FA5]" />
|
|
<span className="text-[9px] font-black uppercase tracking-wider">{t('email', 'Email Address')}</span>
|
|
</div>
|
|
<div className="text-xs font-black text-slate-800 mt-2 truncate" title={employerProfile?.email}>{employerProfile?.email}</div>
|
|
</div>
|
|
|
|
<div className="p-4 bg-slate-50 hover:bg-slate-100/50 rounded-2xl border border-slate-150 transition-colors">
|
|
<div className="flex items-center space-x-2 text-slate-400">
|
|
<Phone className="w-4 h-4 text-[#185FA5]" />
|
|
<span className="text-[9px] font-black uppercase tracking-wider">{t('phone', 'Phone Number')}</span>
|
|
</div>
|
|
<div className="text-xs font-black text-slate-800 mt-2">{employerProfile?.phone}</div>
|
|
</div>
|
|
|
|
<div className="p-4 bg-slate-50 hover:bg-slate-100/50 rounded-2xl border border-slate-150 transition-colors">
|
|
<div className="flex items-center space-x-2 text-slate-400">
|
|
<Home className="w-4 h-4 text-[#185FA5]" />
|
|
<span className="text-[9px] font-black uppercase tracking-wider">{t('property_type', 'Property Type')}</span>
|
|
</div>
|
|
<div className="text-xs font-black text-slate-800 mt-2">{employerProfile?.property_type || t('not_specified', 'Not Specified')}</div>
|
|
</div>
|
|
|
|
<div className="p-4 bg-slate-50 hover:bg-slate-100/50 rounded-2xl border border-slate-150 transition-colors sm:col-span-2">
|
|
<div className="flex items-center space-x-2 text-slate-400">
|
|
<MapPin className="w-4 h-4 text-[#185FA5]" />
|
|
<span className="text-[9px] font-black uppercase tracking-wider">{t('address', 'Address')}</span>
|
|
</div>
|
|
<div className="text-xs font-black text-slate-800 mt-2 leading-relaxed">{employerProfile?.address || t('not_specified', 'Not Specified')}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Notification Preferences & Integration Card */}
|
|
<div className="bg-white rounded-3xl border border-slate-200 p-8 shadow-sm space-y-6">
|
|
<div className="border-b border-slate-100 pb-4">
|
|
<h3 className="text-base font-black text-slate-900">{t('notification_preferences', 'Notification Preferences')}</h3>
|
|
</div>
|
|
|
|
{/* Preferences Toggles */}
|
|
<div className="space-y-4">
|
|
{/* Email Alerts Row */}
|
|
<div className="flex items-center justify-between p-4 bg-slate-50 rounded-2xl border border-slate-150 transition-all hover:bg-slate-100/50">
|
|
<div className="flex items-center gap-3">
|
|
<div className="p-2.5 bg-blue-550/10 text-[#185FA5] rounded-xl">
|
|
<Mail className="w-5 h-5" />
|
|
</div>
|
|
<div>
|
|
<h4 className="text-xs font-black text-slate-800">{t('email_alerts', 'Email Alerts')}</h4>
|
|
<p className="text-[10px] text-slate-400 font-bold uppercase tracking-wider mt-0.5">{t('email_alerts_sub', 'Invoices, updates & announcements')}</p>
|
|
</div>
|
|
</div>
|
|
<button
|
|
type="button"
|
|
onClick={() => toggleNotification('email', employerProfile?.email_notifications)}
|
|
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none ${
|
|
employerProfile?.email_notifications ? 'bg-[#185FA5]' : 'bg-slate-200'
|
|
}`}
|
|
>
|
|
<span
|
|
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
|
employerProfile?.email_notifications ? 'translate-x-6' : 'translate-x-1'
|
|
}`}
|
|
/>
|
|
</button>
|
|
</div>
|
|
|
|
{/* Push Notification Alerts Row */}
|
|
<div className="flex items-center justify-between p-4 bg-slate-50 rounded-2xl border border-slate-150 transition-all hover:bg-slate-100/50">
|
|
<div className="flex items-center gap-3">
|
|
<div className="p-2.5 bg-blue-550/10 text-[#185FA5] rounded-xl">
|
|
<Bell className="w-5 h-5" />
|
|
</div>
|
|
<div>
|
|
<h4 className="text-xs font-black text-slate-800">{t('push_alerts', 'Push Notifications')}</h4>
|
|
<p className="text-[10px] text-slate-400 font-bold uppercase tracking-wider mt-0.5">{t('push_alerts_sub', 'Live updates & mobile alerts')}</p>
|
|
</div>
|
|
</div>
|
|
<button
|
|
type="button"
|
|
onClick={() => toggleNotification('push', employerProfile?.push_notifications)}
|
|
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none ${
|
|
employerProfile?.push_notifications ? 'bg-[#185FA5]' : 'bg-slate-200'
|
|
}`}
|
|
>
|
|
<span
|
|
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
|
employerProfile?.push_notifications ? 'translate-x-6' : 'translate-x-1'
|
|
}`}
|
|
/>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Right Column: Digital Emirates ID & Card Visual (5/12 width) */}
|
|
<div className="lg:col-span-5 space-y-8">
|
|
|
|
{/* Interactive Digital Emirates ID Widget */}
|
|
<div className="bg-white rounded-3xl border border-slate-200 p-8 shadow-sm space-y-6">
|
|
<div className="border-b border-slate-100 pb-4">
|
|
<h3 className="text-base font-black text-slate-900">{t('identity_card', 'Emirates ID Details')}</h3>
|
|
<p className="text-[10px] font-bold text-slate-400 uppercase tracking-widest mt-1">
|
|
{t('vetted_details_badge', 'Vetted MOHRE identity credentials')}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Digital Emirates ID Visual */}
|
|
<div className="relative bg-gradient-to-br from-[#1b3d6c] to-[#0d223e] p-6 rounded-2xl text-white shadow-xl overflow-hidden aspect-[1.586/1] border border-white/5 flex flex-col justify-between">
|
|
{/* Sparkle Background Art */}
|
|
<div className="absolute top-0 right-0 w-36 h-36 bg-blue-500/15 rounded-full -mr-12 -mt-12 blur-3xl pointer-events-none" />
|
|
<div className="absolute bottom-0 left-0 w-36 h-36 bg-emerald-500/10 rounded-full -ml-12 -mb-12 blur-3xl pointer-events-none" />
|
|
|
|
{isExpired && (
|
|
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 border-4 border-rose-500/30 text-rose-500/30 font-black text-2xl uppercase tracking-widest px-4 py-2 rounded-xl rotate-12 select-none z-20 pointer-events-none">
|
|
Expired
|
|
</div>
|
|
)}
|
|
|
|
{/* Top Header */}
|
|
<div className="flex items-center justify-between z-10">
|
|
<div className="space-y-0.5">
|
|
<div className="text-[7px] font-black tracking-widest text-slate-400 uppercase">United Arab Emirates</div>
|
|
<div className="text-[10px] font-black tracking-wide text-white uppercase">Resident Identity Card</div>
|
|
</div>
|
|
<div className="w-7 h-5 bg-white/10 rounded border border-white/10 flex items-center justify-center">
|
|
<Globe className="w-3.5 h-3.5 text-slate-300" />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Card Number & Name */}
|
|
<div className="space-y-2.5 z-10 my-4">
|
|
<div className="text-xs font-mono font-black tracking-widest text-white/95">
|
|
{employerProfile?.emirates_id?.emirates_id_number}
|
|
</div>
|
|
<div className="space-y-0.5">
|
|
<div className="text-[6px] font-black text-slate-400 uppercase tracking-wider">Name</div>
|
|
<div className="text-[11px] font-extrabold text-white truncate max-w-[240px]">
|
|
{employerProfile?.emirates_id?.name}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Bottom Info Row */}
|
|
<div className="grid grid-cols-3 gap-2 pt-2 border-t border-white/10 z-10">
|
|
<div>
|
|
<span className="text-[5px] font-black text-slate-400 uppercase tracking-wider block">Nationality</span>
|
|
<span className="text-[9px] font-bold text-white block">{employerProfile?.emirates_id?.nationality}</span>
|
|
</div>
|
|
<div>
|
|
<span className="text-[5px] font-black text-slate-400 uppercase tracking-wider block">Expiry Date</span>
|
|
<span className={`text-[9px] font-bold block ${isExpired ? 'text-rose-400 font-extrabold animate-pulse' : 'text-white'}`}>
|
|
{employerProfile?.emirates_id?.expiry_date}
|
|
</span>
|
|
</div>
|
|
<div>
|
|
<span className="text-[5px] font-black text-slate-400 uppercase tracking-wider block">Occupation</span>
|
|
<span className="text-[9px] font-bold text-white block truncate">{employerProfile?.emirates_id?.occupation}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Renew Button below ID Card if expired */}
|
|
{isExpired && (
|
|
<button
|
|
onClick={() => setShowRenewModal(true)}
|
|
className="w-full bg-rose-600 hover:bg-rose-700 text-white py-3.5 rounded-2xl text-xs font-black uppercase tracking-wider flex items-center justify-center space-x-2 transition-all shadow-md shadow-rose-200"
|
|
>
|
|
<span>Renew Emirates ID</span>
|
|
</button>
|
|
)}
|
|
|
|
{/* Detailed Metadata Fields */}
|
|
<div className="space-y-4 pt-4 border-t border-slate-100 text-xs">
|
|
<div className="flex justify-between py-2 border-b border-slate-50">
|
|
<span className="font-bold text-slate-400 uppercase tracking-wider text-[9px]">{t('issue_place', 'Issue Place')}</span>
|
|
<span className="font-extrabold text-slate-700">{employerProfile?.emirates_id?.issue_place}</span>
|
|
</div>
|
|
<div className="flex justify-between py-2 border-b border-slate-50">
|
|
<span className="font-bold text-slate-400 uppercase tracking-wider text-[9px]">{t('issue_date', 'Issue Date')}</span>
|
|
<span className="font-extrabold text-slate-700">{employerProfile?.emirates_id?.issue_date}</span>
|
|
</div>
|
|
<div className="flex justify-between py-2 border-b border-slate-50">
|
|
<span className="font-bold text-slate-400 uppercase tracking-wider text-[9px]">{t('date_of_birth', 'Date of Birth')}</span>
|
|
<span className="font-extrabold text-slate-700">{employerProfile?.emirates_id?.date_of_birth}</span>
|
|
</div>
|
|
<div className="flex justify-between py-2">
|
|
<span className="font-bold text-slate-400 uppercase tracking-wider text-[9px]">{t('employer_agency', 'Sponsor')}</span>
|
|
<span className="font-extrabold text-[#185FA5] truncate max-w-[200px]" title={employerProfile?.emirates_id?.employer}>
|
|
{employerProfile?.emirates_id?.employer}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Confirmation Dialog Popup Modal */}
|
|
{showConfirmPopup && (
|
|
<div className="fixed inset-0 bg-slate-900/60 backdrop-blur-sm z-50 flex items-center justify-center p-4">
|
|
<div className="bg-white rounded-3xl max-w-sm w-full p-8 border border-slate-100 shadow-2xl space-y-6 animate-in zoom-in-95 duration-200">
|
|
<div className="flex flex-col items-center text-center space-y-4">
|
|
<div className="p-4 bg-blue-50 text-[#185FA5] rounded-2xl">
|
|
<AlertCircle className="w-8 h-8" />
|
|
</div>
|
|
<div className="space-y-2">
|
|
<h3 className="text-base font-black text-slate-900">
|
|
{t('edit_profile_confirm_title', 'Edit Profile')}
|
|
</h3>
|
|
<p className="text-xs text-slate-500 font-medium leading-relaxed">
|
|
{t('edit_profile_confirm_body', 'Are you sure you want to edit your profile details?')}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex gap-4">
|
|
<button
|
|
onClick={handleCancelEdit}
|
|
className="flex-1 px-4 py-3 border border-slate-200 hover:bg-slate-50 text-slate-650 rounded-xl text-xs font-black uppercase tracking-wider transition-colors outline-none"
|
|
>
|
|
{t('cancel', 'Cancel')}
|
|
</button>
|
|
<button
|
|
onClick={handleConfirmEdit}
|
|
className="flex-1 px-4 py-3 bg-[#185FA5] hover:bg-[#144f8a] text-white rounded-xl text-xs font-black uppercase tracking-wider transition-colors outline-none shadow-md shadow-blue-200/50"
|
|
>
|
|
{t('confirm', 'Confirm')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Renew Emirates ID Modal */}
|
|
{showRenewModal && (
|
|
<div className="fixed inset-0 bg-slate-900/60 backdrop-blur-sm z-[9999] flex items-center justify-center p-4 animate-in fade-in duration-300">
|
|
<div className="bg-white rounded-3xl border border-slate-200 shadow-2xl max-w-xl w-full overflow-hidden animate-in zoom-in-95 duration-300">
|
|
{/* Modal Header */}
|
|
<div className="bg-gradient-to-r from-rose-600 to-rose-700 p-6 text-white relative">
|
|
<h3 className="text-base font-black uppercase tracking-wide">Renew Emirates ID</h3>
|
|
<p className="text-[10px] text-rose-100 font-bold uppercase tracking-wider mt-1">Upload both sides of your new document</p>
|
|
<button
|
|
onClick={() => setShowRenewModal(false)}
|
|
className="absolute top-6 right-6 text-rose-100 hover:text-white transition-colors"
|
|
>
|
|
<XCircle className="w-6 h-6" />
|
|
</button>
|
|
</div>
|
|
|
|
{/* Modal Form */}
|
|
<form onSubmit={handleRenewalSubmit} className="p-6 space-y-6">
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
{/* Front Side Upload */}
|
|
<div className="space-y-2">
|
|
<label className="text-[10px] font-black text-slate-500 uppercase tracking-wider block">Front Side</label>
|
|
<div className="border-2 border-dashed border-slate-200 hover:border-[#185FA5] rounded-2xl p-4 transition-all bg-slate-50/5 flex flex-col items-center justify-center min-h-[160px] relative overflow-hidden group">
|
|
{frontPreview ? (
|
|
<>
|
|
<img src={frontPreview} alt="Front ID Preview" className="absolute inset-0 w-full h-full object-cover" />
|
|
<div className="absolute inset-0 bg-slate-900/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
|
|
<span className="text-[10px] font-black uppercase tracking-wider text-white">Change Photo</span>
|
|
</div>
|
|
</>
|
|
) : (
|
|
<div className="flex flex-col items-center text-slate-400 space-y-2">
|
|
<Camera className="w-8 h-8 text-[#185FA5]/70" />
|
|
<span className="text-[10px] font-bold uppercase tracking-wider text-slate-500">Upload Front Side</span>
|
|
</div>
|
|
)}
|
|
<input
|
|
type="file"
|
|
accept="image/*"
|
|
onChange={(e) => {
|
|
const file = e.target.files[0];
|
|
if (file) {
|
|
setFrontFile(file);
|
|
setFrontPreview(URL.createObjectURL(file));
|
|
}
|
|
}}
|
|
className="absolute inset-0 opacity-0 cursor-pointer"
|
|
required
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Back Side Upload */}
|
|
<div className="space-y-2">
|
|
<label className="text-[10px] font-black text-slate-500 uppercase tracking-wider block">Back Side</label>
|
|
<div className="border-2 border-dashed border-slate-200 hover:border-[#185FA5] rounded-2xl p-4 transition-all bg-slate-50/5 flex flex-col items-center justify-center min-h-[160px] relative overflow-hidden group">
|
|
{backPreview ? (
|
|
<>
|
|
<img src={backPreview} alt="Back ID Preview" className="absolute inset-0 w-full h-full object-cover" />
|
|
<div className="absolute inset-0 bg-slate-900/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
|
|
<span className="text-[10px] font-black uppercase tracking-wider text-white">Change Photo</span>
|
|
</div>
|
|
</>
|
|
) : (
|
|
<div className="flex flex-col items-center text-slate-400 space-y-2">
|
|
<Camera className="w-8 h-8 text-[#185FA5]/70" />
|
|
<span className="text-[10px] font-bold uppercase tracking-wider text-slate-500">Upload Back Side</span>
|
|
</div>
|
|
)}
|
|
<input
|
|
type="file"
|
|
accept="image/*"
|
|
onChange={(e) => {
|
|
const file = e.target.files[0];
|
|
if (file) {
|
|
setBackFile(file);
|
|
setBackPreview(URL.createObjectURL(file));
|
|
}
|
|
}}
|
|
className="absolute inset-0 opacity-0 cursor-pointer"
|
|
required
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Actions */}
|
|
<div className="flex items-center justify-end gap-3 pt-4 border-t border-slate-100">
|
|
<button
|
|
type="button"
|
|
onClick={() => setShowRenewModal(false)}
|
|
className="px-5 py-3 border border-slate-200 hover:bg-slate-50 text-slate-650 rounded-xl text-xs font-black uppercase tracking-wider transition-colors outline-none"
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
disabled={isSubmitting}
|
|
className="bg-rose-600 hover:bg-rose-700 disabled:bg-rose-450 text-white px-6 py-3 rounded-xl text-xs font-black uppercase tracking-wider transition-all flex items-center gap-2 shadow-md shadow-rose-100"
|
|
>
|
|
{isSubmitting ? (
|
|
<>
|
|
<span className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
|
|
<span>Processing OCR...</span>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Save className="w-4 h-4" />
|
|
<span>Upload & Renew</span>
|
|
</>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</EmployerLayout>
|
|
);
|
|
}
|