diff --git a/app/Http/Controllers/Api/EmployerWorkerController.php b/app/Http/Controllers/Api/EmployerWorkerController.php index 031608e..903a654 100644 --- a/app/Http/Controllers/Api/EmployerWorkerController.php +++ b/app/Http/Controllers/Api/EmployerWorkerController.php @@ -772,14 +772,14 @@ public function hireCandidate(Request $request, $id = null) ], 403); } - // Direct Offer check + // Find existing offer or application if targeting by Worker ID directly + $offer = null; + $application = null; + if (is_string($targetId) && str_starts_with($targetId, 'offer_')) { $offerId = substr($targetId, 6); $offer = JobOffer::where('id', $offerId)->where('employer_id', $employerId)->firstOrFail(); - - $offer->update(['status' => 'pending']); $worker = $offer->worker; - $updatedOffer = $offer; } else { // Check if targetId is an application $application = JobApplication::where('id', $targetId) @@ -788,9 +788,7 @@ public function hireCandidate(Request $request, $id = null) })->first(); if ($application) { - $application->update(['status' => 'hire_requested']); $worker = $application->worker; - $updatedApplication = $application; } else { // Try targeting by Worker ID directly $worker = Worker::find($targetId); @@ -802,40 +800,83 @@ public function hireCandidate(Request $request, $id = null) ], 404); } - // Find existing direct offer or create a new one with status 'pending' + // Find existing direct offer $offer = JobOffer::where('employer_id', $employerId) ->where('worker_id', $worker->id) ->first(); - if ($offer) { - $offer->update(['status' => 'pending']); - $updatedOffer = $offer; - } else { + if (!$offer) { // Find existing application $jobIds = JobPost::where('employer_id', $employerId)->pluck('id'); $application = JobApplication::whereIn('job_id', $jobIds) ->where('worker_id', $worker->id) ->first(); - - if ($application) { - $application->update(['status' => 'hire_requested']); - $updatedApplication = $application; - } else { - // Create a new direct job offer in 'pending' status - $updatedOffer = 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 via API.', - 'status' => 'pending', - ]); - } } } } + // Determine if this is first click ("Hire") or second click ("Confirm Hire") + $isWaitingForReview = false; + if ($offer && $offer->status === 'waiting_for_review') { + $isWaitingForReview = true; + } elseif ($application && $application->status === 'waiting_for_review') { + $isWaitingForReview = true; + } + + if (!$isWaitingForReview) { + // Step 1: Transition to 'waiting_for_review' + if ($offer) { + $offer->update(['status' => 'waiting_for_review']); + } elseif ($application) { + $application->update(['status' => 'waiting_for_review']); + $history = $application->status_history ?: []; + $history[] = [ + 'status' => 'waiting_for_review', + 'timestamp' => now()->toIso8601String(), + 'notes' => 'Candidate status moved to waiting for review via API.', + ]; + $application->update(['status_history' => $history]); + } else { + // Create new offer in 'waiting_for_review' status + $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 via API.', + 'status' => 'waiting_for_review', + ]); + } + + return response()->json([ + 'success' => true, + 'message' => 'Candidate status updated to Waiting for Review.', + 'data' => [ + 'worker_id' => $worker->id, + 'worker_status' => 'Waiting for Review', + 'application' => $application, + 'offer' => $offer, + ] + ], 200); + } else { + // Step 2: Confirm hire + if ($offer) { + $offer->update(['status' => 'pending']); + $updatedOffer = $offer; + } elseif ($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]); + $updatedApplication = $application; + } + } + // Dispatch push & database notification to worker for confirmation request if ($worker) { if ($updatedApplication) { @@ -991,6 +1032,28 @@ public function getWorkerDetail(Request $request, $id) ->where('worker_id', $w->id) ->first(); + $pendingOfferOrApp = JobOffer::where('employer_id', $employer->id) + ->where('worker_id', $w->id) + ->where('status', 'pending') + ->exists() || + \App\Models\JobApplication::where('worker_id', $w->id) + ->whereHas('jobPost', function($q) use ($employer) { + $q->where('employer_id', $employer->id); + })->where('status', 'hire_requested') + ->exists(); + + $waitingForReviewOfferOrApp = JobOffer::where('employer_id', $employer->id) + ->where('worker_id', $w->id) + ->where('status', 'waiting_for_review') + ->exists() || + \App\Models\JobApplication::where('worker_id', $w->id) + ->whereHas('jobPost', function($q) use ($employer) { + $q->where('employer_id', $employer->id); + })->where('status', 'waiting_for_review') + ->exists(); + + $availabilityStatus = $pendingOfferOrApp ? 'Pending Confirmation' : ($waitingForReviewOfferOrApp ? 'Waiting for Review' : ($w->status === 'Hired' ? 'Hired' : $w->status)); + $workerProfile = [ 'id' => $w->id, 'name' => $w->name, @@ -1002,6 +1065,7 @@ public function getWorkerDetail(Request $request, $id) 'experience' => $w->experience, 'verified' => (bool)$w->verified, 'status' => $w->status, + 'availability_status' => $availabilityStatus, 'created_at' => $w->created_at?->toISOString(), 'updated_at' => $w->updated_at?->toISOString(), 'deleted_at' => $w->deleted_at?->toISOString(), diff --git a/app/Http/Controllers/Api/WorkerJobController.php b/app/Http/Controllers/Api/WorkerJobController.php index 284e54c..5fca20c 100644 --- a/app/Http/Controllers/Api/WorkerJobController.php +++ b/app/Http/Controllers/Api/WorkerJobController.php @@ -1233,6 +1233,68 @@ public function declineHire(Request $request, $id) ]); } + /** + * API for workers to check for any pending hiring requests. + * GET /api/workers/pending-hiring-request + */ + public function pendingHiringRequest(Request $request) + { + /** @var Worker $worker */ + $worker = $request->attributes->get('worker'); + + if (!$worker) { + return response()->json([ + 'success' => false, + 'message' => 'Unauthenticated.' + ], 401); + } + + // Find any pending hire requests (JobApplication in 'hire_requested' status) + $pendingApp = JobApplication::where('worker_id', $worker->id) + ->where('status', 'hire_requested') + ->with(['jobPost.employer.employerProfile']) + ->first(); + + $pendingHiringRequest = null; + + if ($pendingApp) { + $pendingHiringRequest = [ + 'id' => $pendingApp->id, + 'type' => 'hire_request', + 'employer_name' => $pendingApp->jobPost->employer->name ?? 'Employer', + 'job_title' => $pendingApp->jobPost->title ?? 'Job Post', + 'salary' => $pendingApp->jobPost->salary ?? 0, + 'location' => $pendingApp->jobPost->location ?? '', + 'message' => "Employer " . ($pendingApp->jobPost->employer->name ?? "Employer") . " wants to hire you for '" . ($pendingApp->jobPost->title ?? 'Job Post') . "'. Please confirm.", + ]; + } else { + // Find any pending direct job offers (JobOffer in 'pending' status) + $pendingOffer = \App\Models\JobOffer::where('worker_id', $worker->id) + ->where('status', 'pending') + ->with(['employer.employerProfile']) + ->first(); + + if ($pendingOffer) { + $pendingHiringRequest = [ + 'id' => $pendingOffer->id, + 'type' => 'direct_hire_request', + 'employer_name' => $pendingOffer->employer->name ?? 'Employer', + 'job_title' => 'Direct Sponsoring Offer', + 'salary' => $pendingOffer->salary ?? 0, + 'location' => $pendingOffer->location ?? '', + 'message' => ($pendingOffer->employer->name ?? "Employer") . " wants to hire you. Do you want to accept this job offer?", + ]; + } + } + + return response()->json([ + 'success' => true, + 'data' => [ + 'pending_hiring_request' => $pendingHiringRequest + ] + ]); + } + /** * Dispatch FCM Push Notification & In-app database notifications. */ diff --git a/app/Http/Controllers/Api/WorkerProfileController.php b/app/Http/Controllers/Api/WorkerProfileController.php index b514c59..3fdd238 100644 --- a/app/Http/Controllers/Api/WorkerProfileController.php +++ b/app/Http/Controllers/Api/WorkerProfileController.php @@ -695,6 +695,44 @@ public function getDashboard(Request $request) ]; }); + // Find any pending hire requests (JobApplication in 'hire_requested' status) + $pendingApp = \App\Models\JobApplication::where('worker_id', $worker->id) + ->where('status', 'hire_requested') + ->with(['jobPost.employer.employerProfile']) + ->first(); + + $pendingHiringRequest = null; + + if ($pendingApp) { + $pendingHiringRequest = [ + 'id' => $pendingApp->id, + 'type' => 'hire_request', + 'employer_name' => $pendingApp->jobPost->employer->name ?? 'Employer', + 'job_title' => $pendingApp->jobPost->title ?? 'Job Post', + 'salary' => $pendingApp->jobPost->salary ?? 0, + 'location' => $pendingApp->jobPost->location ?? '', + 'message' => "Employer " . ($pendingApp->jobPost->employer->name ?? "Employer") . " wants to hire you for '" . ($pendingApp->jobPost->title ?? 'Job Post') . "'. Please confirm.", + ]; + } else { + // Find any pending direct job offers (JobOffer in 'pending' status) + $pendingOffer = JobOffer::where('worker_id', $worker->id) + ->where('status', 'pending') + ->with(['employer.employerProfile']) + ->first(); + + if ($pendingOffer) { + $pendingHiringRequest = [ + 'id' => $pendingOffer->id, + 'type' => 'direct_hire_request', + 'employer_name' => $pendingOffer->employer->name ?? 'Employer', + 'job_title' => 'Direct Sponsoring Offer', + 'salary' => $pendingOffer->salary ?? 0, + 'location' => $pendingOffer->location ?? '', + 'message' => ($pendingOffer->employer->name ?? "Employer") . " wants to hire you. Do you want to accept this job offer?", + ]; + } + } + return response()->json([ 'success' => true, 'data' => [ @@ -704,7 +742,8 @@ public function getDashboard(Request $request) 'profile_viewed' => $profileViewed, 'currently_working_sponsor' => $currentSponsor, 'current_employer' => $currentSponsor, - 'latest_charity_events_list' => $charityEvents + 'latest_charity_events_list' => $charityEvents, + 'pending_hiring_request' => $pendingHiringRequest, ] ], 200); diff --git a/app/Http/Controllers/Employer/MessageController.php b/app/Http/Controllers/Employer/MessageController.php index c788f38..8aab787 100644 --- a/app/Http/Controllers/Employer/MessageController.php +++ b/app/Http/Controllers/Employer/MessageController.php @@ -245,14 +245,33 @@ public function show($id) ]; } + $hasJobAccess = $this->checkJobAccess($user); + return Inertia::render('Employer/Messages/Show', [ 'conversations' => $conversations, 'conversation' => $conversationData, 'initialMessages' => $initialMessages, 'application' => $applicationData, + 'hasJobAccess' => $hasJobAccess, ]); } + private function checkJobAccess($user) + { + if (!$user) { + return false; + } + + $sub = \Illuminate\Support\Facades\DB::table('subscriptions') + ->where('user_id', $user->id) + ->where('status', 'active') + ->latest('id') + ->first(); + + $planId = $sub ? $sub->plan_id : 'basic'; + return $planId !== 'basic'; + } + public function send(Request $request, $id) { $user = $this->resolveCurrentUser(); diff --git a/app/Http/Controllers/Employer/WorkerController.php b/app/Http/Controllers/Employer/WorkerController.php index 13a6b7d..9b99d85 100644 --- a/app/Http/Controllers/Employer/WorkerController.php +++ b/app/Http/Controllers/Employer/WorkerController.php @@ -365,6 +365,16 @@ public function show($id) $visaStatus = $w->visa_status; + $waitingForReviewOfferOrApp = JobOffer::where('employer_id', $user ? $user->id : 0) + ->where('worker_id', $w->id) + ->where('status', 'waiting_for_review') + ->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', 'waiting_for_review') + ->exists(); + $pendingOfferOrApp = JobOffer::where('employer_id', $user ? $user->id : 0) ->where('worker_id', $w->id) ->where('status', 'pending') @@ -402,7 +412,7 @@ public function show($id) 'reviews' => $reviews, 'similar_workers' => $similarWorkers, 'status' => $w->status, - 'availability_status' => $pendingOfferOrApp ? 'Pending Confirmation' : ($w->status === 'Hired' ? 'Hired' : $w->status), + 'availability_status' => $pendingOfferOrApp ? 'Pending Confirmation' : ($waitingForReviewOfferOrApp ? 'Waiting for Review' : ($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, @@ -482,36 +492,41 @@ public function markHired(Request $request, $id) $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; + // 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 ($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(); + // Determine if this is first click ("Hire") or second click ("Confirm Hire") + // If they have an existing offer or application with status 'waiting_for_review', then it's the second click. + $isWaitingForReview = false; + if ($offer && $offer->status === 'waiting_for_review') { + $isWaitingForReview = true; + } elseif ($application && $application->status === 'waiting_for_review') { + $isWaitingForReview = true; + } - if ($application) { - $application->update(['status' => 'hire_requested']); - + if (!$isWaitingForReview) { + // Step 1: Transition to 'waiting_for_review' + if ($offer) { + $offer->update(['status' => 'waiting_for_review']); + } elseif ($application) { + $application->update(['status' => 'waiting_for_review']); $history = $application->status_history ?: []; $history[] = [ - 'status' => 'hire_requested', + 'status' => 'waiting_for_review', 'timestamp' => now()->toIso8601String(), - 'notes' => 'Hire request initiated by employer.', + 'notes' => 'Candidate status moved to waiting for review.', ]; $application->update(['status_history' => $history]); } else { - // Create a new direct job offer with status pending + // Create a new direct offer in 'waiting_for_review' status $offer = JobOffer::create([ 'employer_id' => $employerId, 'worker_id' => $worker->id, @@ -519,35 +534,51 @@ public function markHired(Request $request, $id) 'location' => 'Dubai', 'salary' => $worker->salary, 'notes' => 'Direct sponsoring matching initiated.', - 'status' => 'pending', + 'status' => 'waiting_for_review', ]); } - } - // 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', - ] - )); + return back()->with('success', 'Candidate status updated to Waiting for Review.'); } 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, + // Step 2: Confirm hire (Transition to pending/hire_requested and send notifications) + if ($offer) { + $offer->update(['status' => 'pending']); + } elseif ($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]); + } - return back()->with('success', 'Hire request initiated successfully! Awaiting candidate confirmation.'); + // 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.'); + } } } diff --git a/resources/js/Pages/Employer/Auth/Register.jsx b/resources/js/Pages/Employer/Auth/Register.jsx index 6608cf3..505cde2 100644 --- a/resources/js/Pages/Employer/Auth/Register.jsx +++ b/resources/js/Pages/Employer/Auth/Register.jsx @@ -160,7 +160,7 @@ export default function Register({ prefillData }) { const newErrors = {}; if (!data.name.trim()) { - newErrors.name = 'Sponsor name is required.'; + newErrors.name = 'Employer name is required.'; } if (!data.email.trim()) { @@ -266,7 +266,7 @@ export default function Register({ prefillData }) { return (
- + {/* Left Brand Panel (Desktop Only) */}
@@ -282,7 +282,7 @@ export default function Register({ prefillData }) {
- Sponsor Registration + Employer Registration

Find verified domestic workers directly. @@ -326,14 +326,14 @@ export default function Register({ prefillData }) {

Create Account

-

Register your sponsor portal to start searching

+

Register your employer portal to start searching

{/* Company Name */} - {/* Sponsor Name */} + {/* Employer Name */}
- + handleInputChange('email', e.target.value)} - placeholder="sponsor@domain.com" + placeholder="employer@domain.com" className={`w-full px-3.5 py-3 rounded-xl border text-sm focus:outline-none focus:ring-2 transition-all ${ errors.email ? 'border-red-500 focus:ring-red-500/20 focus:border-red-500' diff --git a/resources/js/Pages/Employer/Messages/Show.jsx b/resources/js/Pages/Employer/Messages/Show.jsx index 99aa5bc..fc0f0e4 100644 --- a/resources/js/Pages/Employer/Messages/Show.jsx +++ b/resources/js/Pages/Employer/Messages/Show.jsx @@ -32,7 +32,7 @@ import { } from 'lucide-react'; import { toast } from 'sonner'; -export default function Show({ conversation, initialMessages, conversations = [], application = null }) { +export default function Show({ conversation, initialMessages, conversations = [], application = null, hasJobAccess = false }) { const { t } = useTranslation(); const [messages, setMessages] = useState(initialMessages || []); const [input, setInput] = useState(''); @@ -343,7 +343,7 @@ export default function Show({ conversation, initialMessages, conversations = []
- {application ? ( + {application && hasJobAccess ? ( )} @@ -954,6 +963,52 @@ export default function Show({ worker }) {
)} + {/* Confirm Hire Modal Overlay */} + {showHireConfirmModal && ( +
+
+ + +
+
+ +
+

+ {availabilityStatus === 'Waiting for Review' + ? t('confirm_hire_title', 'Confirm Sponsoring / Hiring Offer') + : t('initiate_hire_title', 'Initiate Sponsoring / Hiring')} +

+

+ {availabilityStatus === 'Waiting for Review' + ? t('confirm_hire_desc', 'Are you sure you want to hire this worker? This action will send a hiring request to the worker.') + : t('initiate_hire_desc', 'Are you sure you want to initiate the hiring process for this worker? This will add them to your review list.')} +

+
+ +
+ + +
+
+
+ )} + {/* Report Abuse Modal Overlay */} {showReportModal && (
diff --git a/routes/api.php b/routes/api.php index efb6717..0190d2f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -117,6 +117,7 @@ Route::post('/workers/applied-jobs/{id}/withdraw', [\App\Http\Controllers\Api\WorkerJobController::class, 'withdrawApplication']); Route::post('/workers/applied-jobs/{id}/confirm-hire', [\App\Http\Controllers\Api\WorkerJobController::class, 'confirmHire']); Route::post('/workers/applied-jobs/{id}/decline-hire', [\App\Http\Controllers\Api\WorkerJobController::class, 'declineHire']); + Route::get('/workers/pending-hiring-request', [\App\Http\Controllers\Api\WorkerJobController::class, 'pendingHiringRequest']); // Review Management (Worker reviewing Employer) Route::get('/workers/reviews', [\App\Http\Controllers\Api\WorkerReviewController::class, 'getReviews']); diff --git a/tests/Feature/WorkerJobApiTest.php b/tests/Feature/WorkerJobApiTest.php index 9ab8521..d86da23 100644 --- a/tests/Feature/WorkerJobApiTest.php +++ b/tests/Feature/WorkerJobApiTest.php @@ -1133,6 +1133,64 @@ public function test_basic_plan_employer_can_directly_hire_without_subscription_ 'status' => 'hire_requested', ]); } + + public function test_two_step_hiring_flow() + { + // 1. Direct hiring flow via Web Controller + // First click: transition from Available to 'Waiting for Review' + $response = $this->actingAs($this->employer) + ->withSession(['user' => $this->employer]) + ->post("/employer/workers/{$this->worker->id}/mark-hired"); + + $response->assertRedirect(); + $this->assertDatabaseHas('job_offers', [ + 'employer_id' => $this->employer->id, + 'worker_id' => $this->worker->id, + 'status' => 'waiting_for_review', + ]); + + // Fetch the created job offer + $offer = \App\Models\JobOffer::where('employer_id', $this->employer->id) + ->where('worker_id', $this->worker->id) + ->first(); + $this->assertNotNull($offer); + + // Second click: transition to 'Pending Confirmation' (status 'pending') and notify worker + $response2 = $this->actingAs($this->employer) + ->withSession(['user' => $this->employer]) + ->post("/employer/workers/{$this->worker->id}/mark-hired"); + + $response2->assertRedirect(); + $offer->refresh(); + $this->assertEquals('pending', $offer->status); + + // 2. Check pending hiring request via worker API + $responseWorkerDashboard = $this->getJson('/api/workers/dashboard', [ + 'Authorization' => 'Bearer worker_api_token' + ]); + $responseWorkerDashboard->assertStatus(200); + $responseWorkerDashboard->assertJsonPath('data.pending_hiring_request.id', $offer->id); + $responseWorkerDashboard->assertJsonPath('data.pending_hiring_request.type', 'direct_hire_request'); + + $responsePendingApi = $this->getJson('/api/workers/pending-hiring-request', [ + 'Authorization' => 'Bearer worker_api_token' + ]); + $responsePendingApi->assertStatus(200); + $responsePendingApi->assertJsonPath('data.pending_hiring_request.id', $offer->id); + + // 3. Worker confirms direct job offer + $responseConfirm = $this->postJson("/api/workers/offers/{$offer->id}/respond", [ + 'status' => 'accepted' + ], [ + 'Authorization' => 'Bearer worker_api_token' + ]); + $responseConfirm->assertStatus(200); + + $offer->refresh(); + $this->assertEquals('accepted', $offer->status); + $this->worker->refresh(); + $this->assertEquals('Hired', $this->worker->status); + } } diff --git a/vite.config.js b/vite.config.js index 6b56652..79c4347 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.217', + host: '192.168.0.241', }, watch: { ignored: ['**/storage/framework/views/**'],