diff --git a/app/Http/Controllers/Api/EmployerMessageController.php b/app/Http/Controllers/Api/EmployerMessageController.php index 52152d6..8cdea97 100644 --- a/app/Http/Controllers/Api/EmployerMessageController.php +++ b/app/Http/Controllers/Api/EmployerMessageController.php @@ -166,6 +166,8 @@ public function getMessages(Request $request, $id) '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(), + 'attachment_url' => $msg->attachment_path ? asset('storage/' . $msg->attachment_path) : null, + 'attachment_type' => $msg->attachment_type, ]; }); @@ -209,7 +211,8 @@ public function sendMessage(Request $request, $id) $employer = $request->attributes->get('employer'); $validator = Validator::make($request->all(), [ - 'text' => 'required|string|max:1000', + '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 ]); if ($validator->fails()) { @@ -232,13 +235,32 @@ public function sendMessage(Request $request, $id) ], 404); } + $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 = null; - DB::transaction(function () use ($conv, $employer, $request, &$message) { + DB::transaction(function () use ($conv, $employer, $request, $attachmentPath, $attachmentType, &$message) { $message = Message::create([ 'conversation_id' => $conv->id, 'sender_type' => 'employer', 'sender_id' => $employer->id, 'text' => $request->text, + 'attachment_path' => $attachmentPath, + 'attachment_type' => $attachmentType, ]); // Touch conversation updated_at for sorting @@ -281,6 +303,8 @@ public function sendMessage(Request $request, $id) 'text' => $message->text, 'time' => $message->created_at->format('g:i A') . ' Today', 'created_at' => $message->created_at->toISOString(), + 'attachment_url' => $message->attachment_path ? asset('storage/' . $message->attachment_path) : null, + 'attachment_type' => $message->attachment_type, ] ] ], 201); diff --git a/app/Models/Message.php b/app/Models/Message.php index e58a1d1..59ba3ec 100644 --- a/app/Models/Message.php +++ b/app/Models/Message.php @@ -14,11 +14,15 @@ class Message extends Model 'sender_type', 'sender_id', 'text', + 'attachment_path', + 'attachment_type', 'is_read', + 'read_at', ]; protected $casts = [ 'is_read' => 'boolean', + 'read_at' => 'datetime', ]; public function conversation() diff --git a/bootstrap/app.php b/bootstrap/app.php index 8ab31a2..278de26 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -24,5 +24,10 @@ ]); }) ->withExceptions(function (Exceptions $exceptions): void { - // + $exceptions->shouldRenderJsonWhen(function (\Illuminate\Http\Request $request, \Throwable $e) { + if ($request->is('api/*')) { + return true; + } + return $request->expectsJson(); + }); })->create(); diff --git a/config/app.php b/config/app.php index 423eed5..b5d37f8 100644 --- a/config/app.php +++ b/config/app.php @@ -65,7 +65,7 @@ | */ - 'timezone' => 'UTC', + 'timezone' => env('APP_TIMEZONE', 'Asia/Dubai'), /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2026_06_01_154918_add_attachment_fields_to_messages_table.php b/database/migrations/2026_06_01_154918_add_attachment_fields_to_messages_table.php new file mode 100644 index 0000000..eae256e --- /dev/null +++ b/database/migrations/2026_06_01_154918_add_attachment_fields_to_messages_table.php @@ -0,0 +1,29 @@ +string('attachment_path')->nullable()->after('text'); + $table->string('attachment_type')->nullable()->after('attachment_path'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('messages', function (Blueprint $table) { + $table->dropColumn(['attachment_path', 'attachment_type']); + }); + } +}; diff --git a/database/migrations/2026_06_01_160843_make_text_nullable_in_messages_table.php b/database/migrations/2026_06_01_160843_make_text_nullable_in_messages_table.php new file mode 100644 index 0000000..f554b84 --- /dev/null +++ b/database/migrations/2026_06_01_160843_make_text_nullable_in_messages_table.php @@ -0,0 +1,28 @@ +text('text')->nullable()->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('messages', function (Blueprint $table) { + $table->text('text')->nullable(false)->change(); + }); + } +}; diff --git a/public/uploads/documents/1780250108_passport_mds11.png b/public/uploads/documents/1780250108_passport_mds11.png new file mode 100644 index 0000000..ae18a13 Binary files /dev/null and b/public/uploads/documents/1780250108_passport_mds11.png differ diff --git a/public/uploads/documents/1780250108_visa_mds.png b/public/uploads/documents/1780250108_visa_mds.png new file mode 100644 index 0000000..4b9331f Binary files /dev/null and b/public/uploads/documents/1780250108_visa_mds.png differ