import React, { useState, useEffect, useRef } from 'react';
import { Head, Link, router } from '@inertiajs/react';
import EmployerLayout from '../../../Layouts/EmployerLayout';
import { useTranslation } from '../../../lib/LanguageContext';
import {
Send,
ArrowLeft,
CheckCircle2,
Globe2,
DollarSign,
Sparkles,
MoreVertical,
Phone,
Video,
Paperclip,
Search,
Info,
Calendar,
Briefcase,
ShieldCheck,
ChevronRight,
MapPin,
Smile,
X,
MessageSquare,
Eye,
UploadCloud,
FileText,
Mic,
Square,
Clock
} from 'lucide-react';
import { toast } from 'sonner';
export default function Show({ conversation, initialMessages, conversations = [] }) {
const { t } = useTranslation();
const [messages, setMessages] = useState(initialMessages || []);
const [input, setInput] = useState('');
const [isTyping, setIsTyping] = useState(false);
const [searchTerm, setSearchTerm] = useState('');
const [showHireConfirmModal, setShowHireConfirmModal] = useState(false);
const [showAttachmentModal, setShowAttachmentModal] = useState(false);
const [uploadedFiles, setUploadedFiles] = useState([]);
const [isRecording, setIsRecording] = useState(false);
const mediaRecorderRef = useRef(null);
const audioChunksRef = useRef([]);
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
};
useEffect(() => {
scrollToBottom();
}, [messages, isTyping]);
useEffect(() => {
setMessages(initialMessages || []);
}, [initialMessages]);
// Simulate typing indicator when conversation opens
useEffect(() => {
setIsTyping(true);
const timer = setTimeout(() => setIsTyping(false), 2500);
return () => clearTimeout(timer);
}, [conversation.id]);
const filteredConversations = (conversations || []).filter(c =>
c.worker_name.toLowerCase().includes(searchTerm.toLowerCase())
);
const sendFile = (file) => {
if (!file) return;
const isImage = file.type.startsWith('image/');
const isAudio = file.type.startsWith('audio/');
const type = isImage ? 'image' : (isAudio ? 'voice' : 'document');
// Optimistically update message feed
const newMsg = {
id: Date.now(),
sender: 'employer',
text: file.name,
time: t('just_now', 'Just Now'),
read: false,
attachment_url: URL.createObjectURL(file),
attachment_type: type
};
setMessages(prev => [...prev, newMsg]);
router.post(`/employer/messages/${conversation.id}/send`, {
text: file.name,
file: file
}, {
preserveScroll: true,
onSuccess: () => {
toast.success(t('file_sent_success', 'File and notification sent successfully!'));
setShowAttachmentModal(false);
},
onError: (err) => {
toast.error(t('file_sent_error', 'Failed to upload file attachment.'));
}
});
};
const sendMsg = (text) => {
if (!text.trim()) return;
// Optimistically update message feed
const newMsg = {
id: Date.now(),
sender: 'employer',
text: text,
time: t('just_now', 'Just Now'),
read: false
};
setMessages(prev => [...prev, newMsg]);
setInput('');
const isLookingJobQuery = text.toLowerCase().includes('looking') && text.toLowerCase().includes('job');
router.post(`/employer/messages/${conversation.id}/send`, {
text: text
}, {
preserveScroll: true,
onSuccess: () => {
router.reload({ preserveScroll: true });
}
});
};
const handleFormSubmit = (e) => {
e.preventDefault();
sendMsg(input);
};
const handleFileUpload = (e) => {
const file = e.target.files[0];
if (!file) return;
sendFile(file);
};
const startRecording = async () => {
try {
// Check browser permission status if query API is supported
if (navigator.permissions && navigator.permissions.query) {
try {
const permissionStatus = await navigator.permissions.query({ name: 'microphone' });
if (permissionStatus.state === 'denied') {
toast.error(t('microphone_blocked', 'Microphone access is blocked. Please enable microphone permissions in your browser settings.'));
return;
}
} catch (pe) {
// Ignore query check failures if name is not supported in some browsers
}
}
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
audioChunksRef.current = [];
const recorder = new MediaRecorder(stream);
recorder.ondataavailable = (e) => {
if (e.data.size > 0) {
audioChunksRef.current.push(e.data);
}
};
recorder.onstop = () => {
const audioBlob = new Blob(audioChunksRef.current, { type: 'audio/webm' });
const file = new File([audioBlob], `voice_${Date.now()}.webm`, { type: 'audio/webm' });
sendFile(file);
// Stop all tracks to release mic
stream.getTracks().forEach(track => track.stop());
};
mediaRecorderRef.current = recorder;
recorder.start();
setIsRecording(true);
toast.info(t('recording_started', 'Recording voice message... Click microphone again to stop.'));
} catch (err) {
console.error(err);
if (err.name === 'NotAllowedError' || err.name === 'PermissionDeniedError') {
toast.error(t('microphone_permission_denied', 'Permission to access the microphone was denied. Please allow microphone access in your browser settings.'));
} else if (err.name === 'NotFoundError' || err.name === 'DevicesNotFoundError') {
toast.error(t('microphone_not_found', 'No microphone device was detected on your system.'));
} else {
toast.error(t('microphone_access_error', 'Could not access the microphone. Please check your system settings.'));
}
}
};
const handleMarkHired = () => {
router.post(`/employer/workers/${conversation.worker_id}/mark-hired`, {}, {
preserveScroll: true,
onSuccess: () => {
toast.success(t('hire_request_sent', 'Hiring request sent successfully!'), {
description: t('hire_request_sent_desc', 'Awaiting worker confirmation of the hiring offer.')
});
router.reload();
}
});
};
const stopRecording = () => {
if (mediaRecorderRef.current && isRecording) {
mediaRecorderRef.current.stop();
setIsRecording(false);
}
};
const chips = [
t('chip_salary', "What is your final expected salary?"),
t('chip_visa', "Can you transfer your visa immediately?")
];
return (
{t('attach_documents_desc', 'Upload sponsor papers, employment agreements, or work descriptions to review securely.')}
{t('confirm_hire_desc', 'Verify this worker with your needs and make sure to hire this worker. If hired, you can view this worker in the Hired Workers page.')}