554 lines
24 KiB
PHP
554 lines
24 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Employer;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Inertia\Inertia;
|
|
use App\Models\User;
|
|
use App\Models\Worker;
|
|
use App\Models\Shortlist;
|
|
use App\Models\JobOffer;
|
|
use App\Models\Review;
|
|
use App\Models\ProfileView;
|
|
|
|
class WorkerController extends Controller
|
|
{
|
|
private function resolveCurrentUser()
|
|
{
|
|
$sess = session('user');
|
|
$sessId = is_array($sess) ? ($sess['id'] ?? null) : ($sess->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',
|
|
'main_profession' => $w->main_profession,
|
|
'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('main_profession')) {
|
|
$mainProfession = strtolower($request->main_profession);
|
|
$workers = array_values(array_filter($workers, function ($c) use ($mainProfession) {
|
|
return isset($c['main_profession']) && strtolower($c['main_profession']) === $mainProfession;
|
|
}));
|
|
}
|
|
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),
|
|
'professions' => ['All Professions', 'Housemaid', 'Nanny', 'Cook', 'Driver', 'Caregiver'],
|
|
'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'],
|
|
];
|
|
|
|
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;
|
|
|
|
$pendingOfferOrApp = JobOffer::where('employer_id', $user ? $user->id : 0)
|
|
->where('worker_id', $w->id)
|
|
->where('status', 'pending')
|
|
->exists() ||
|
|
\App\Models\JobApplication::where('worker_id', $w->id)
|
|
->whereHas('jobPost', function($q) use ($user) {
|
|
$q->where('employer_id', $user ? $user->id : 0);
|
|
})->where('status', 'hire_requested')
|
|
->exists();
|
|
|
|
$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',
|
|
'main_profession' => $w->main_profession,
|
|
'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' => $pendingOfferOrApp ? 'Pending Confirmation' : ($w->status === 'Hired' ? 'Hired' : $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;
|
|
|
|
if (!User::canContactWorker($employerId, $id)) {
|
|
$activeSub = \App\Models\Subscription::where('user_id', $employerId)->where('status', 'active')->first();
|
|
$planId = $activeSub ? $activeSub->plan_id : 'basic';
|
|
$plan = \App\Models\Plan::find($planId);
|
|
$maxContacts = $plan ? $plan->max_contact_people : 10;
|
|
|
|
return redirect()->route('employer.subscription')
|
|
->with('error', 'You have reached your contacted workers limit of ' . $maxContacts . ' under your active plan. Please upgrade or renew your subscription to contact more workers.');
|
|
}
|
|
|
|
$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;
|
|
|
|
if (!User::canContactWorker($employerId, $id)) {
|
|
$activeSub = \App\Models\Subscription::where('user_id', $employerId)->where('status', 'active')->first();
|
|
$planId = $activeSub ? $activeSub->plan_id : 'basic';
|
|
$plan = \App\Models\Plan::find($planId);
|
|
$maxContacts = $plan ? $plan->max_contact_people : 10;
|
|
|
|
return redirect()->route('employer.subscription')
|
|
->with('error', 'You have reached your contacted workers limit of ' . $maxContacts . ' under your active plan. Please upgrade or renew your subscription to contact more workers.');
|
|
}
|
|
|
|
$worker = Worker::findOrFail($id);
|
|
|
|
// Do NOT update worker status to 'Hired' directly.
|
|
|
|
// 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();
|
|
|
|
$application = null;
|
|
|
|
if ($offer) {
|
|
$offer->update(['status' => 'pending']);
|
|
} 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' => 'hire_requested']);
|
|
|
|
$history = $application->status_history ?: [];
|
|
$history[] = [
|
|
'status' => 'hire_requested',
|
|
'timestamp' => now()->toIso8601String(),
|
|
'notes' => 'Hire request initiated by employer.',
|
|
];
|
|
$application->update(['status_history' => $history]);
|
|
} else {
|
|
// Create a new direct job offer with status pending
|
|
$offer = 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 initiated.',
|
|
'status' => 'pending',
|
|
]);
|
|
}
|
|
}
|
|
|
|
// Notify the worker
|
|
if ($offer) {
|
|
$worker->notify(new \App\Notifications\GenericNotification(
|
|
"Direct Hiring Offer",
|
|
($user->name ?? "Employer") . " wants to hire you. Do you want to accept this job offer?",
|
|
[
|
|
'type' => 'direct_hire_request',
|
|
'offer_id' => $offer->id,
|
|
'status' => 'pending',
|
|
]
|
|
));
|
|
} else {
|
|
$worker->notify(new \App\Notifications\GenericNotification(
|
|
"Action Required: Confirm Hiring",
|
|
"Employer " . ($user->name ?? "Employer") . " wants to hire you for '" . ($application->jobPost->title ?? 'Job Post') . "'. Please confirm.",
|
|
[
|
|
'type' => 'hire_request',
|
|
'job_id' => $application->jobPost->id ?? '',
|
|
'application_id' => $application->id,
|
|
'status' => 'hire_requested',
|
|
]
|
|
));
|
|
}
|
|
|
|
return back()->with('success', 'Hire request initiated successfully! Awaiting candidate confirmation.');
|
|
}
|
|
}
|