2026-05-20 13:26:43 +05:30

342 lines
20 KiB
JavaScript

import React, { useState, useEffect, useRef } from 'react';
import { Head, Link, router } from '@inertiajs/react';
import EmployerLayout from '../../../Layouts/EmployerLayout';
import {
Send,
ArrowLeft,
CheckCircle2,
Globe2,
DollarSign,
Sparkles,
MoreVertical,
Phone,
Video,
Paperclip,
Search,
Info,
Calendar,
Briefcase,
ShieldCheck,
ChevronRight,
MapPin,
Smile
} from 'lucide-react';
export default function Show({ conversation, initialMessages, conversations = [] }) {
const [messages, setMessages] = useState(initialMessages || []);
const [input, setInput] = useState('');
const [isTyping, setIsTyping] = useState(false);
const [searchTerm, setSearchTerm] = useState('');
const [showProfile, setShowProfile] = useState(false);
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
};
useEffect(() => {
scrollToBottom();
}, [messages, isTyping]);
useEffect(() => {
setMessages(initialMessages || []);
}, [initialMessages]);
const filteredConversations = (conversations || []).filter(c =>
c.worker_name.toLowerCase().includes(searchTerm.toLowerCase())
);
const sendMsg = (text) => {
if (!text.trim()) return;
router.post(`/employer/messages/${conversation.id}/send`, {
text: text
}, {
preserveScroll: true,
onSuccess: () => {
setInput('');
}
});
};
const handleFormSubmit = (e) => {
e.preventDefault();
sendMsg(input);
};
const chips = [
"Are you available for a video interview today?",
"What is your final expected salary?",
"Can you transfer your visa immediately?"
];
return (
<EmployerLayout title={null} fullPage={true}>
<Head title={`Chat with ${conversation.worker_name} - Messages`} />
<div className="flex h-full bg-[#FAFBFF] overflow-hidden select-none">
{/* Conversation List Sidebar (Desktop) */}
<aside className="hidden xl:flex w-96 border-r border-slate-200 flex-col flex-shrink-0 bg-white shadow-sm z-30">
<div className="p-6 border-b border-slate-100">
<div className="flex items-center justify-between mb-6">
<h2 className="font-black text-2xl text-slate-900 tracking-tight">Messages</h2>
<button className="p-2 bg-slate-50 text-slate-400 rounded-xl hover:text-[#185FA5] transition-colors">
<Search className="w-5 h-5" />
</button>
</div>
<div className="relative">
<input
type="text"
placeholder="Search by name..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="w-full pl-5 pr-4 py-3.5 bg-slate-50 border-none rounded-2xl text-sm font-bold focus:ring-2 focus:ring-blue-100 transition-all placeholder:text-slate-400"
/>
</div>
</div>
<div className="flex-1 overflow-y-auto divide-y divide-slate-50">
{filteredConversations.map((c) => (
<Link
key={c.id}
href={`/employer/messages/${c.id}`}
className={`flex items-center space-x-4 p-5 transition-all relative group ${
c.id === conversation.id ? 'bg-blue-50/50' : 'hover:bg-slate-50'
}`}
>
{c.id === conversation.id && (
<div className="absolute left-0 top-0 bottom-0 w-1.5 bg-[#185FA5] rounded-r-full shadow-[0_0_15px_rgba(24,95,165,0.4)]" />
)}
<div className="relative flex-shrink-0">
<div className={`w-14 h-14 rounded-[20px] text-white flex items-center justify-center font-black text-xl shadow-lg ${
c.id === conversation.id ? 'bg-gradient-to-br from-[#185FA5] to-blue-600' : 'bg-slate-200 text-slate-400'
}`}>
{c.worker_name.charAt(0)}
</div>
{c.online && (
<span className="absolute -bottom-1 -right-1 w-4 h-4 bg-emerald-500 border-4 border-white rounded-full shadow-sm" />
)}
</div>
<div className="flex-1 min-w-0">
<div className="flex items-center justify-between mb-1">
<span className={`text-sm font-black truncate ${c.id === conversation.id ? 'text-[#185FA5]' : 'text-slate-900'}`}>
{c.worker_name}
</span>
<span className="text-[10px] text-slate-400 font-bold uppercase tracking-tighter">{c.sent_at}</span>
</div>
<p className={`text-xs font-bold truncate leading-tight ${c.unread ? 'text-slate-900' : 'text-slate-400'}`}>
{c.last_message}
</p>
</div>
{c.unread && (
<div className="w-2.5 h-2.5 bg-red-500 rounded-full flex-shrink-0 shadow-[0_0_8px_rgba(239,68,68,0.4)]" />
)}
</Link>
))}
</div>
</aside>
{/* Main Chat Interface */}
<div className="flex-1 flex flex-col h-full bg-white relative z-10 shadow-2xl">
{/* Glassmorphism Header */}
<div className="bg-white/80 backdrop-blur-xl p-4 sm:p-6 border-b border-slate-100 flex items-center justify-between z-40 sticky top-0">
<div className="flex items-center space-x-4">
<Link
href="/employer/messages"
className="lg:hidden p-2.5 text-slate-400 hover:text-[#185FA5] hover:bg-blue-50 rounded-2xl transition-all"
>
<ArrowLeft className="w-6 h-6" />
</Link>
<div className="relative group">
<div className="w-12 h-12 rounded-2xl bg-gradient-to-br from-[#185FA5] to-blue-600 text-white flex items-center justify-center font-black text-lg shadow-xl group-hover:scale-105 transition-transform">
{conversation.worker_name.charAt(0)}
</div>
{conversation.online && (
<span className="absolute -bottom-1 -right-1 w-4 h-4 bg-emerald-500 border-4 border-white rounded-full shadow-lg" />
)}
</div>
<div>
<div className="flex items-center gap-2">
<h3 className="font-black text-slate-900 text-lg tracking-tight">{conversation.worker_name}</h3>
<span className="bg-emerald-50 text-emerald-600 p-0.5 rounded-full shadow-sm">
<ShieldCheck className="w-4 h-4" />
</span>
</div>
<div className="flex items-center space-x-2 mt-0.5">
<div className={`w-2 h-2 rounded-full ${conversation.online ? 'bg-emerald-500' : 'bg-slate-300'}`} />
<span className="text-[10px] font-black text-slate-400 uppercase tracking-widest">
{conversation.online ? 'Active Now' : 'Last seen 2h ago'}
</span>
</div>
</div>
</div>
<div className="flex items-center space-x-3">
<Link
href={`/employer/workers/${conversation.id}`}
className="p-3 bg-slate-50 text-slate-400 hover:text-[#185FA5] hover:bg-blue-50 rounded-2xl transition-all shadow-sm"
title="View Full Profile"
>
<Info className="w-5 h-5" />
</Link>
</div>
</div>
{/* Chat Messages */}
<div className="flex-1 px-6 py-8 overflow-y-auto bg-[#F8FAFC]/50 space-y-8 scroll-smooth">
<div className="flex flex-col items-center mb-10">
<div className="bg-white border border-slate-200 px-6 py-2 rounded-full shadow-sm">
<span className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Today, Dec 15</span>
</div>
</div>
{messages.map((msg, idx) => {
const isEmp = msg.sender === 'employer';
return (
<div
key={msg.id}
className={`flex w-full ${isEmp ? 'justify-end' : 'justify-start'} animate-in fade-in slide-in-from-bottom-4 duration-500`}
>
<div className={`flex flex-col ${isEmp ? 'items-end' : 'items-start'} max-w-[80%] sm:max-w-[65%]`}>
<div className={`px-6 py-4 rounded-[32px] text-[13px] font-bold leading-relaxed shadow-xl relative ${
isEmp
? 'bg-[#185FA5] text-white rounded-br-lg shadow-blue-500/10'
: 'bg-white border border-slate-100 text-slate-800 rounded-bl-lg shadow-slate-200/40'
}`}>
{msg.text}
</div>
<div className="flex items-center space-x-2 mt-2 px-2">
<span className="text-[9px] font-black text-slate-400 uppercase tracking-tighter">{msg.time}</span>
{isEmp && <CheckCircle2 className="w-3 h-3 text-emerald-500" />}
</div>
</div>
</div>
);
})}
{isTyping && (
<div className="flex w-full justify-start animate-in fade-in slide-in-from-bottom-2">
<div className="bg-white border border-slate-100 px-6 py-4 rounded-[32px] rounded-bl-lg shadow-sm flex items-center space-x-1.5">
<div className="w-1.5 h-1.5 bg-[#185FA5] rounded-full animate-bounce [animation-delay:-0.3s]"></div>
<div className="w-1.5 h-1.5 bg-[#185FA5] rounded-full animate-bounce [animation-delay:-0.15s]"></div>
<div className="w-1.5 h-1.5 bg-[#185FA5] rounded-full animate-bounce"></div>
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
{/* Quick Replies & Input */}
<div className="bg-white border-t border-slate-100 p-6 space-y-4 shadow-[0_-10px_40px_rgba(0,0,0,0.02)]">
<div className="flex items-center space-x-3 overflow-x-auto scrollbar-none pb-2">
<div className="flex-shrink-0 p-2 bg-indigo-50 text-indigo-500 rounded-xl">
<Sparkles className="w-4 h-4" />
</div>
{chips.map((chip, idx) => (
<button
key={idx}
onClick={() => sendMsg(chip)}
className="bg-slate-50 hover:bg-[#185FA5] text-slate-600 hover:text-white px-5 py-2.5 rounded-2xl text-[11px] font-black uppercase tracking-widest flex-shrink-0 transition-all border border-slate-100 hover:border-transparent hover:scale-105 active:scale-95"
>
{chip}
</button>
))}
</div>
<form onSubmit={handleFormSubmit} className="flex items-center gap-4">
<button type="button" className="p-4 bg-slate-50 text-slate-400 hover:text-slate-600 rounded-[24px] transition-all flex-shrink-0 border border-slate-100">
<Paperclip className="w-6 h-6" />
</button>
<div className="flex-1 relative group">
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Type a secure message..."
className="w-full pl-6 pr-14 py-5 bg-slate-50 border-none rounded-[32px] text-sm font-bold focus:ring-4 focus:ring-blue-100 transition-all outline-none group-focus-within:bg-white border-2 border-transparent group-focus-within:border-slate-100"
/>
<div className="absolute right-4 top-1/2 -translate-y-1/2 p-2 text-slate-300">
<Smile className="w-5 h-5" />
</div>
</div>
<button
type="submit"
disabled={!input.trim()}
className="bg-[#185FA5] hover:bg-[#144f8a] disabled:bg-slate-200 text-white p-5 rounded-[24px] transition-all shadow-xl shadow-blue-500/20 flex items-center justify-center flex-shrink-0 group hover:-translate-y-1 active:translate-y-0"
>
<Send className="w-6 h-6 group-hover:translate-x-1 group-hover:-translate-y-1 transition-transform" />
</button>
</form>
</div>
</div>
{/* Candidate Context Sidebar (Right) */}
{showProfile && (
<aside className="hidden lg:flex w-80 2xl:w-96 border-l border-slate-200 flex-col flex-shrink-0 bg-white z-20 animate-in slide-in-from-right-10 duration-500">
<div className="p-8 space-y-8 overflow-y-auto">
<div className="text-center space-y-4">
<div className="w-24 h-24 rounded-[40px] bg-gradient-to-br from-[#185FA5] to-blue-600 text-white flex items-center justify-center font-black text-3xl mx-auto shadow-2xl relative">
{conversation.worker_name.charAt(0)}
<span className="absolute -bottom-2 -right-2 bg-emerald-500 p-2 rounded-2xl border-4 border-white shadow-lg">
<ShieldCheck className="w-5 h-5 text-white" />
</span>
</div>
<div>
<h4 className="font-black text-2xl text-slate-900 tracking-tight">{conversation.worker_name}</h4>
<p className="text-[10px] font-black text-slate-400 uppercase tracking-[0.2em] mt-1">{conversation.category}</p>
</div>
</div>
<div className="grid grid-cols-2 gap-3">
<div className="bg-slate-50 p-4 rounded-3xl text-center">
<DollarSign className="w-4 h-4 text-emerald-600 mx-auto mb-1.5" />
<div className="text-[9px] font-black text-slate-400 uppercase tracking-widest">Expected</div>
<div className="text-sm font-black text-slate-900 mt-1 truncate">{conversation.salary}</div>
</div>
<div className="bg-slate-50 p-4 rounded-3xl text-center">
<MapPin className="w-4 h-4 text-blue-600 mx-auto mb-1.5" />
<div className="text-[9px] font-black text-slate-400 uppercase tracking-widest">Region</div>
<div className="text-sm font-black text-slate-900 mt-1 truncate">{conversation.nationality}</div>
</div>
</div>
<div className="space-y-4">
<h5 className="text-[10px] font-black text-slate-400 uppercase tracking-widest pl-2">Recruitment Context</h5>
<div className="space-y-3">
{[
{ label: 'Visa Status', value: 'Transferable', icon: Briefcase, color: 'text-blue-500' },
{ label: 'Medical Test', value: 'Cleared', icon: ShieldCheck, color: 'text-emerald-500' },
{ label: 'Last Active', value: 'Today, 10:15 AM', icon: Calendar, color: 'text-slate-500' }
].map((item, i) => (
<div key={i} className="flex items-center justify-between p-4 bg-slate-50/50 border border-slate-100 rounded-3xl">
<div className="flex items-center space-x-3">
<item.icon className={`w-4 h-4 ${item.color}`} />
<span className="text-[11px] font-black text-slate-500 uppercase tracking-tighter">{item.label}</span>
</div>
<span className="text-[11px] font-black text-slate-900">{item.value}</span>
</div>
))}
</div>
</div>
<div className="pt-4">
<Link
href={`/employer/workers/${conversation.id}`}
className="w-full bg-slate-900 text-white py-4 rounded-3xl text-xs font-black uppercase tracking-widest flex items-center justify-center space-x-2 shadow-xl shadow-slate-900/10 hover:-translate-y-1 transition-all"
>
<span>Full Dossier</span>
<ChevronRight className="w-4 h-4" />
</Link>
</div>
</div>
</aside>
)}
</div>
</EmployerLayout>
);
}