id ?? null); if (!$sessId) { $user = User::where('role', 'employer')->first(); if ($user) { session(['user' => (object)[ 'id' => $user->id, 'name' => $user->name, 'email' => $user->email, 'role' => 'employer', 'subscription_status' => $user->subscription_status ?? 'active', ]]); return $user; } } else { return User::find($sessId); } return null; } public static function processWorkerResponse($conv, $worker, $text) { $replyText = strtolower(trim($text)); if ($replyText === 'yes' || $replyText === 'no') { // Find the last message sent by the employer in this conversation (excluding the current worker message) $lastEmployerMessage = Message::where('conversation_id', $conv->id) ->where('sender_type', 'employer') ->latest() ->first(); if ($lastEmployerMessage) { $questionText = strtolower($lastEmployerMessage->text); $isLookingJobQuestion = str_contains($questionText, 'looking job') || str_contains($questionText, 'looking for a job') || str_contains($questionText, 'looking for job') || str_contains($questionText, 'are you looking'); if ($isLookingJobQuestion) { if ($replyText === 'yes') { // S6 Outcome: Update status as Hired $worker->update([ 'status' => 'Hired', 'availability' => 'Hired' ]); // Accept existing direct offer or application $offer = JobOffer::where('employer_id', $conv->employer_id) ->where('worker_id', $worker->id) ->first(); if ($offer) { $offer->update(['status' => 'accepted']); } else { JobOffer::create([ 'employer_id' => $conv->employer_id, 'worker_id' => $worker->id, 'work_date' => now()->format('Y-m-d'), 'location' => 'Dubai', 'salary' => $worker->salary ?: 2000, 'notes' => 'Hired via chat agreement.', 'status' => 'accepted', ]); } } else if ($replyText === 'no') { // S5 Outcome: Update status as Hidden (Auto-Hidden from search) $worker->update([ 'status' => 'hidden', 'availability' => 'Not Available' ]); } } } } } public function index(Request $request) { $user = $this->resolveCurrentUser(); if (!$user) { return redirect()->route('employer.login'); } $dbConversations = Conversation::where('employer_id', $user->id) ->with(['worker.category', 'messages']) ->latest('updated_at') ->get(); $conversations = $dbConversations->map(function ($conv) { $lastMsg = $conv->messages->last(); return [ 'id' => $conv->id, 'worker_id' => $conv->worker_id, 'worker_name' => $conv->worker->name ?? 'Candidate', 'category' => $conv->worker->category->name ?? 'General Helper', 'worker_status' => strtolower($conv->worker->status ?? 'active'), 'last_message' => $lastMsg->text ?? 'No messages yet.', 'unread' => $lastMsg ? ($lastMsg->sender_type === 'worker' && is_null($lastMsg->read_at)) : false, 'online' => true, 'sent_at' => $lastMsg ? $lastMsg->created_at->diffForHumans() : 'Just now', ]; })->toArray(); return Inertia::render('Employer/Messages/Index', [ 'conversations' => $conversations, ]); } public function show($id) { $user = $this->resolveCurrentUser(); if (!$user) { return redirect()->route('employer.login'); } $dbConversations = Conversation::where('employer_id', $user->id) ->with(['worker.category', 'messages']) ->latest('updated_at') ->get(); $conversations = $dbConversations->map(function ($conv) { $lastMsg = $conv->messages->last(); return [ 'id' => $conv->id, 'worker_id' => $conv->worker_id, 'worker_name' => $conv->worker->name ?? 'Candidate', 'category' => $conv->worker->category->name ?? 'General Helper', 'worker_status' => strtolower($conv->worker->status ?? 'active'), 'last_message' => $lastMsg->text ?? 'No messages yet.', 'unread' => $lastMsg ? ($lastMsg->sender_type === 'worker' && is_null($lastMsg->read_at)) : false, 'online' => true, 'sent_at' => $lastMsg ? $lastMsg->created_at->diffForHumans() : 'Just now', ]; })->toArray(); $activeConv = Conversation::where('employer_id', $user->id) ->where('id', $id) ->with(['worker.category', 'messages']) ->firstOrFail(); // Mark incoming messages as read Message::where('conversation_id', $activeConv->id) ->where('sender_type', 'worker') ->whereNull('read_at') ->update(['read_at' => now()]); $conversationData = [ 'id' => $activeConv->id, 'worker_id' => $activeConv->worker_id, 'worker_name' => $activeConv->worker->name ?? 'Candidate', 'category' => $activeConv->worker->category->name ?? 'General Helper', 'worker_status' => strtolower($activeConv->worker->status ?? 'active'), 'online' => true, 'salary' => ($activeConv->worker->expected_salary ?? 2000) . ' AED', 'nationality' => $activeConv->worker->nationality ?? 'Unknown', ]; $initialMessages = $activeConv->messages->map(function ($msg) { return [ 'id' => $msg->id, 'sender' => $msg->sender_type, // employer or worker 'text' => $msg->text, 'time' => $msg->created_at->format('g:i A') . ($msg->created_at->isToday() ? ' Today' : ' ' . $msg->created_at->format('M d')), 'attachment_url' => $msg->attachment_path ? asset('storage/' . $msg->attachment_path) : null, 'attachment_type' => $msg->attachment_type, ]; })->toArray(); return Inertia::render('Employer/Messages/Show', [ 'conversations' => $conversations, 'conversation' => $conversationData, 'initialMessages' => $initialMessages, ]); } public function send(Request $request, $id) { $user = $this->resolveCurrentUser(); if (!$user) { return back()->withErrors(['general' => 'User session not found.']); } $request->validate([ 'text' => 'required_without:file|string|max:1000|nullable', 'file' => 'nullable|file|mimes:jpg,jpeg,png,pdf,mp3,wav,m4a,ogg,webm,mp4,aac,3gp,amr|max:10240', // 10MB limit ]); $conv = Conversation::where('employer_id', $user->id)->where('id', $id)->firstOrFail(); $attachmentPath = null; $attachmentType = null; if ($request->hasFile('file')) { $file = $request->file('file'); $attachmentPath = $file->store('chat_attachments', 'public'); $mime = $file->getMimeType(); if (str_starts_with($mime, 'image/')) { $attachmentType = 'image'; } elseif (str_starts_with($mime, 'audio/')) { $attachmentType = 'voice'; } else { $attachmentType = 'document'; } } $message = Message::create([ 'conversation_id' => $conv->id, 'sender_type' => 'employer', 'sender_id' => $user->id, 'text' => $request->text, 'attachment_path' => $attachmentPath, 'attachment_type' => $attachmentType, ]); // Touch conversation updated_at for sorting $conv->touch(); return back(); } /** * Start or load a conversation with a specific worker. * * @param int $workerId * @return \Illuminate\Http\RedirectResponse */ public function startConversation($workerId) { $user = $this->resolveCurrentUser(); if (!$user) { return redirect()->route('employer.login'); } // Find or create conversation $conv = Conversation::firstOrCreate([ 'employer_id' => $user->id, 'worker_id' => $workerId, ]); return redirect()->route('employer.messages.show', ['id' => $conv->id]); } }