migrant-web/resources/js/Layouts/EmployerLayout.jsx
2026-05-20 13:26:43 +05:30

300 lines
17 KiB
JavaScript

import React, { useEffect } from 'react';
import { Link, usePage } from '@inertiajs/react';
import { toast } from 'sonner';
import {
LayoutDashboard,
Search,
Bookmark,
MessageSquare,
CreditCard,
User,
LogOut,
Bell,
CheckCircle,
AlertCircle,
ArrowRight,
UserCheck,
Megaphone,
Briefcase
} from 'lucide-react';
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator
} from '@/components/ui/dropdown-menu';
export default function EmployerLayout({ children, title, fullPage = false }) {
const { url, props } = usePage();
const { auth, unread_messages_count, flash } = props;
useEffect(() => {
if (flash?.success) {
toast.success(flash.success);
}
if (flash?.error) {
toast.error(flash.error);
}
if (flash?.first_login) {
// Elegant first login celebratory alert
toast.success('🎉 Welcome to Marketplace!', {
description: 'Your employer profile is verified and active with 30 days of Premium Access.',
duration: 6000,
});
}
}, [flash]);
const user = auth?.user || {
name: 'John Doe',
company_name: 'Al Mansoor Household',
email: 'employer@example.com',
subscription_status: 'active',
subscription_expires_at: '2026-12-31',
};
const isSubActive = user.subscription_status === 'active';
const navItems = [
{ name: 'Dashboard', href: '/employer/dashboard', icon: LayoutDashboard },
{ name: 'Find Workers', href: '/employer/workers', icon: Search },
{ name: 'My Jobs', href: '/employer/jobs', icon: Briefcase },
{ name: 'Shortlist', href: '/employer/shortlist', icon: Bookmark },
{ name: 'Candidates', href: '/employer/candidates', icon: UserCheck },
{ name: 'Messages', href: '/employer/messages', icon: MessageSquare, badge: unread_messages_count },
{ name: 'Announcements', href: '/employer/announcements', icon: Megaphone },
{ name: 'Subscription', href: '/employer/subscription', icon: CreditCard },
{ name: 'My Profile', href: '/employer/profile', icon: User },
];
const mobileTabs = [
{ name: 'Search', href: '/employer/workers', icon: Search },
{ name: 'Shortlist', href: '/employer/shortlist', icon: Bookmark },
{ name: 'Candidates', href: '/employer/candidates', icon: UserCheck },
{ name: 'Messages', href: '/employer/messages', icon: MessageSquare, badge: unread_messages_count },
{ name: 'Profile', href: '/employer/profile', icon: User },
];
return (
<div className="min-h-screen flex flex-col bg-slate-50 font-sans select-none">
{/* Top Subscription Gate Banner */}
{!isSubActive && !fullPage && (
<div className="bg-[#185FA5] text-white px-4 py-2.5 text-xs sm:text-sm font-medium flex items-center justify-between shadow-sm z-50">
<div className="flex items-center space-x-2 truncate">
<AlertCircle className="w-4 h-4 text-amber-300 flex-shrink-0 animate-bounce" />
<span className="truncate">You need an active subscription to contact workers.</span>
</div>
<Link
href="/employer/subscription"
className="bg-white text-[#185FA5] hover:bg-slate-100 px-3 py-1 rounded-lg text-xs font-bold transition-colors inline-flex items-center space-x-1 flex-shrink-0 shadow-sm"
>
<span>Subscribe now</span>
<ArrowRight className="w-3 h-3" />
</Link>
</div>
)}
{/* Mobile Header Navbar */}
{!fullPage && (
<header className="lg:hidden sticky top-0 z-40 bg-white border-b border-slate-200 px-4 h-14 flex items-center justify-between">
<div className="flex items-center space-x-2.5">
<div className="w-8 h-8 bg-[#185FA5] text-white rounded-lg flex items-center justify-center font-bold text-base shadow-sm">
M
</div>
<span className="font-bold text-lg text-slate-800 tracking-tight truncate">Employer Portal</span>
</div>
<div className="flex items-center space-x-3">
<Link href="/employer/messages" className="relative p-2 text-slate-600 hover:bg-slate-100 rounded-lg">
<Bell className="w-5 h-5" />
{unread_messages_count > 0 && (
<span className="absolute top-1.5 right-1.5 w-2 h-2 bg-red-500 rounded-full animate-ping" />
)}
</Link>
<div className="w-8 h-8 rounded-full bg-slate-100 border border-slate-200 flex items-center justify-center font-bold text-xs text-[#185FA5]">
{user.name.charAt(0)}
</div>
</div>
</header>
)}
<div className="flex flex-1 flex-col lg:flex-row h-screen overflow-hidden">
{/* Desktop Sidebar (lg+) */}
<aside className="hidden lg:flex w-64 bg-white border-r border-slate-200 flex-col justify-between flex-shrink-0 sticky top-0 h-screen">
<div>
{/* Top Section */}
<div className="p-6 border-b border-slate-100 space-y-4">
<div className="flex items-center space-x-3">
<div className="w-10 h-10 bg-[#185FA5] text-white rounded-xl flex items-center justify-center font-bold text-xl shadow-md">
M
</div>
<span className="font-bold text-xl text-slate-800 tracking-tight">Employer Portal</span>
</div>
{/* Subscription Status Pill */}
<Link href="/employer/subscription" className="block">
{isSubActive ? (
<div className="flex items-center justify-between px-3 py-1.5 bg-emerald-50 border border-emerald-200 rounded-lg text-xs font-semibold text-emerald-700 hover:bg-emerald-100 transition-colors">
<div className="flex items-center space-x-1.5 truncate">
<CheckCircle className="w-3.5 h-3.5 text-emerald-600 flex-shrink-0" />
<span className="truncate">Active until {user.subscription_expires_at || 'Dec 31'}</span>
</div>
</div>
) : (
<div className="flex items-center justify-between px-3 py-1.5 bg-red-50 border border-red-200 rounded-lg text-xs font-semibold text-red-700 hover:bg-red-100 transition-colors">
<div className="flex items-center space-x-1.5 truncate">
<AlertCircle className="w-3.5 h-3.5 text-red-600 flex-shrink-0" />
<span className="truncate">Expired Renew now</span>
</div>
</div>
)}
</Link>
</div>
{/* Navigation Items */}
<nav className="p-4 space-y-1">
{navItems.map((item) => {
const Icon = item.icon;
const isActive = url.startsWith(item.href);
return (
<Link
key={item.name}
href={item.href}
className={`flex items-center justify-between px-4 py-3 rounded-xl text-sm transition-all duration-200 group ${
isActive
? 'bg-[#185FA5] text-white font-bold shadow-lg shadow-blue-900/20 scale-[1.02]'
: 'text-slate-600 hover:bg-slate-50 hover:text-slate-900'
}`}
>
<div className="flex items-center space-x-3">
<Icon className={`w-5 h-5 transition-colors ${isActive ? 'text-white' : 'text-slate-400 group-hover:text-slate-900'}`} />
<span className="tracking-tight">{item.name}</span>
</div>
{item.badge > 0 && (
<span className={`text-[10px] font-black px-2 py-0.5 rounded-full ${isActive ? 'bg-white text-[#185FA5]' : 'bg-[#185FA5] text-white'}`}>
{item.badge}
</span>
)}
</Link>
);
})}
</nav>
</div>
</aside>
{/* Main Content Area */}
<main className="flex-1 flex flex-col min-w-0 h-screen relative overflow-hidden bg-[#FAFBFF]">
{/* Top Desktop Header */}
{!fullPage && (
<header className="hidden lg:flex h-16 bg-white border-b border-slate-200 items-center justify-between px-8 shrink-0 sticky top-0 z-30 shadow-sm">
<div className="flex items-center space-x-4">
<div className="text-xs font-bold text-slate-400 uppercase tracking-widest">
{title || 'Overview'}
</div>
</div>
<div className="flex items-center space-x-6">
{/* Language Switcher */}
<div className="flex items-center bg-slate-50 border border-slate-200 rounded-xl p-1">
<button className="px-3 py-1 text-[10px] font-black bg-white text-[#185FA5] rounded-lg shadow-sm border border-slate-100">EN</button>
<button className="px-3 py-1 text-[10px] font-black text-slate-400 hover:text-slate-600">AR</button>
</div>
{/* Chat/Notifications */}
<Link href="/employer/messages" className="relative p-2.5 text-slate-500 hover:text-[#185FA5] hover:bg-blue-50 rounded-xl transition-all group">
<MessageSquare className="w-5 h-5" />
<span className="absolute top-2 right-2 w-2 h-2 bg-red-500 rounded-full border-2 border-white group-hover:scale-110 transition-transform" />
</Link>
{/* Profile Section with Dropdown */}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button className="flex items-center space-x-3 pl-6 border-l border-slate-200 group outline-none">
<div className="text-right hidden sm:block">
<div className="text-xs font-black text-slate-900 group-hover:text-[#185FA5] transition-colors">{user.name}</div>
<div className="text-[10px] font-bold text-slate-400 uppercase tracking-tighter">Employer Account</div>
</div>
<div className="w-10 h-10 rounded-xl bg-blue-100 text-[#185FA5] flex items-center justify-center font-black text-xs border border-blue-200 shadow-sm transition-transform group-hover:scale-105">
{user.name.charAt(0)}
</div>
</button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56 mt-2">
<DropdownMenuLabel className="text-[10px] font-black text-slate-400 uppercase tracking-widest px-2 py-1.5">My Account</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link href="/employer/profile" className="flex items-center space-x-2 text-xs font-bold text-slate-600 cursor-pointer">
<User className="w-4 h-4" />
<span>Profile Settings</span>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/employer/subscription" className="flex items-center space-x-2 text-xs font-bold text-slate-600 cursor-pointer">
<CreditCard className="w-4 h-4" />
<span>Subscription</span>
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link
href={route('employer.logout')}
method="post"
as="button"
className="w-full flex items-center space-x-2 text-xs font-bold text-rose-600 cursor-pointer"
>
<LogOut className="w-4 h-4" />
<span>Sign Out</span>
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</header>
)}
<div className={`flex-1 overflow-y-auto ${fullPage ? 'p-0' : 'p-4 sm:p-8 pb-24 lg:pb-8'}`}>
{title && !fullPage && (
<h1 className="text-2xl font-black text-slate-900 mb-6 tracking-tight lg:hidden">{title}</h1>
)}
{children}
</div>
</main>
</div>
{/* Mobile Bottom Tab Bar */}
{!fullPage && (
<nav className="lg:hidden fixed bottom-0 left-0 right-0 bg-white border-t border-slate-200 h-16 px-4 flex items-center justify-around z-40">
{mobileTabs.map((tab) => {
const Icon = tab.icon;
const isActive = url.startsWith(tab.href);
return (
<Link
key={tab.name}
href={tab.href}
className={`flex flex-col items-center justify-center space-y-1 w-16 h-full ${
isActive ? 'text-[#185FA5]' : 'text-slate-400 hover:text-slate-600'
}`}
>
<div className="relative">
<Icon className="w-5 h-5" />
{tab.badge > 0 && (
<span className="absolute -top-1 -right-2 w-3.5 h-3.5 bg-red-500 text-white rounded-full flex items-center justify-center text-[8px] font-bold">
{tab.badge}
</span>
)}
</div>
<span className="text-[10px] font-bold">{tab.name}</span>
</Link>
);
})}
</nav>
)}
</div>
);
}