migrant-web/app/Http/Controllers/Employer/MessageController.php
2026-06-15 11:59:05 +05:30

275 lines
10 KiB
PHP

<?php
namespace App\Http\Controllers\Employer;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Inertia\Inertia;
use App\Models\User;
use App\Models\Conversation;
use App\Models\Message;
use App\Models\Worker;
use App\Models\JobOffer;
class MessageController extends Controller
{
private function resolveCurrentUser()
{
$sess = session('user');
$sessId = is_array($sess) ? ($sess['id'] ?? null) : ($sess->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', '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',
'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', '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',
'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', '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',
'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();
// Dispatch push notification to worker
$worker = $conv->worker;
if ($worker && $worker->fcm_token) {
\App\Services\FCMService::sendPushNotification(
$worker->fcm_token,
"New Message from " . ($user->name ?? "Employer"),
$request->text ?: "Sent an attachment",
[
'conversation_id' => $conv->id,
'sender_type' => 'employer',
'sender_id' => $user->id,
]
);
}
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]);
}
}