From 2e89215c9f9a8aec12d3138a6e36686b48dfafc8 Mon Sep 17 00:00:00 2001 From: mohanmd Date: Tue, 23 Jun 2026 23:52:13 +0530 Subject: [PATCH] dashboard api for employer --- .../Api/EmployerProfileController.php | 31 ++++++- public/swagger.json | 84 +++++++++++++++++++ resources/js/Pages/Admin/Workers/Index.jsx | 72 ++++++++-------- resources/js/Pages/Employer/Workers/Show.jsx | 81 +++++++++--------- tests/Feature/EmployerProfileApiTest.php | 36 +++++++- vite.config.js | 2 +- 6 files changed, 226 insertions(+), 80 deletions(-) diff --git a/app/Http/Controllers/Api/EmployerProfileController.php b/app/Http/Controllers/Api/EmployerProfileController.php index 62ce416..e2c1559 100644 --- a/app/Http/Controllers/Api/EmployerProfileController.php +++ b/app/Http/Controllers/Api/EmployerProfileController.php @@ -54,6 +54,17 @@ public function getProfile(Request $request) 'occupation' => $profile->emirates_id_occupation, 'employer' => $profile->emirates_id_employer, 'issuing_place' => $profile->emirates_id_issue_place, + 'emirates_id' => [ + 'emirates_id_number' => $profile->emirates_id_number, + 'name' => $profile->emirates_id_name, + 'date_of_birth' => $profile->emirates_id_dob, + 'nationality' => $profile->nationality, + 'issue_date' => $profile->emirates_id_issue_date, + 'expiry_date' => $profile->emirates_id_expiry, + 'employer' => $profile->emirates_id_employer, + 'issue_place' => $profile->emirates_id_issue_place, + 'occupation' => $profile->emirates_id_occupation, + ], ]; return response()->json([ @@ -270,6 +281,17 @@ public function updateProfile(Request $request) 'occupation' => $profile->emirates_id_occupation, 'employer' => $profile->emirates_id_employer, 'issuing_place' => $profile->emirates_id_issue_place, + 'emirates_id' => [ + 'emirates_id_number' => $profile->emirates_id_number, + 'name' => $profile->emirates_id_name, + 'date_of_birth' => $profile->emirates_id_dob, + 'nationality' => $profile->nationality, + 'issue_date' => $profile->emirates_id_issue_date, + 'expiry_date' => $profile->emirates_id_expiry, + 'employer' => $profile->emirates_id_employer, + 'issue_place' => $profile->emirates_id_issue_place, + 'occupation' => $profile->emirates_id_occupation, + ], ]; return response()->json([ @@ -309,7 +331,14 @@ public function getDashboard(Request $request) $savedCandidates = \App\Models\Shortlist::where('employer_id', $employer->id)->count(); - $totalWorkers = \App\Models\Worker::where('status', 'active')->count(); + $totalWorkers = \App\Models\Worker::with('documents') + ->where('status', '!=', 'Hired') + ->where('status', '!=', 'hidden') + ->get() + ->filter(function ($w) { + return !str_contains(strtolower($w->passport_status), 'pending'); + }) + ->count(); // Resolve plan $sub = \Illuminate\Support\Facades\DB::table('subscriptions') diff --git a/public/swagger.json b/public/swagger.json index 8b48739..284d8cb 100644 --- a/public/swagger.json +++ b/public/swagger.json @@ -3897,6 +3897,48 @@ "issuing_place": { "type": "string", "example": "Dubai" + }, + "emirates_id": { + "type": "object", + "description": "Consolidated Emirates ID details.", + "properties": { + "emirates_id_number": { + "type": "string", + "example": "784-1988-5310327-2" + }, + "name": { + "type": "string", + "example": "Ahmad Bin Ahmed" + }, + "date_of_birth": { + "type": "string", + "example": "1990-01-01" + }, + "nationality": { + "type": "string", + "example": "Emirati" + }, + "issue_date": { + "type": "string", + "example": "2023-04-11" + }, + "expiry_date": { + "type": "string", + "example": "2028-04-11" + }, + "employer": { + "type": "string", + "example": "Federal Authority" + }, + "issue_place": { + "type": "string", + "example": "Abu Dhabi" + }, + "occupation": { + "type": "string", + "example": "Manager" + } + } } } } @@ -4114,6 +4156,48 @@ "issuing_place": { "type": "string", "example": "Dubai" + }, + "emirates_id": { + "type": "object", + "description": "Consolidated Emirates ID details.", + "properties": { + "emirates_id_number": { + "type": "string", + "example": "784-1988-5310327-2" + }, + "name": { + "type": "string", + "example": "Ahmad Bin Ahmed" + }, + "date_of_birth": { + "type": "string", + "example": "1990-01-01" + }, + "nationality": { + "type": "string", + "example": "Emirati" + }, + "issue_date": { + "type": "string", + "example": "2023-04-11" + }, + "expiry_date": { + "type": "string", + "example": "2028-04-11" + }, + "employer": { + "type": "string", + "example": "Federal Authority" + }, + "issue_place": { + "type": "string", + "example": "Abu Dhabi" + }, + "occupation": { + "type": "string", + "example": "Manager" + } + } } } } diff --git a/resources/js/Pages/Admin/Workers/Index.jsx b/resources/js/Pages/Admin/Workers/Index.jsx index a34142c..a1ae972 100644 --- a/resources/js/Pages/Admin/Workers/Index.jsx +++ b/resources/js/Pages/Admin/Workers/Index.jsx @@ -805,10 +805,14 @@ export default function WorkerManagement({ workers }) { Document Type {safeRender(passportDoc.ocr_data?.document_type)} -
- Personal Number - {safeRender(passportDoc.ocr_data?.personal_number)} -
+ {passportDoc.ocr_data?.personal_number && + passportDoc.ocr_data?.personal_number !== 'N/A' && + passportDoc.ocr_data?.personal_number !== (passportDoc.ocr_data?.passport_number || passportDoc.number) && ( +
+ Personal Number + {safeRender(passportDoc.ocr_data?.personal_number)} +
+ )} {passportDoc.file_path && (
@@ -840,6 +844,16 @@ export default function WorkerManagement({ workers }) {
); } + + const sponsorObj = visaDoc.ocr_data?.sponsor; + const isSponsorObj = sponsorObj && typeof sponsorObj === 'object' && !Array.isArray(sponsorObj); + const sponsorName = isSponsorObj + ? (sponsorObj.name || sponsorObj.sponsor_name || sponsorObj.full_name) + : (visaDoc.ocr_data?.sponsor_name || (typeof sponsorObj === 'string' ? sponsorObj : null)); + const sponsorMobile = isSponsorObj + ? (sponsorObj.mobile || sponsorObj.mobile_number || sponsorObj.phone) + : null; + return (
@@ -851,22 +865,12 @@ export default function WorkerManagement({ workers }) { UID No {safeRender(visaDoc.ocr_data?.uid_no)}
-
- File Number - {safeRender(visaDoc.ocr_data?.file_number || visaDoc.number)} -
-
- ID Number - {safeRender(visaDoc.ocr_data?.id_number)} -
-
- Full Name - {safeRender(visaDoc.ocr_data?.full_name)} -
-
- Name - {safeRender(visaDoc.ocr_data?.name)} -
+ {visaDoc.ocr_data?.id_number && visaDoc.ocr_data?.id_number !== 'N/A' && ( +
+ ID Number + {safeRender(visaDoc.ocr_data?.id_number)} +
+ )}
Visa Type {safeRender(visaDoc.ocr_data?.visa_type)} @@ -875,10 +879,18 @@ export default function WorkerManagement({ workers }) { Profession {safeRender(visaDoc.ocr_data?.profession)}
-
- Sponsor Name - {safeRender(visaDoc.ocr_data?.sponsor_name)} -
+ {sponsorName && ( +
+ Sponsor Name + {safeRender(sponsorName)} +
+ )} + {sponsorMobile && ( +
+ Sponsor Mobile + {safeRender(sponsorMobile)} +
+ )}
Nationality @@ -888,14 +900,6 @@ export default function WorkerManagement({ workers }) { Country {safeRender(visaDoc.ocr_data?.country)}
-
- Passport No - {safeRender(visaDoc.ocr_data?.passport_no)} -
-
- Passport Number - {safeRender(visaDoc.ocr_data?.passport_number)} -
Date of Birth {safeRender(visaDoc.ocr_data?.date_of_birth)} @@ -917,10 +921,6 @@ export default function WorkerManagement({ workers }) { {safeRender(visaDoc.ocr_data?.expiry_date || visaDoc.expiry_date)}
-
- Accompanied By - {safeRender(visaDoc.ocr_data?.accompanied_by)} -
Document Type {safeRender(visaDoc.ocr_data?.document_type)} diff --git a/resources/js/Pages/Employer/Workers/Show.jsx b/resources/js/Pages/Employer/Workers/Show.jsx index 97772df..01feb3b 100644 --- a/resources/js/Pages/Employer/Workers/Show.jsx +++ b/resources/js/Pages/Employer/Workers/Show.jsx @@ -564,46 +564,49 @@ export default function Show({ worker }) {
- {visaDoc.ocr_data ? ( -
-
-
{t('full_name', 'Full Name')}
-
{safeRender(visaDoc.ocr_data.name)}
+ {visaDoc.ocr_data ? (() => { + const sponsorObj = visaDoc.ocr_data?.sponsor; + const isSponsorObj = sponsorObj && typeof sponsorObj === 'object' && !Array.isArray(sponsorObj); + const sponsorName = isSponsorObj + ? (sponsorObj.name || sponsorObj.sponsor_name || sponsorObj.full_name) + : (visaDoc.ocr_data?.sponsor_name || (typeof sponsorObj === 'string' ? sponsorObj : null)); + const sponsorMobile = isSponsorObj + ? (sponsorObj.mobile || sponsorObj.mobile_number || sponsorObj.phone) + : null; + + return ( +
+
+
{t('profession', 'Profession')}
+
{safeRender(visaDoc.ocr_data.profession || worker.visa_status)}
+
+ {sponsorName && ( +
+
{t('sponsor', 'Sponsor')}
+
{safeRender(sponsorName)}
+
+ )} + {sponsorMobile && ( +
+
{t('sponsor_mobile', 'Sponsor Mobile')}
+
{safeRender(sponsorMobile)}
+
+ )} +
+
{t('place_of_issue', 'Place of Issue')}
+
{safeRender(visaDoc.ocr_data.place_of_issue)}
+
+
+
{t('issue_date', 'Date of Issue')}
+
{safeRender(visaDoc.ocr_data.issue_date || visaDoc.issue_date)}
+
+
+
{t('expiry_date', 'Date of Expiry')}
+
{safeRender(visaDoc.ocr_data.expiry_date || visaDoc.expiry_date)}
+
-
-
{t('file_number', 'File Number')}
-
{safeRender(visaDoc.ocr_data.file_number || visaDoc.number)}
-
-
-
{t('profession', 'Profession')}
-
{safeRender(visaDoc.ocr_data.profession || worker.visa_status)}
-
-
-
{t('sponsor', 'Sponsor')}
-
{safeRender(visaDoc.ocr_data.sponsor || visaDoc.ocr_data.sponsor_name)}
-
-
-
{t('passport_number', 'Passport Number')}
-
{safeRender(visaDoc.ocr_data.passport_number)}
-
-
-
{t('place_of_issue', 'Place of Issue')}
-
{safeRender(visaDoc.ocr_data.place_of_issue)}
-
-
-
{t('issue_date', 'Date of Issue')}
-
{safeRender(visaDoc.ocr_data.issue_date || visaDoc.issue_date)}
-
-
-
{t('expiry_date', 'Date of Expiry')}
-
{safeRender(visaDoc.ocr_data.expiry_date || visaDoc.expiry_date)}
-
-
-
{t('accompanied_by', 'Accompanied By')}
-
{safeRender(visaDoc.ocr_data.accompanied_by)}
-
-
- ) : ( + ); + })() : (
{t('document_id', 'Document ID')}
diff --git a/tests/Feature/EmployerProfileApiTest.php b/tests/Feature/EmployerProfileApiTest.php index a7adec4..6ca7a7b 100644 --- a/tests/Feature/EmployerProfileApiTest.php +++ b/tests/Feature/EmployerProfileApiTest.php @@ -57,6 +57,7 @@ public function test_employer_can_get_profile() 'address', 'notifications', 'verification_status', + 'emirates_id', ] ] ]); @@ -91,6 +92,7 @@ public function test_employer_can_update_profile() 'phone', 'address', 'notifications', + 'emirates_id', ] ] ]); @@ -147,6 +149,17 @@ public function test_employer_can_update_profile_with_emirates_id_fields() 'card_number' => '151023946', 'full_name' => 'Mohammad Jobaier Mohammad Abul Kalam', 'gender' => 'M', + 'emirates_id' => [ + 'emirates_id_number' => '784-1987-5493842-5', + 'name' => 'Mohammad Jobaier Mohammad Abul Kalam', + 'date_of_birth' => '14/04/1987', + 'nationality' => 'Bangladesh', + 'issue_date' => '12/12/2025', + 'expiry_date' => '11/12/2027', + 'employer' => 'Msj International Technical Services L.L.C UAE', + 'issue_place' => 'Dubai', + 'occupation' => 'Electrician', + ] ] ] ]); @@ -248,23 +261,40 @@ public function test_employer_dashboard_returns_total_workers_active() \App\Models\Worker::query()->delete(); // Create 3 active workers - \App\Models\Worker::create([ + $w1 = \App\Models\Worker::create([ 'name' => 'Active 1', 'email' => 'a1@test.com', 'phone' => '+971501110001', 'password' => bcrypt('password'), 'status' => 'active', 'nationality' => 'Indian', 'preferred_location' => 'Dubai', 'age' => 25, 'salary' => 1500, 'experience' => '3 Years', 'availability' => 'Immediate', 'religion' => 'Christian', 'bio' => 'experienced worker', + 'verified' => true, ]); - \App\Models\Worker::create([ + \App\Models\WorkerDocument::create([ + 'worker_id' => $w1->id, 'type' => 'passport', 'number' => 'P111', + 'issue_date' => '2020-01-01', 'expiry_date' => '2030-01-01', + ]); + + $w2 = \App\Models\Worker::create([ 'name' => 'Active 2', 'email' => 'a2@test.com', 'phone' => '+971501110002', 'password' => bcrypt('password'), 'status' => 'active', 'nationality' => 'Indian', 'preferred_location' => 'Dubai', 'age' => 26, 'salary' => 1500, 'experience' => '3 Years', 'availability' => 'Immediate', 'religion' => 'Christian', 'bio' => 'experienced worker', + 'verified' => true, ]); - \App\Models\Worker::create([ + \App\Models\WorkerDocument::create([ + 'worker_id' => $w2->id, 'type' => 'passport', 'number' => 'P222', + 'issue_date' => '2020-01-01', 'expiry_date' => '2030-01-01', + ]); + + $w3 = \App\Models\Worker::create([ 'name' => 'Active 3', 'email' => 'a3@test.com', 'phone' => '+971501110003', 'password' => bcrypt('password'), 'status' => 'active', 'nationality' => 'Indian', 'preferred_location' => 'Dubai', 'age' => 27, 'salary' => 1500, 'experience' => '3 Years', 'availability' => 'Immediate', 'religion' => 'Christian', 'bio' => 'experienced worker', + 'verified' => true, + ]); + \App\Models\WorkerDocument::create([ + 'worker_id' => $w3->id, 'type' => 'passport', 'number' => 'P333', + 'issue_date' => '2020-01-01', 'expiry_date' => '2030-01-01', ]); // Create 2 inactive/hidden workers diff --git a/vite.config.js b/vite.config.js index 69084ca..fa54835 100644 --- a/vite.config.js +++ b/vite.config.js @@ -23,7 +23,7 @@ export default defineConfig({ port: 5173, cors: true, hmr: { - host: '192.168.0.166', + host: '192.168.29.131', }, watch: { ignored: ['**/storage/framework/views/**'],