attributes->get('employer'); try { $profile = $employer->employerProfile; if (!$profile) { $profile = EmployerProfile::create([ 'user_id' => $employer->id, 'phone' => '+971 50 123 4567', 'address' => 'Dubai, UAE', 'verification_status' => 'approved', ]); } $employerProfile = [ 'name' => $employer->name, 'email' => $employer->email, 'phone' => $profile->phone, 'address' => $profile->address, 'notifications' => (bool)($profile->notifications ?? true), 'verification_status' => $profile->verification_status ?? 'approved', 'emirates_id_number' => $profile->emirates_id_number, 'emirates_id_expiry' => $profile->emirates_id_expiry, 'id_number' => $profile->emirates_id_number, 'card_number' => $profile->emirates_id_card_number, 'full_name' => $profile->emirates_id_name, 'date_of_birth' => $profile->emirates_id_dob, 'nationality' => $profile->nationality, 'gender' => $profile->emirates_id_gender, 'issue_date' => $profile->emirates_id_issue_date, 'expiry_date' => $profile->emirates_id_expiry, '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([ 'success' => true, 'data' => [ 'profile' => $employerProfile ] ], 200); } catch (\Exception $e) { logger()->error('Mobile Employer Get Profile Failure: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'An error occurred while fetching the profile.', 'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error' ], 500); } } /** * Update the authenticated employer's profile details. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse */ public function updateProfile(Request $request) { /** @var User $employer */ $employer = $request->attributes->get('employer'); $sponsor = \App\Models\Sponsor::where('email', $employer->email)->first(); $validator = Validator::make($request->all(), [ 'name' => 'required|string|max:255', 'email' => [ 'required', 'string', 'email', 'max:255', 'unique:users,email,' . $employer->id, $sponsor ? 'unique:sponsors,email,' . $sponsor->id : 'unique:sponsors,email', ], 'phone' => [ 'required', 'string', 'max:255', 'unique:employer_profiles,phone,' . ($employer->employerProfile ? $employer->employerProfile->id : 'NULL'), $sponsor ? 'unique:sponsors,mobile,' . $sponsor->id : 'unique:sponsors,mobile', ], 'address' => 'required|string|max:255', 'notifications' => 'nullable|boolean', 'fcm_token' => 'nullable|string|max:255', // Emirates ID optional fields 'id_number' => 'nullable|string|max:255', 'card_number' => 'nullable|string|max:255', 'full_name' => 'nullable|string|max:255', 'date_of_birth' => 'nullable|string|max:255', 'nationality' => 'nullable|string|max:255', 'gender' => 'nullable|string|max:255', 'issue_date' => 'nullable|string|max:255', 'expiry_date' => 'nullable|string|max:255', 'occupation' => 'nullable|string|max:255', 'employer' => 'nullable|string|max:255', 'issuing_place' => 'nullable|string|max:255', ]); $validator->after(function ($validator) use ($request) { if ($request->has('full_name') && !$request->filled('full_name')) { $validator->errors()->add('full_name', 'Failed to extract name from the Emirates ID. Please upload a clearer document.'); } }); if ($validator->fails()) { return response()->json([ 'success' => false, 'message' => 'Validation error.', 'errors' => $validator->errors() ], 422); } try { if ($request->filled('full_name')) { $request->merge(['name' => $request->full_name]); } // Validate Emirates ID immutability — once set, it cannot be changed if ($request->filled('id_number')) { $existingProfile = $employer->employerProfile; if ($existingProfile && $existingProfile->emirates_id_number && $existingProfile->emirates_id_number !== $request->id_number) { return response()->json([ 'success' => false, 'message' => 'Emirates ID mismatch. You cannot change your registered Emirates ID number.', 'errors' => [ 'id_number' => ['Emirates ID mismatch.'] ] ], 422); } } // Find old email before update to locate the correct sponsor record $oldEmail = $employer->getOriginal('email') ?? $employer->email; // Update user table $userData = [ 'name' => $request->name, 'email' => $request->email, ]; if ($request->has('fcm_token')) { $userData['fcm_token'] = $request->fcm_token; } $employer->update($userData); // Sync with corresponding sponsor record if found $matchingSponsor = \App\Models\Sponsor::where('email', $oldEmail)->first(); if ($matchingSponsor) { $sponsorData = [ 'full_name' => $request->name, 'email' => $request->email, 'mobile' => $request->phone, 'address' => $request->address, ]; if ($request->has('id_number')) { $sponsorData['emirates_id'] = $request->id_number; } if ($request->has('card_number')) { $sponsorData['emirates_id_card_number'] = $request->card_number; } if ($request->has('full_name')) { $sponsorData['emirates_id_name'] = $request->full_name; } if ($request->has('date_of_birth')) { $sponsorData['emirates_id_dob'] = $request->date_of_birth; } if ($request->has('nationality')) { $sponsorData['nationality'] = $request->nationality; } if ($request->has('gender')) { $sponsorData['emirates_id_gender'] = $request->gender; } if ($request->has('issue_date')) { $sponsorData['emirates_id_issue_date'] = $request->issue_date; } if ($request->has('expiry_date')) { $sponsorData['emirates_id_expiry'] = $request->expiry_date; } if ($request->has('occupation')) { $sponsorData['emirates_id_occupation'] = $request->occupation; } if ($request->has('employer')) { $sponsorData['emirates_id_employer'] = $request->employer; } if ($request->has('issuing_place')) { $sponsorData['emirates_id_issue_place'] = $request->issuing_place; } $matchingSponsor->update($sponsorData); } // Update employer_profiles table $profile = $employer->employerProfile; if (!$profile) { $profile = new EmployerProfile(['user_id' => $employer->id]); } $profile->address = $request->address; $profile->phone = $request->phone; $profile->notifications = $request->has('notifications') ? $request->notifications : ($profile->notifications ?? true); if ($request->has('id_number')) { $profile->emirates_id_number = $request->id_number; } if ($request->has('card_number')) { $profile->emirates_id_card_number = $request->card_number; } if ($request->has('full_name')) { $profile->emirates_id_name = $request->full_name; } if ($request->has('date_of_birth')) { $profile->emirates_id_dob = $request->date_of_birth; } if ($request->has('nationality')) { $profile->nationality = $request->nationality; } if ($request->has('gender')) { $profile->emirates_id_gender = $request->gender; } if ($request->has('issue_date')) { $profile->emirates_id_issue_date = $request->issue_date; } if ($request->has('expiry_date')) { $profile->emirates_id_expiry = $request->expiry_date; } if ($request->has('occupation')) { $profile->emirates_id_occupation = $request->occupation; } if ($request->has('employer')) { $profile->emirates_id_employer = $request->employer; } if ($request->has('issuing_place')) { $profile->emirates_id_issue_place = $request->issuing_place; } $profile->save(); $employerProfile = [ 'name' => $employer->name, 'email' => $employer->email, 'phone' => $profile->phone, 'address' => $profile->address, 'notifications' => (bool)$profile->notifications, 'verification_status' => $profile->verification_status ?? 'approved', 'emirates_id_number' => $profile->emirates_id_number, 'emirates_id_expiry' => $profile->emirates_id_expiry, 'id_number' => $profile->emirates_id_number, 'card_number' => $profile->emirates_id_card_number, 'full_name' => $profile->emirates_id_name, 'date_of_birth' => $profile->emirates_id_dob, 'nationality' => $profile->nationality, 'gender' => $profile->emirates_id_gender, 'issue_date' => $profile->emirates_id_issue_date, 'expiry_date' => $profile->emirates_id_expiry, '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([ 'success' => true, 'message' => 'Profile updated successfully.', 'data' => [ 'profile' => $employerProfile ] ], 200); } catch (\Exception $e) { logger()->error('Mobile Employer Update Profile Failure: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'An error occurred while updating the profile.', 'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error' ], 500); } } /** * Get dashboard analytics and summary for employer. */ public function getDashboard(Request $request) { /** @var User $employer */ $employer = $request->attributes->get('employer'); try { $contactedWorkersCount = \App\Models\Conversation::where('employer_id', $employer->id)->count(); $totalHiredWorkers = \App\Models\JobOffer::where('employer_id', $employer->id)->where('status', 'accepted')->count() + \App\Models\JobApplication::whereHas('jobPost', function($q) use ($employer) { $q->where('employer_id', $employer->id); })->where('status', 'hired')->count(); $savedCandidates = \App\Models\Shortlist::where('employer_id', $employer->id)->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') ->where('user_id', $employer->id) ->where('status', 'active') ->latest('id') ->first(); $currentPlan = [ 'plan_id' => $sub ? $sub->plan_id : 'premium', 'name' => $sub ? (ucfirst($sub->plan_id) . ' Pass') : 'Premium Employer Pass', 'status' => $sub ? $sub->status : 'active', 'starts_at' => $sub ? date('Y-m-d', strtotime($sub->starts_at)) : now()->subDays(6)->format('Y-m-d'), 'expires_at' => $sub ? date('Y-m-d', strtotime($sub->expires_at)) : now()->addDays(24)->format('Y-m-d'), ]; // Recent Announcements / Events $dbAnnouncements = \App\Models\Announcement::where('status', 'approved')->latest()->limit(2)->get(); $recentAnnouncements = $dbAnnouncements->map(function ($ann) { $body = $ann->body; $eventDate = null; $eventTime = null; $locationDetails = null; $locationPin = null; $providedItems = null; if (strpos($ann->body, '{"type":"Charity"') === 0) { $decoded = json_decode($ann->body, true); if ($decoded) { $body = $decoded['content'] ?? $ann->body; $eventDate = $decoded['event_date'] ?? null; $eventTime = $decoded['event_time'] ?? null; $locationDetails = $decoded['location_details'] ?? null; $locationPin = $decoded['location_pin'] ?? null; $providedItems = $decoded['provided_items'] ?? null; } } else { $body = $ann->body; $eventDate = $ann->created_at->addDays(2)->format('Y-m-d'); $eventTime = '9:00 AM - 3:00 PM'; $locationDetails = 'Al Quoz Community Center, Dubai'; $locationPin = 'https://maps.google.com'; $providedItems = 'Free Medical Checks & Food Supplies'; } return [ 'id' => $ann->id, 'title' => $ann->title, 'body' => $body, 'is_charity' => true, 'event_date' => $eventDate, 'event_time' => $eventTime, 'location_details' => $locationDetails, 'location_pin' => $locationPin, 'provided_items' => $providedItems, 'created_at' => $ann->created_at->toISOString(), 'time_ago' => $ann->created_at->diffForHumans(), ]; }); return response()->json([ 'success' => true, 'data' => [ 'stats' => [ 'contacted_workers_count' => $contactedWorkersCount, 'total_hired_workers' => $totalHiredWorkers, 'saved_candidates' => $savedCandidates, 'total_workers' => $totalWorkers, ], 'current_plan' => $currentPlan, 'recent_announcements' => $recentAnnouncements, 'recent_events' => $recentAnnouncements, // alias for ease ] ], 200); } catch (\Exception $e) { logger()->error('Mobile Employer Get Dashboard Failure: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'An error occurred while fetching the dashboard statistics.', 'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error' ], 500); } } /** * Change employer's password. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse */ public function changePassword(Request $request) { /** @var User $employer */ $employer = $request->attributes->get('employer'); $validator = Validator::make($request->all(), [ 'current_password' => 'required|string', 'new_password' => 'required|string|min:8|confirmed', ]); if ($validator->fails()) { return response()->json([ 'success' => false, 'message' => 'Validation error.', 'errors' => $validator->errors() ], 422); } if (!Hash::check($request->current_password, $employer->password)) { return response()->json([ 'success' => false, 'message' => 'Validation error.', 'errors' => [ 'current_password' => ['The current password is incorrect.'] ] ], 422); } try { $hashedPassword = Hash::make($request->new_password); // Update user table $employer->update([ 'password' => $hashedPassword ]); // Sync with corresponding sponsor record if found $matchingSponsor = \App\Models\Sponsor::where('email', $employer->email)->first(); if ($matchingSponsor) { $matchingSponsor->update([ 'password' => $hashedPassword ]); } return response()->json([ 'success' => true, 'message' => 'Password changed successfully.' ], 200); } catch (\Exception $e) { logger()->error('Mobile Employer Change Password Failure: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'An error occurred while changing password.', 'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error' ], 500); } } }