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 function index(Request $request) { $user = $this->resolveCurrentUser(); $employerId = $user ? $user->id : 2; $dbWorkers = Worker::with(['skills', 'documents']) ->where('status', '!=', 'Hired') ->where('status', '!=', 'hidden') ->get(); $workers = $dbWorkers->map(function ($w) { $isPending = str_contains(strtolower($w->passport_status), 'pending'); if ($isPending || $w->status === 'hidden' || $w->status === 'Hired') { return null; } // Map languages from database comma-separated string $langs = $w->language ? array_map('trim', explode(',', $w->language)) : ['English']; // Preferred job types: full-time / part-time / live-in / live-out $jobTypes = ['full-time', 'part-time', 'live-in', 'live-out']; $preferredJobType = $w->preferred_job_type ?? $jobTypes[$w->id % 4]; // Emirates ID verification status (now dynamic passport status) $emiratesIdStatus = $w->emirates_id_status; // Map skills dynamically from database $mappedSkills = $w->skills->pluck('name')->toArray(); if (empty($mappedSkills)) { $mappedSkills = ['cooking', 'cleaning']; } // Visa status $visaStatus = $w->visa_status; $photo = null; $dbReviews = \App\Models\Review::where('worker_id', $w->id)->get(); $reviewsCount = $dbReviews->count(); $rating = $reviewsCount > 0 ? round($dbReviews->avg('rating'), 1) : 0.0; return [ 'id' => $w->id, 'name' => $w->name, 'phone' => $w->phone, 'gender' => $w->gender ?? 'Female', 'nationality' => $w->nationality, 'photo' => $photo, 'emirates_id_status' => $emiratesIdStatus, 'passport_status' => $w->passport_status, 'category' => 'Domestic Worker', 'skills' => $mappedSkills, 'visa_status' => $visaStatus, 'experience' => $w->experience, 'salary' => (int) $w->salary, 'religion' => $w->religion, 'languages' => $langs, 'age' => $w->age, 'verified' => (bool) $w->verified, 'preferred_job_type' => $preferredJobType, 'live_in_out' => $w->live_in_out ?? 'Live-in', 'bio' => $w->bio, 'rating' => $rating, 'reviews_count' => $reviewsCount, 'preferred_location' => $w->preferred_location, 'in_country' => (bool) $w->in_country, 'document_expiry_status' => $w->document_expiry_status, 'document_expiry_days' => $w->document_expiry_days, 'visa_expiry_date' => $w->visa_expiry_date, ]; })->filter()->values()->toArray(); // Apply request filters: preferred_location, job_type, live_in_out, nationality, in_country, visa_status if ($request->filled('preferred_location')) { $prefLoc = $request->preferred_location; $locsArray = is_array($prefLoc) ? $prefLoc : array_filter(array_map('trim', explode(',', $prefLoc))); $locsArray = array_map('strtolower', $locsArray); $locationMapping = [ 'dubai' => ['dubai', 'marina', 'barsha', 'nahda', 'jumeirah', 'deira', 'downtown', 'silicon', 'sports', 'motor', 'jlt', 'jbr', 'meydan', 'ranches', 'bay', 'mirdif', 'quoz'], 'abu dhabi' => ['abu dhabi', 'yas', 'khalifa', 'reem', 'saadiyat', 'raha', 'mussafah', 'zahiyah', 'karamah'], 'oman' => ['oman', 'muscat', 'salalah', 'sohar', 'nizwa', 'sur', 'ibri', 'rustaq'] ]; $workers = array_values(array_filter($workers, function ($c) use ($locsArray, $locationMapping) { if (!isset($c['preferred_location'])) return false; $wLoc = strtolower($c['preferred_location']); foreach ($locsArray as $l) { if ($l === 'all') return true; $allowedKeywords = $locationMapping[$l] ?? [$l]; foreach ($allowedKeywords as $keyword) { if (str_contains($wLoc, $keyword)) { return true; } } } return false; })); } $jobTypeParam = $request->input('job_type') ?? $request->input('preferred_job_type'); if ($jobTypeParam) { $jobTypesArray = is_array($jobTypeParam) ? $jobTypeParam : array_filter(array_map('trim', explode(',', $jobTypeParam))); $jobTypesArray = array_map('strtolower', $jobTypesArray); $workers = array_values(array_filter($workers, function ($c) use ($jobTypesArray) { if (!isset($c['preferred_job_type'])) return false; $wJobType = strtolower($c['preferred_job_type']); foreach ($jobTypesArray as $jt) { if (str_contains($wJobType, $jt)) { return true; } } return false; })); } $accParam = $request->input('live_in_out') ?? $request->input('accommodation_type') ?? $request->input('accomadation_type'); if ($accParam) { $accsArray = is_array($accParam) ? $accParam : array_filter(array_map('trim', explode(',', $accParam))); $accsArray = array_map(function($val) { return str_replace(['_', '-'], ' ', strtolower($val)); }, $accsArray); $workers = array_values(array_filter($workers, function ($c) use ($accsArray) { if (!isset($c['live_in_out'])) return false; $wAcc = str_replace(['_', '-'], ' ', strtolower($c['live_in_out'])); foreach ($accsArray as $a) { if (str_contains($wAcc, $a)) { return true; } } return false; })); } if ($request->filled('nationality')) { $natInput = $request->nationality; $natsArray = is_array($natInput) ? $natInput : array_filter(array_map('trim', explode(',', $natInput))); $natsArray = array_map('strtolower', $natsArray); $workers = array_values(array_filter($workers, function ($c) use ($natsArray) { if (!isset($c['nationality'])) return false; $wNat = strtolower($c['nationality']); foreach ($natsArray as $n) { if (str_contains($wNat, $n) || $wNat === $n) { return true; } } return false; })); } if ($request->filled('gender')) { $gender = strtolower($request->gender); $workers = array_values(array_filter($workers, function ($c) use ($gender) { return isset($c['gender']) && strtolower($c['gender']) === $gender; })); } if ($request->has('in_country')) { $inCountryVal = $request->input('in_country'); if ($inCountryVal !== null && $inCountryVal !== '') { $isInCountry = filter_var($inCountryVal, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); if ($isInCountry === null) { $strVal = strtolower(trim($inCountryVal)); if ($strVal === 'in' || $strVal === 'in_country' || $strVal === 'yes') { $isInCountry = true; } elseif ($strVal === 'out' || $strVal === 'out_country' || $strVal === 'no') { $isInCountry = false; } } if ($isInCountry !== null) { $workers = array_values(array_filter($workers, function ($c) use ($isInCountry) { return isset($c['in_country']) && (bool)$c['in_country'] === $isInCountry; })); } } } if ($request->has('out_country')) { $outCountryVal = $request->input('out_country'); if ($outCountryVal !== null && $outCountryVal !== '') { $isOutCountry = filter_var($outCountryVal, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); if ($isOutCountry === null) { $strVal = strtolower(trim($outCountryVal)); if ($strVal === 'out' || $strVal === 'out_country' || $strVal === 'yes') { $isOutCountry = true; } elseif ($strVal === 'in' || $strVal === 'in_country' || $strVal === 'no') { $isOutCountry = false; } } if ($isOutCountry !== null) { $workers = array_values(array_filter($workers, function ($c) use ($isOutCountry) { return isset($c['in_country']) && (bool)$c['in_country'] !== $isOutCountry; })); } } } $visaParam = $request->input('visa_status') ?? $request->input('next_visa_type') ?? $request->input('visa_type'); if ($visaParam) { $visasArray = is_array($visaParam) ? $visaParam : array_filter(array_map('trim', explode(',', $visaParam))); $visasArray = array_map('strtolower', $visasArray); $workers = array_values(array_filter($workers, function ($c) use ($visasArray) { if (!isset($c['visa_status'])) return false; $isInCountry = isset($c['in_country']) && (bool)$c['in_country']; if (!$isInCountry) { return false; } $wVisa = strtolower($c['visa_status']); foreach ($visasArray as $v) { if (str_contains($wVisa, $v)) { return true; } } return false; })); } $shortlistedIds = Shortlist::where('employer_id', $employerId)->pluck('worker_id')->toArray(); $nationalitiesResponse = app(\App\Http\Controllers\Api\WorkerAuthController::class)->nationalities(new \Illuminate\Http\Request(['per_page' => 500])); $nationalitiesData = json_decode($nationalitiesResponse->getContent(), true); $dbNationalities = collect($nationalitiesData['data']['nationalities'] ?? [])->pluck('name')->filter()->toArray(); $filtersMetadata = [ 'nationalities' => array_merge(['All Nationalities'], $dbNationalities), 'experienceLevels' => ['All Experience', '1-2 Years', '3-5 Years', '5+ Years'], 'religions' => ['All Religions', 'Christian', 'Muslim', 'Hindu', 'Buddhist'], 'languages' => ['All Languages', 'English', 'Arabic', 'Hindi', 'Tagalog'], 'workTypes' => ['All Types', 'full-time', 'part-time', 'live-in', 'live-out'], 'skills' => ['All Skills', 'cooking', 'driving', 'childcare', 'cleaning', 'elderly care', 'gardening'], 'visaStatuses' => ['All Visa Statuses', 'Residence Visa', 'Tourist Visa', 'Employment Visa', 'Cancelled Visa', 'Own Visa'], ]; return Inertia::render('Employer/Workers/Index', [ 'initialWorkers' => $workers, 'initialShortlistedIds' => $shortlistedIds, 'filtersMetadata' => $filtersMetadata, ]); } public function show($id) { $w = Worker::with(['skills', 'documents'])->findOrFail($id); $isPending = str_contains(strtolower($w->passport_status), 'pending'); if ($w->status === 'hidden' || $isPending) { abort(404); } // Record employer profile view (Requirement 3) $user = $this->resolveCurrentUser(); if ($user) { ProfileView::updateOrCreate( ['employer_id' => $user->id, 'worker_id' => $w->id], ['updated_at' => now()] ); } $langs = $w->language ? array_map('trim', explode(',', $w->language)) : ['English']; // Preferred job types: full-time / part-time / live-in / live-out $jobTypes = ['full-time', 'part-time', 'live-in', 'live-out']; $preferredJobType = $jobTypes[$w->id % 4]; $emiratesIdStatus = $w->emirates_id_status; // Map skills dynamically from database $mappedSkills = $w->skills->pluck('name')->toArray(); if (empty($mappedSkills)) { $mappedSkills = ['cooking', 'cleaning']; } $photo = null; // Fetch dynamic database reviews (Requirement 1) $dbReviews = Review::where('worker_id', $w->id)->with('employer')->latest()->get(); $reviews = $dbReviews->map(function ($rev) { return [ 'id' => $rev->id, 'employer_name' => $rev->employer->name ?? 'Employer', 'rating' => $rev->rating, 'date' => $rev->created_at->format('M d, Y'), 'comment' => $rev->comment, ]; })->toArray(); $reviewsCount = count($reviews); $rating = $reviewsCount > 0 ? round($dbReviews->avg('rating'), 1) : 0; $simDb = Worker::query() ->where('id', '!=', $w->id) ->where('status', '!=', 'Hired') ->where('status', '!=', 'hidden') ->limit(3) ->get(); $similarWorkers = $simDb->map(function ($sw) { $isPending = str_contains(strtolower($sw->passport_status), 'pending'); if ($isPending || $sw->status === 'hidden' || $sw->status === 'Hired') { return null; } return [ 'id' => $sw->id, 'name' => $sw->name, 'nationality' => $sw->nationality, 'category' => 'Helper', 'salary' => (int) $sw->salary, 'rating' => 4.7, 'verified' => (bool) $sw->verified, ]; })->filter()->values()->toArray(); $visaStatus = $w->visa_status; $worker = [ 'id' => $w->id, 'name' => $w->name, 'phone' => $w->phone, 'gender' => $w->gender ?? 'Female', 'nationality' => $w->nationality, 'photo' => $photo, 'emirates_id_status' => $emiratesIdStatus, 'passport_status' => $w->passport_status, 'category' => 'Domestic Worker', 'skills' => $mappedSkills, 'visa_status' => $visaStatus, 'experience' => $w->experience, 'salary' => (int) $w->salary, 'religion' => $w->religion, 'languages' => $langs, 'age' => $w->age, 'verified' => (bool) $w->verified, 'preferred_job_type' => $preferredJobType, 'live_in_out' => $w->live_in_out ?? 'Live-in', 'bio' => $w->bio, 'rating' => $rating, 'reviews_count' => $reviewsCount, 'reviews' => $reviews, 'similar_workers' => $similarWorkers, 'status' => $w->status, 'availability_status' => $w->status, 'document_expiry_status' => $w->document_expiry_status, 'document_expiry_days' => $w->document_expiry_days, 'visa_expiry_date' => $w->visa_expiry_date, 'in_country' => (bool) $w->in_country, 'preferred_location' => $w->preferred_location, 'documents' => $w->documents->map(function ($doc) { return [ 'id' => $doc->id, 'type' => $doc->type, 'number' => $doc->number, 'issue_date' => $doc->issue_date, 'expiry_date' => $doc->expiry_date, 'ocr_accuracy' => $doc->ocr_accuracy, 'file_path' => $doc->file_path ? url($doc->file_path) : null, 'ocr_data' => $doc->ocr_data, ]; })->toArray(), ]; return Inertia::render('Employer/Workers/Show', [ 'worker' => $worker, ]); } public function sendOffer(Request $request, $id) { $request->validate([ 'work_date' => 'required|date', 'location' => 'required|string|max:255', 'salary' => 'required|numeric|min:0', 'notes' => 'nullable|string|max:1000', ]); $user = $this->resolveCurrentUser(); $employerId = $user ? $user->id : 2; $worker = Worker::findOrFail($id); JobOffer::create([ 'employer_id' => $employerId, 'worker_id' => $worker->id, 'work_date' => $request->work_date, 'location' => $request->location, 'salary' => $request->salary, 'notes' => $request->notes, 'status' => 'pending', ]); return redirect()->route('employer.hiring.success', ['id' => $id]) ->with('success', 'Hiring offer has been successfully dispatched to the worker!'); } public function markHired(Request $request, $id) { $user = $this->resolveCurrentUser(); $employerId = $user ? $user->id : 2; $worker = Worker::findOrFail($id); $worker->update([ 'status' => 'Hired', ]); // Check if there is an existing job offer for this employer and worker $offer = JobOffer::where('employer_id', $employerId) ->where('worker_id', $worker->id) ->first(); if ($offer) { $offer->update(['status' => 'accepted']); } else { // Also check if there's an existing job application $jobIds = \App\Models\JobPost::where('employer_id', $employerId)->pluck('id'); $application = \App\Models\JobApplication::whereIn('job_id', $jobIds) ->where('worker_id', $worker->id) ->first(); if ($application) { $application->update(['status' => 'hired']); } else { // Create a new direct job offer with status accepted JobOffer::create([ 'employer_id' => $employerId, 'worker_id' => $worker->id, 'work_date' => now()->format('Y-m-d'), 'location' => 'Dubai', 'salary' => $worker->salary, 'notes' => 'Direct sponsoring matching finalized.', 'status' => 'accepted', ]); } } return back()->with('success', 'Worker successfully marked as Hired!'); } }