get('companyId'); $companySettings = $request->get('companySettings'); $userSlug = $request->get('userSlug'); $query = JobPosting::with(['jobType', 'location', 'branch', 'department']) ->where('is_published', true) ->where('status', 'Published'); if ($companyId) { $query->whereIn('created_by', getCompanyUsers($companyId)); } if ($request->has('search') && !empty($request->search)) { $query->where(function ($q) use ($request) { $q->where('title', 'like', '%' . $request->search . '%') ->orWhere('description', 'like', '%' . $request->search . '%'); }); } if ($request->has('job_type') && !empty($request->job_type)) { $jobTypeIds = explode(',', $request->job_type); $query->whereIn('job_type_id', $jobTypeIds); } if ($request->has('location') && !empty($request->location)) { $query->where('location_id', $request->location); } if ($request->has('salary_range') && !empty($request->salary_range)) { switch ($request->salary_range) { case '0-50k': $query->where('max_salary', '<=', 50000); break; case '50k-100k': $query->whereBetween('min_salary', [50000, 100000]); break; case '100k+': $query->where('min_salary', '>=', 100000); break; } } if ($request->has('vacancies') && !empty($request->vacancies)) { $vacancyRanges = explode(',', $request->vacancies); $query->where(function ($q) use ($vacancyRanges) { foreach ($vacancyRanges as $range) { switch ($range) { case '1-5': $q->orWhereBetween('positions', [1, 5]); break; case '6-15': $q->orWhereBetween('positions', [6, 15]); break; case '16-25': $q->orWhereBetween('positions', [16, 25]); break; case '25+': $q->orWhere('positions', '>', 25); break; } } }); } // $query = $query->orderBy('is_featured', 'desc'); if ($request->has('sort') && !empty($request->sort)) { switch ($request->sort) { case 'oldest': $query = $query->orderBy('created_at', 'asc'); break; case 'salary-high': $query = $query->orderBy('max_salary', 'desc'); break; case 'salary-low': $query = $query->orderBy('min_salary', 'asc'); break; default: // newest $query = $query->orderBy('created_at', 'desc'); break; } } else { $query = $query->orderBy('created_at', 'desc'); } $jobPostings = $query->paginate(6); $jobTypes = JobType::where('status', 'active')->whereIn('created_by', getCompanyUsers($companyId))->get(); $locations = JobLocation::where('status', 'active')->whereIn('created_by', getCompanyUsers($companyId))->get(); $vacancyRanges = [ ['value' => '1-5', 'label' => '1-5'], ['value' => '6-15', 'label' => '6-15'], ['value' => '16-25', 'label' => '16-25'], ['value' => '25+', 'label' => '25+'], ]; return Inertia::render('career/index', [ 'jobPostings' => $jobPostings, 'jobTypes' => $jobTypes, 'locations' => $locations, 'companyId' => $companyId, 'userSlug' => $userSlug, 'companySettings' => $companySettings, 'vacancyRanges' => $vacancyRanges, 'filters' => $request->all(keys: ['search', 'job_type', 'location', 'salary_range', 'vacancies', 'sort']), ]); } public function show(Request $request, $userSlug, $jobCode) { try { // Get company data from middleware $companyId = $request->get('companyId'); $companySettings = $request->get('companySettings'); $query = JobPosting::with(['jobType', 'location', 'branch', 'department']) ->where('code', $jobCode) ->whereIn('created_by', getCompanyUsers($companyId)) ->where('is_published', true) ->where('status', 'Published'); $jobPosting = $query->firstOrFail(); $relatedQuery = JobPosting::with(['jobType', 'location', 'branch', 'department']) ->where('code', '!=', $jobCode) ->where('is_published', true) ->where('status', 'Published'); if ($companyId) { $relatedQuery->whereIn('created_by', getCompanyUsers($companyId)); } $relatedJobs = $relatedQuery->inRandomOrder()->limit(4)->get(); if ($companyId) { $companyUser = User::find($companyId); if ($companyUser) { $companySettings = array_merge($companySettings, [ 'company_name' => $companyUser->name, 'company_email' => $companyUser->email, ]); } } return Inertia::render('career/job-details', [ 'jobPosting' => $jobPosting, 'relatedJobs' => $relatedJobs, 'companyId' => $companyId, 'userSlug' => $userSlug, 'companySettings' => $companySettings, ]); } catch (\Exception $e) { return redirect()->route('career.index', $userSlug) ->with('error', 'Job not found or no longer available.'); } } public function showApplicationForm(Request $request, $userSlug, $jobCode) { try { // Get company data from middleware $companyId = $request->get('companyId'); $companySettings = $request->get('companySettings'); $jobPosting = JobPosting::with(['jobType', 'location', 'branch', 'department']) ->where('code', $jobCode) ->whereIn('created_by', getCompanyUsers($companyId)) ->where('is_published', true) ->where('status', 'Published') ->firstOrFail(); // Get custom questions based on IDs stored in job posting $customQuestions = []; if ($jobPosting->custom_question && is_array($jobPosting->custom_question)) { $customQuestions = \App\Models\CustomQuestion::whereIn('id', $jobPosting->custom_question) ->get(); } // Get candidate sources $candidateSources = CandidateSource::where('status', 'active') ->whereIn('created_by', getCompanyUsers($companyId)) ->get(); return Inertia::render('career/apply', [ 'jobPosting' => $jobPosting, 'customQuestions' => $customQuestions, 'candidateSources' => $candidateSources, 'applicantFields' => $jobPosting->applicant ?? [], 'visibilityFields' => $jobPosting->visibility ?? [], 'companyId' => $companyId, 'userSlug' => $userSlug, 'companySettings' => $companySettings, ]); } catch (\Exception $e) { return redirect()->route('career.index', $userSlug) ->with('error', 'Job not found or no longer available.'); } } public function submitApplication(Request $request, $userSlug, $jobCode) { try { // Get company data from middleware $companyId = $request->get('companyId'); // Find the job posting $jobPosting = JobPosting::where('code', $jobCode) ->whereIn('created_by', getCompanyUsers($companyId)) ->where('is_published', true) ->where('status', 'Published') ->firstOrFail(); // Base validation rules $rules = [ 'first_name' => 'required|string|max:255', 'last_name' => 'required|string|max:255', 'email' => 'required|email|max:255', 'phone' => 'required|string|max:20', 'address' => 'required|string|max:500', 'city' => 'required|string|max:100', 'state' => 'required|string|max:100', 'zip_code' => 'required', 'country' => 'required', 'current_position' => 'required', 'current_company' => 'required', 'experience_years' => 'required|numeric|min:0|max:50', 'current_salary' => 'required|numeric|min:0', 'expected_salary' => 'required|numeric|min:0', 'source_id' => 'required|exists:candidate_sources,id', 'custom_question' => 'nullable|json', 'resume' => 'required', ]; // Check job posting applicant fields for conditional validation $applicantFields = $jobPosting->applicant ?? []; $visibilityFields = $jobPosting->visibility ?? []; // Add conditional validation for gender if (in_array('gender', $applicantFields)) { $rules['gender'] = 'required|in:male,female,other'; } else { $rules['gender'] = 'nullable|in:male,female,other'; } // Add conditional validation for date_of_birth if (in_array('date_of_birth', $applicantFields)) { $rules['date_of_birth'] = 'required|date'; } else { $rules['date_of_birth'] = 'nullable|date'; } // Add conditional validation for cover letter fields if (in_array('cover_letter', $visibilityFields)) { $rules['coverletter_message'] = 'required|string|max:2000'; $rules['cover_letter_file'] = 'required'; } else { $rules['coverletter_message'] = 'nullable|string|max:2000'; $rules['cover_letter_file'] = 'nullable|file'; } // Add conditional validation for terms and conditions if (in_array('terms_and_conditions', $visibilityFields)) { $rules['terms_condition_check'] = 'required|in:on,off,1,0'; } else { // If terms not required, accept any value or make it optional $rules['terms_condition_check'] = 'sometimes|in:on,off,1,0'; } $validator = Validator::make($request->all(), $rules); if ($validator->fails()) { return redirect()->back() ->withErrors($validator) ->withInput(); } // Check if candidate already applied for this job $existingCandidate = Candidate::where('email', $request->email) ->where('job_id', $jobPosting->id) ->first(); if ($existingCandidate) { return redirect()->back() ->withErrors(['email' => 'You have already applied for this position.']) ->withInput(); } // Handle file uploads $resumePath = null; $coverLetterPath = null; if (!empty($request->resume) && $request->hasFile('resume')) { $filenameWithExt = $request->file('resume')->getClientOriginalName(); $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME); $extension = $request->file('resume')->getClientOriginalExtension(); $fileNameToStore = $filename . '_' . time() . '.' . $extension; $upload = upload_file($request, 'resume', $fileNameToStore, 'candidates/candidate_resumes'); if ($upload['status'] == true) { $resumePath = $upload['url']; } else { return redirect()->back() ->withErrors(['resume' => $upload['msg']]) ->withInput(); } } if (!empty($request->cover_letter_file) && $request->hasFile('cover_letter_file')) { $filenameWithExt = $request->file('cover_letter_file')->getClientOriginalName(); $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME); $extension = $request->file('cover_letter_file')->getClientOriginalExtension(); $fileNameToStore = $filename . '_' . time() . '.' . $extension; $upload = upload_file($request, 'cover_letter_file', $fileNameToStore, 'candidates/candidate_cover_letters'); if ($upload['status'] == true) { $coverLetterPath = $upload['url']; } else { return redirect()->back() ->withErrors(['cover_letter_file' => $upload['msg']]) ->withInput(); } } // Convert terms_condition_check from 1/0 to on/off if ($request->has('terms_condition_check')) { $termsValue = $request->terms_condition_check; $request->merge([ 'terms_condition_check' => ($termsValue == '1' || $termsValue === true) ? 'on' : 'off', ]); } // Get custom questions for processing answers $customQuestions = []; if ($jobPosting->custom_question && is_array($jobPosting->custom_question)) { $customQuestions = \App\Models\CustomQuestion::whereIn('id', $jobPosting->custom_question) ->get(); } // Process custom questions into question-answer format $customQuestionData = []; if ($customQuestions && count($customQuestions) > 0) { foreach ($customQuestions as $question) { $fieldName = 'custom_question_' . $question->id; if ($request->has($fieldName) && !empty($request->input($fieldName))) { $customQuestionData[$question->question] = $request->input($fieldName); } } } // Create candidate record $candidate = new Candidate; $candidate->job_id = $jobPosting->id; $candidate->source_id = $request->source_id; $candidate->branch_id = $jobPosting->branch_id; $candidate->department_id = $jobPosting->department_id; $candidate->first_name = $request->first_name; $candidate->last_name = $request->last_name; $candidate->email = $request->email; $candidate->phone = $request->phone; $candidate->gender = $request->gender; $candidate->date_of_birth = $request->date_of_birth; $candidate->address = $request->address; $candidate->city = $request->city; $candidate->state = $request->state; $candidate->zip_code = $request->zip_code; $candidate->country = $request->country; $candidate->current_company = $request->current_company; $candidate->current_position = $request->current_position; $candidate->experience_years = $request->experience_years ?: 0; $candidate->current_salary = $request->current_salary ? str_replace(',', '', $request->current_salary) : null; $candidate->expected_salary = $request->expected_salary ? str_replace(',', '', $request->expected_salary) : null; $candidate->resume_path = $resumePath; $candidate->cover_letter_path = $coverLetterPath; $candidate->coverletter_message = $request->coverletter_message; $candidate->custom_question = $customQuestionData; $candidate->terms_condition_check = $request->terms_condition_check; $candidate->application_date = now()->toDateString(); $candidate->created_by = $companyId; $candidate->save(); return redirect()->back() ->with('success', 'Your application has been submitted successfully! We will review it and get back to you soon.'); } catch (\Exception $e) { // Clean up uploaded files if candidate creation fails if (isset($resumePath) && Storage::disk('public')->exists($resumePath)) { Storage::disk('public')->delete($resumePath); } if (isset($coverLetterPath) && Storage::disk('public')->exists($coverLetterPath)) { Storage::disk('public')->delete($coverLetterPath); } return redirect()->back() ->withErrors(['error' => 'An error occurred while submitting your application. Please try again.']) ->withInput(); } } }