migrant-web/app/Http/Controllers/Api/WorkerMessageController.php

211 lines
7.5 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Conversation;
use App\Models\Message;
use App\Models\Worker;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
class WorkerMessageController extends Controller
{
/**
* Get all conversations for the authorized worker.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function getConversations(Request $request)
{
/** @var Worker $worker */
$worker = $request->attributes->get('worker');
try {
$dbConversations = Conversation::where('worker_id', $worker->id)
->with(['employer.employerProfile', 'messages'])
->latest('updated_at')
->get();
$conversations = $dbConversations->map(function ($conv) {
$lastMsg = $conv->messages->last();
// Calculate unread count (messages sent by employer that are not read by worker)
$unreadCount = $conv->messages->filter(function ($msg) {
return $msg->sender_type === 'employer' && is_null($msg->read_at);
})->count();
return [
'id' => $conv->id,
'employer_id' => $conv->employer_id,
'employer_name' => $conv->employer->name ?? 'Employer',
'company_name' => $conv->employer->employerProfile->company_name ?? 'Individual Employer',
'last_message' => $lastMsg->text ?? 'No messages yet.',
'unread_count' => $unreadCount,
'sent_at' => $lastMsg ? $lastMsg->created_at->diffForHumans() : 'Just now',
'updated_at' => $conv->updated_at->toISOString(),
];
});
return response()->json([
'success' => true,
'data' => [
'conversations' => $conversations
]
], 200);
} catch (\Exception $e) {
logger()->error('Mobile Worker Get Conversations Failure: ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'An error occurred while fetching conversations.',
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
], 500);
}
}
/**
* Get messages in a single conversation and mark unread incoming messages as read.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function getMessages(Request $request, $id)
{
/** @var Worker $worker */
$worker = $request->attributes->get('worker');
try {
$conv = Conversation::where('worker_id', $worker->id)
->where('id', $id)
->with(['employer.employerProfile', 'messages'])
->first();
if (!$conv) {
return response()->json([
'success' => false,
'message' => 'Conversation not found.'
], 404);
}
// Mark incoming employer messages in this conversation as read
Message::where('conversation_id', $conv->id)
->where('sender_type', 'employer')
->whereNull('read_at')
->update(['read_at' => now()]);
$messages = $conv->messages->map(function ($msg) {
return [
'id' => $msg->id,
'sender_type' => $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')),
'read_at' => $msg->read_at ? $msg->read_at->toISOString() : null,
'created_at' => $msg->created_at->toISOString(),
];
});
$conversationDetail = [
'id' => $conv->id,
'employer_name' => $conv->employer->name ?? 'Employer',
'company_name' => $conv->employer->employerProfile->company_name ?? 'Individual Employer',
];
return response()->json([
'success' => true,
'data' => [
'conversation' => $conversationDetail,
'messages' => $messages
]
], 200);
} catch (\Exception $e) {
logger()->error('Mobile Worker Get Messages Failure: ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'An error occurred while fetching messages.',
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
], 500);
}
}
/**
* Send a reply message from the worker to the employer.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function sendMessage(Request $request, $id)
{
/** @var Worker $worker */
$worker = $request->attributes->get('worker');
$validator = Validator::make($request->all(), [
'text' => 'required|string|max:1000',
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => 'Validation error.',
'errors' => $validator->errors()
], 422);
}
try {
$conv = Conversation::where('worker_id', $worker->id)
->where('id', $id)
->first();
if (!$conv) {
return response()->json([
'success' => false,
'message' => 'Conversation not found.'
], 404);
}
$message = null;
DB::transaction(function () use ($conv, $worker, $request, &$message) {
$message = Message::create([
'conversation_id' => $conv->id,
'sender_type' => 'worker',
'sender_id' => $worker->id,
'text' => $request->text,
]);
// Touch conversation updated_at for sorting
$conv->touch();
});
return response()->json([
'success' => true,
'message' => 'Message sent successfully.',
'data' => [
'message' => [
'id' => $message->id,
'sender_type' => $message->sender_type,
'text' => $message->text,
'time' => $message->created_at->format('g:i A') . ' Today',
'created_at' => $message->created_at->toISOString(),
]
]
], 201);
} catch (\Exception $e) {
logger()->error('Mobile Worker Send Message Failure: ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'An error occurred while sending the message.',
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
], 500);
}
}
}