554 lines
32 KiB
PHP
554 lines
32 KiB
PHP
<?php
|
|
|
|
use App\Http\Controllers\Admin\AdminAuthController;
|
|
use App\Http\Controllers\Admin\SponsorController;
|
|
use Illuminate\Support\Facades\Route;
|
|
use Inertia\Inertia;
|
|
|
|
// Smart root redirect — send users to the right dashboard based on their role
|
|
Route::get('/', function () {
|
|
// Check Laravel's built-in auth (survives refresh via remember cookie)
|
|
if (auth()->check()) {
|
|
$role = auth()->user()->role;
|
|
if ($role === 'employer') {
|
|
return redirect()->route('employer.dashboard');
|
|
}
|
|
if ($role === 'admin') {
|
|
return redirect()->route('admin.dashboard');
|
|
}
|
|
}
|
|
|
|
// Fallback: check custom session key (registration flow / legacy)
|
|
$sessionUser = session('user');
|
|
if ($sessionUser) {
|
|
$role = is_array($sessionUser) ? ($sessionUser['role'] ?? null) : ($sessionUser->role ?? null);
|
|
if ($role === 'employer') {
|
|
return redirect()->route('employer.dashboard');
|
|
}
|
|
if ($role === 'admin') {
|
|
return redirect()->route('admin.dashboard');
|
|
}
|
|
}
|
|
|
|
// Not logged in — send to admin login as default
|
|
return redirect()->route('admin.login');
|
|
});
|
|
|
|
// Admin Auth Routes
|
|
Route::get('/admin/login', [AdminAuthController::class, 'showLogin'])->name('admin.login');
|
|
Route::post('/admin/login', [AdminAuthController::class, 'login'])->name('admin.login.submit');
|
|
Route::post('/admin/logout', [AdminAuthController::class, 'logout'])->name('admin.logout');
|
|
|
|
|
|
|
|
|
|
// Admin Protected Routes
|
|
Route::prefix('admin')->middleware(['admin'])->group(function () {
|
|
Route::get('/dashboard', [\App\Http\Controllers\Admin\DashboardController::class, 'index'])->name('admin.dashboard');
|
|
Route::post('/verifications/approve', [\App\Http\Controllers\Admin\DashboardController::class, 'approveVerification'])->name('admin.verifications.approve');
|
|
Route::post('/verifications/reject', [\App\Http\Controllers\Admin\DashboardController::class, 'rejectVerification'])->name('admin.verifications.reject');
|
|
|
|
Route::get('/workers', [\App\Http\Controllers\Admin\WorkerController::class, 'index'])->name('admin.workers');
|
|
Route::post('/workers/{worker}/toggle-status', [\App\Http\Controllers\Admin\WorkerController::class, 'toggleStatus'])->name('admin.workers.toggle-status');
|
|
Route::post('/workers/{worker}/availability-override', [\App\Http\Controllers\Admin\WorkerController::class, 'availabilityOverride'])->name('admin.workers.availability-override');
|
|
Route::post('/workers/{worker}/flag-fraud', [\App\Http\Controllers\Admin\WorkerController::class, 'flagFraud'])->name('admin.workers.flag-fraud');
|
|
Route::post('/workers/{worker}/update-profile', [\App\Http\Controllers\Admin\WorkerController::class, 'updateProfile'])->name('admin.workers.update-profile');
|
|
|
|
Route::get('/workers/verifications', [\App\Http\Controllers\Admin\WorkerVerificationController::class, 'index'])->name('admin.workers.verifications');
|
|
Route::post('/workers/{worker}/verify', [\App\Http\Controllers\Admin\WorkerVerificationController::class, 'verify'])->name('admin.workers.verify');
|
|
|
|
// Employer Management Routes
|
|
Route::get('/employers', [\App\Http\Controllers\Admin\EmployerController::class, 'index'])->name('admin.employers');
|
|
Route::get('/employers/export', [\App\Http\Controllers\Admin\EmployerController::class, 'export'])->name('admin.employers.export');
|
|
Route::post('/employers/{id}/verify', [\App\Http\Controllers\Admin\EmployerController::class, 'verify'])->name('admin.employers.verify');
|
|
Route::post('/employers/{id}/suspend', [\App\Http\Controllers\Admin\EmployerController::class, 'suspend'])->name('admin.employers.suspend');
|
|
Route::post('/employers/{id}/activate', [\App\Http\Controllers\Admin\EmployerController::class, 'activate'])->name('admin.employers.activate');
|
|
Route::post('/employers/{id}/update', [\App\Http\Controllers\Admin\EmployerController::class, 'update'])->name('admin.employers.update');
|
|
Route::delete('/employers/{id}', [\App\Http\Controllers\Admin\EmployerController::class, 'delete'])->name('admin.employers.delete');
|
|
|
|
// Charity Organization Management Routes
|
|
Route::get('/charity-organizations', [\App\Http\Controllers\Admin\SponsorController::class, 'index'])->name('admin.charity-organizations');
|
|
Route::get('/charity-organizations/export', [\App\Http\Controllers\Admin\SponsorController::class, 'export'])->name('admin.charity-organizations.export');
|
|
Route::post('/charity-organizations/{id}/verify', [\App\Http\Controllers\Admin\SponsorController::class, 'verify'])->name('admin.charity-organizations.verify');
|
|
Route::post('/charity-organizations/{id}/suspend', [\App\Http\Controllers\Admin\SponsorController::class, 'suspend'])->name('admin.charity-organizations.suspend');
|
|
Route::post('/charity-organizations/{id}/activate', [\App\Http\Controllers\Admin\SponsorController::class, 'activate'])->name('admin.charity-organizations.activate');
|
|
Route::post('/charity-organizations/{id}/update', [\App\Http\Controllers\Admin\SponsorController::class, 'update'])->name('admin.charity-organizations.update');
|
|
Route::delete('/charity-organizations/{id}', [\App\Http\Controllers\Admin\SponsorController::class, 'delete'])->name('admin.charity-organizations.delete');
|
|
|
|
Route::get('/subscriptions', function () {
|
|
$plans = \App\Models\Plan::all()->map(function ($plan) {
|
|
$plan->usage_count = \App\Models\Sponsor::where('subscription_plan', $plan->id)
|
|
->where('subscription_status', 'active')
|
|
->count();
|
|
return $plan;
|
|
});
|
|
return Inertia::render('Admin/Subscriptions/Index', [
|
|
'plans' => $plans
|
|
]);
|
|
})->name('admin.subscriptions');
|
|
|
|
Route::post('/subscriptions', function (\Illuminate\Http\Request $request) {
|
|
$data = $request->validate([
|
|
'id' => 'required|string|unique:plans,id',
|
|
'name' => 'required|string|max:255',
|
|
'price' => 'required|numeric|min:0',
|
|
'duration' => 'required|string',
|
|
'features' => 'required|array',
|
|
'max_contact_people' => 'nullable|integer',
|
|
'unlimited_contacts' => 'required|boolean',
|
|
'enable_job_apply' => 'required|boolean',
|
|
'status' => 'nullable|string|in:Active,Disabled',
|
|
]);
|
|
|
|
\App\Models\Plan::create([
|
|
'id' => $data['id'],
|
|
'name' => $data['name'],
|
|
'price' => $data['price'],
|
|
'duration' => $data['duration'],
|
|
'features' => $data['features'],
|
|
'status' => $data['status'] ?? 'Active',
|
|
'max_contact_people' => $data['unlimited_contacts'] ? null : $data['max_contact_people'],
|
|
'unlimited_contacts' => $data['unlimited_contacts'],
|
|
'enable_job_apply' => $data['enable_job_apply'],
|
|
]);
|
|
|
|
return redirect()->back();
|
|
})->name('admin.subscriptions.store');
|
|
|
|
Route::post('/subscriptions/{id}/update', function (\Illuminate\Http\Request $request, $id) {
|
|
$plan = \App\Models\Plan::findOrFail($id);
|
|
$data = $request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'price' => 'required|numeric|min:0',
|
|
'duration' => 'required|string',
|
|
'features' => 'required|array',
|
|
'max_contact_people' => 'nullable|integer',
|
|
'unlimited_contacts' => 'required|boolean',
|
|
'enable_job_apply' => 'required|boolean',
|
|
'status' => 'required|string|in:Active,Disabled',
|
|
]);
|
|
|
|
if ($data['status'] === 'Disabled') {
|
|
$usageCount = \App\Models\Sponsor::where('subscription_plan', $plan->id)
|
|
->where('subscription_status', 'active')
|
|
->count();
|
|
if ($usageCount > 0) {
|
|
return redirect()->back()->withErrors([
|
|
'status' => "Cannot disable plan. {$usageCount} " . ($usageCount === 1 ? 'person is' : 'people are') . " using this plan."
|
|
]);
|
|
}
|
|
}
|
|
|
|
$plan->update([
|
|
'name' => $data['name'],
|
|
'price' => $data['price'],
|
|
'duration' => $data['duration'],
|
|
'features' => $data['features'],
|
|
'status' => $data['status'],
|
|
'max_contact_people' => $data['unlimited_contacts'] ? null : $data['max_contact_people'],
|
|
'unlimited_contacts' => $data['unlimited_contacts'],
|
|
'enable_job_apply' => $data['enable_job_apply'],
|
|
]);
|
|
|
|
return redirect()->back();
|
|
})->name('admin.subscriptions.update');
|
|
|
|
Route::delete('/subscriptions/{id}', function ($id) {
|
|
$plan = \App\Models\Plan::findOrFail($id);
|
|
$usageCount = \App\Models\Sponsor::where('subscription_plan', $plan->id)
|
|
->where('subscription_status', 'active')
|
|
->count();
|
|
if ($usageCount > 0) {
|
|
return redirect()->back()->withErrors([
|
|
'status' => "Cannot delete plan. {$usageCount} " . ($usageCount === 1 ? 'person is' : 'people are') . " using this plan."
|
|
]);
|
|
}
|
|
$plan->delete();
|
|
return redirect()->back();
|
|
})->name('admin.subscriptions.delete');
|
|
|
|
Route::get('/payments', function () {
|
|
$payments = \Illuminate\Support\Facades\DB::table('subscriptions')
|
|
->leftJoin('users', 'subscriptions.user_id', '=', 'users.id')
|
|
->select('subscriptions.*', 'users.name as user_name', 'users.email as user_email')
|
|
->orderBy('subscriptions.created_at', 'desc')
|
|
->get()
|
|
->map(function($sub) {
|
|
$planLabel = ucfirst($sub->plan_id) . ' Sponsor Pass';
|
|
$status = $sub->status === 'active' ? 'Completed' : (ucfirst($sub->status) ?: 'Completed');
|
|
$startsAt = $sub->starts_at ?? $sub->created_at;
|
|
$expiresAt = $sub->expires_at ?? date('Y-m-d H:i:s', strtotime($startsAt . ' +1 month'));
|
|
return [
|
|
'id' => 'PAY-' . str_pad($sub->id, 3, '0', STR_PAD_LEFT),
|
|
'employer' => $sub->user_name ?: 'System Guest / Sponsor',
|
|
'plan' => $planLabel,
|
|
'amount' => (float)$sub->amount_aed,
|
|
'method' => 'PayTabs Gateway',
|
|
'date' => date('Y-m-d', strtotime($startsAt)),
|
|
'status' => $status,
|
|
'period' => date('M Y', strtotime($startsAt)) . ' - ' . date('M Y', strtotime($expiresAt)),
|
|
];
|
|
});
|
|
|
|
$totalRevenue = \Illuminate\Support\Facades\DB::table('subscriptions')->where('status', 'active')->sum('amount_aed');
|
|
$activeSubs = \Illuminate\Support\Facades\DB::table('subscriptions')->where('status', 'active')->count();
|
|
$failedPayments = \Illuminate\Support\Facades\DB::table('subscriptions')->where('status', 'failed')->count();
|
|
$avgTicket = \Illuminate\Support\Facades\DB::table('subscriptions')->where('status', 'active')->avg('amount_aed') ?: 0;
|
|
|
|
$stats = [
|
|
'total_revenue' => number_format($totalRevenue, 2),
|
|
'active_subscriptions' => $activeSubs,
|
|
'failed_payments' => $failedPayments,
|
|
'average_ticket' => number_format($avgTicket, 2),
|
|
];
|
|
|
|
return Inertia::render('Admin/Payments/Index', [
|
|
'payments' => $payments,
|
|
'stats' => $stats
|
|
]);
|
|
})->name('admin.payments');
|
|
|
|
Route::post('/payments/{id}/refund', [\App\Http\Controllers\Admin\AdminExtraController::class, 'refundPayment'])->name('admin.payments.refund');
|
|
|
|
Route::get('/master-data/skills', function () {
|
|
$skills = \App\Models\Skill::all()->map(function ($skill) {
|
|
return [
|
|
'id' => $skill->id,
|
|
'name' => $skill->name,
|
|
'image_url' => $skill->image_path ? asset('storage/' . $skill->image_path) : null,
|
|
'worker_count' => \DB::table('worker_skills')->where('skill_id', $skill->id)->count(),
|
|
'status' => 'Active',
|
|
];
|
|
});
|
|
return Inertia::render('Admin/MasterData/WorkerSkills', [
|
|
'skills' => $skills
|
|
]);
|
|
})->name('admin.skills');
|
|
|
|
Route::post('/master-data/skills', function (\Illuminate\Http\Request $request) {
|
|
$request->validate([
|
|
'name' => 'required|string|max:255|unique:skills,name',
|
|
'image' => 'nullable|image|max:2048',
|
|
]);
|
|
$imagePath = null;
|
|
if ($request->hasFile('image')) {
|
|
$imagePath = $request->file('image')->store('skills', 'public');
|
|
}
|
|
\App\Models\Skill::create([
|
|
'name' => strtolower($request->name),
|
|
'image_path' => $imagePath,
|
|
]);
|
|
return redirect()->back();
|
|
})->name('admin.skills.store');
|
|
|
|
Route::post('/master-data/skills/{id}/update', function (\Illuminate\Http\Request $request, $id) {
|
|
$request->validate([
|
|
'name' => 'required|string|max:255|unique:skills,name,' . $id,
|
|
'image' => 'nullable|image|max:2048',
|
|
]);
|
|
$skill = \App\Models\Skill::findOrFail($id);
|
|
$imagePath = $skill->image_path;
|
|
if ($request->hasFile('image')) {
|
|
if ($imagePath) {
|
|
\Storage::disk('public')->delete($imagePath);
|
|
}
|
|
$imagePath = $request->file('image')->store('skills', 'public');
|
|
}
|
|
$skill->update([
|
|
'name' => strtolower($request->name),
|
|
'image_path' => $imagePath,
|
|
]);
|
|
return redirect()->back();
|
|
})->name('admin.skills.update');
|
|
|
|
Route::delete('/master-data/skills/{id}', function ($id) {
|
|
$skill = \App\Models\Skill::findOrFail($id);
|
|
if ($skill->image_path) {
|
|
\Storage::disk('public')->delete($skill->image_path);
|
|
}
|
|
\DB::table('worker_skills')->where('skill_id', $id)->delete();
|
|
$skill->delete();
|
|
return redirect()->back();
|
|
})->name('admin.skills.delete');
|
|
|
|
Route::get('/master-data/reasons', function () {
|
|
\DB::table('report_reasons')->whereIn('type', ['Both', 'Review'])->update(['type' => 'Chat']);
|
|
$reasons = \App\Models\ReportReason::orderBy('id', 'desc')->get()->map(function ($reason) {
|
|
return [
|
|
'id' => $reason->id,
|
|
'reason' => $reason->reason,
|
|
'status' => $reason->status,
|
|
'type' => $reason->type,
|
|
];
|
|
});
|
|
return Inertia::render('Admin/MasterData/ReportReasons', [
|
|
'reasons' => $reasons
|
|
]);
|
|
})->name('admin.reasons');
|
|
|
|
Route::post('/master-data/reasons', function (\Illuminate\Http\Request $request) {
|
|
$request->validate([
|
|
'reason' => 'required|string|max:255|unique:report_reasons,reason',
|
|
'type' => 'required|string|in:Chat,Support',
|
|
]);
|
|
\App\Models\ReportReason::create([
|
|
'reason' => $request->reason,
|
|
'type' => $request->type,
|
|
'status' => 'Active',
|
|
]);
|
|
return redirect()->back();
|
|
})->name('admin.reasons.store');
|
|
|
|
Route::post('/master-data/reasons/{id}/update', function (\Illuminate\Http\Request $request, $id) {
|
|
$request->validate([
|
|
'reason' => 'required|string|max:255|unique:report_reasons,reason,' . $id,
|
|
'status' => 'required|string|in:Active,Inactive',
|
|
'type' => 'required|string|in:Chat,Support',
|
|
]);
|
|
$reason = \App\Models\ReportReason::findOrFail($id);
|
|
$reason->update([
|
|
'reason' => $request->reason,
|
|
'status' => $request->status,
|
|
'type' => $request->type,
|
|
]);
|
|
return redirect()->back();
|
|
})->name('admin.reasons.update');
|
|
|
|
Route::delete('/master-data/reasons/{id}', function ($id) {
|
|
$reason = \App\Models\ReportReason::findOrFail($id);
|
|
$reason->delete();
|
|
return redirect()->back();
|
|
})->name('admin.reasons.delete');
|
|
|
|
Route::get('/events', [\App\Http\Controllers\Admin\AdminExtraController::class, 'announcements'])->name('admin.events');
|
|
Route::post('/events/create', [\App\Http\Controllers\Admin\AdminExtraController::class, 'storeAnnouncement'])->name('admin.events.store');
|
|
Route::post('/events/{id}/approve', [\App\Http\Controllers\Admin\AdminExtraController::class, 'approveAnnouncement'])->name('admin.events.approve');
|
|
Route::post('/events/{id}/reject', [\App\Http\Controllers\Admin\AdminExtraController::class, 'rejectAnnouncement'])->name('admin.events.reject');
|
|
Route::delete('/events/{id}', [\App\Http\Controllers\Admin\AdminExtraController::class, 'deleteAnnouncement'])->name('admin.events.delete');
|
|
|
|
// New Modules Added
|
|
Route::get('/safety', [\App\Http\Controllers\Admin\AdminExtraController::class, 'safety'])->name('admin.safety');
|
|
Route::post('/safety/reports/{id}/resolve', [\App\Http\Controllers\Admin\AdminExtraController::class, 'resolveSafetyReport'])->name('admin.safety.resolve-report');
|
|
|
|
// Disputes have been consolidated into Help & Support module
|
|
// Route::get('/disputes', [\App\Http\Controllers\Admin\AdminExtraController::class, 'disputes'])->name('admin.disputes');
|
|
// Route::post('/disputes/{id}/resolve', [\App\Http\Controllers\Admin\AdminExtraController::class, 'resolveDispute'])->name('admin.disputes.resolve');
|
|
// Route::post('/disputes/{id}/add-note', [\App\Http\Controllers\Admin\AdminExtraController::class, 'addDisputeNote'])->name('admin.disputes.add-note');
|
|
|
|
|
|
Route::get('/analytics', [\App\Http\Controllers\Admin\AdminExtraController::class, 'analytics'])->name('admin.analytics');
|
|
Route::get('/audit-logs', [\App\Http\Controllers\Admin\AdminExtraController::class, 'auditLogs'])->name('admin.audit-logs');
|
|
|
|
// Admin FAQs Management
|
|
Route::get('/faqs', [\App\Http\Controllers\Admin\FaqController::class, 'index'])->name('admin.faqs');
|
|
Route::post('/faqs', [\App\Http\Controllers\Admin\FaqController::class, 'store'])->name('admin.faqs.store');
|
|
Route::post('/faqs/{id}', [\App\Http\Controllers\Admin\FaqController::class, 'update'])->name('admin.faqs.update');
|
|
Route::delete('/faqs/{id}', [\App\Http\Controllers\Admin\FaqController::class, 'destroy'])->name('admin.faqs.destroy');
|
|
|
|
// Admin Support Tickets
|
|
Route::get('/tickets', [\App\Http\Controllers\Admin\SupportTicketController::class, 'index'])->name('admin.tickets.index');
|
|
Route::get('/tickets/{id}', [\App\Http\Controllers\Admin\SupportTicketController::class, 'show'])->name('admin.tickets.show');
|
|
Route::post('/tickets/{id}/reply', [\App\Http\Controllers\Admin\SupportTicketController::class, 'reply'])->name('admin.tickets.reply');
|
|
Route::post('/tickets/{id}/status', [\App\Http\Controllers\Admin\SupportTicketController::class, 'updateStatus'])->name('admin.tickets.update-status');
|
|
Route::post('/tickets/{id}/generate-dev-response', [\App\Http\Controllers\Admin\SupportTicketController::class, 'generateDevResponse'])->name('admin.tickets.generate-dev-response');
|
|
});
|
|
|
|
// Employer Auth Routes — guest-only pages redirect logged-in employers to dashboard
|
|
Route::middleware('employer.guest')->group(function () {
|
|
Route::get('/employer/login', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'showLogin'])->name('employer.login');
|
|
Route::get('/employer/register', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'showRegister'])->name('employer.register');
|
|
Route::get('/employer/forgot-password', function () {
|
|
return Inertia::render('Employer/Auth/ForgotPassword');
|
|
})->name('employer.forgot-password');
|
|
});
|
|
|
|
// Employer Auth POST/flow routes (no guest guard — mid-registration steps allowed)
|
|
Route::post('/employer/login', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'login'])->name('employer.login.submit');
|
|
Route::post('/employer/register', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'register'])->name('employer.register.submit');
|
|
Route::get('/employer/verify-email', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'showVerifyEmail'])->name('employer.verify-email');
|
|
Route::post('/employer/verify-email', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'verifyEmail'])->name('employer.verify-email.submit')->middleware('throttle:5,1');
|
|
Route::post('/employer/resend-otp', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'resendOtp'])->name('employer.resend-otp')->middleware('throttle:3,1');
|
|
Route::get('/employer/upload-emirates-id', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'showUploadEmiratesId'])->name('employer.upload-emirates-id');
|
|
Route::post('/employer/upload-emirates-id', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'uploadEmiratesId'])->name('employer.upload-emirates-id.submit');
|
|
Route::post('/employer/confirm-emirates-id', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'confirmEmiratesId'])->name('employer.confirm-emirates-id.submit');
|
|
Route::get('/employer/register-payment', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'showRegisterPayment'])->name('employer.register-payment');
|
|
Route::post('/employer/register-payment', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'storeRegisterPayment'])->name('employer.register-payment.submit');
|
|
Route::get('/employer/create-password', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'showCreatePassword'])->name('employer.create-password');
|
|
Route::post('/employer/create-password', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'createPassword'])->name('employer.create-password.submit');
|
|
Route::post('/employer/logout', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'logout'])->name('employer.logout');
|
|
Route::get('/employer/pending-verification', function () {
|
|
return Inertia::render('Employer/Auth/PendingVerification');
|
|
})->name('employer.pending-verification');
|
|
Route::post('/employer/forgot-password', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'forgotPassword'])->name('employer.forgot-password.submit');
|
|
Route::post('/employer/reset-password', [\App\Http\Controllers\Employer\EmployerAuthController::class, 'resetPassword'])->name('employer.reset-password.submit');
|
|
|
|
// Employer Protected Routes
|
|
Route::prefix('employer')->middleware(['employer'])->group(function () {
|
|
Route::get('/dashboard', [\App\Http\Controllers\Employer\DashboardController::class, 'index'])->name('employer.dashboard');
|
|
Route::get('/workers', [\App\Http\Controllers\Employer\WorkerController::class, 'index'])->name('employer.workers');
|
|
Route::get('/workers/{id}', [\App\Http\Controllers\Employer\WorkerController::class, 'show'])->name('employer.workers.show');
|
|
Route::get('/workers/{id}/hire', function ($id) {
|
|
$worker = \App\Models\Worker::findOrFail($id);
|
|
$workerData = [
|
|
'id' => $worker->id,
|
|
'name' => $worker->name,
|
|
'nationality' => $worker->nationality,
|
|
'category' => $worker->preferred_job_type ?? 'Domestic Worker',
|
|
'salary' => (int) $worker->salary,
|
|
];
|
|
return Inertia::render('Employer/Hiring/Confirm', ['worker' => $workerData]);
|
|
})->name('employer.hiring.confirm');
|
|
Route::post('/workers/{id}/hire', [\App\Http\Controllers\Employer\WorkerController::class, 'sendOffer'])->name('employer.workers.send-offer');
|
|
Route::post('/workers/{id}/mark-hired', [\App\Http\Controllers\Employer\WorkerController::class, 'markHired'])->name('employer.workers.mark-hired');
|
|
Route::get('/workers/{id}/hire/success', function ($id) {
|
|
$worker = \App\Models\Worker::findOrFail($id);
|
|
$workerData = [
|
|
'id' => $worker->id,
|
|
'name' => $worker->name,
|
|
];
|
|
return Inertia::render('Employer/Hiring/Success', ['worker' => $workerData]);
|
|
})->name('employer.hiring.success');
|
|
|
|
// Job Management
|
|
Route::get('/jobs', [\App\Http\Controllers\Employer\JobController::class, 'index'])->name('employer.jobs');
|
|
Route::get('/jobs/create', [\App\Http\Controllers\Employer\JobController::class, 'create'])->name('employer.jobs.create');
|
|
Route::post('/jobs/create', [\App\Http\Controllers\Employer\JobController::class, 'store'])->name('employer.jobs.store');
|
|
Route::get('/jobs/all-applicants', [\App\Http\Controllers\Employer\JobController::class, 'allApplicants'])->name('employer.jobs.all-applicants');
|
|
Route::get('/jobs/shortlisted', [\App\Http\Controllers\Employer\JobController::class, 'shortlistedApplicants'])->name('employer.jobs.shortlisted');
|
|
Route::get('/jobs/{id}/edit', [\App\Http\Controllers\Employer\JobController::class, 'edit'])->name('employer.jobs.edit');
|
|
Route::post('/jobs/{id}/edit', [\App\Http\Controllers\Employer\JobController::class, 'update'])->name('employer.jobs.update');
|
|
Route::delete('/jobs/{id}', [\App\Http\Controllers\Employer\JobController::class, 'destroy'])->name('employer.jobs.destroy');
|
|
Route::get('/jobs/{id}', [\App\Http\Controllers\Employer\JobController::class, 'show'])->name('employer.jobs.show');
|
|
Route::post('/jobs/{id}/close', [\App\Http\Controllers\Employer\JobController::class, 'close'])->name('employer.jobs.close');
|
|
Route::get('/jobs/{id}/applicants', [\App\Http\Controllers\Employer\JobController::class, 'applicants'])->name('employer.jobs.applicants');
|
|
Route::get('/subscription', function () {
|
|
$sess = session('user');
|
|
$sessId = is_array($sess) ? ($sess['id'] ?? null) : ($sess->id ?? null);
|
|
$user = $sessId ? \App\Models\User::find($sessId) : \App\Models\User::where('role', 'employer')->first();
|
|
|
|
$sub = $user ? \Illuminate\Support\Facades\DB::table('subscriptions')->where('user_id', $user->id)->where('status', 'active')->latest('id')->first() : null;
|
|
|
|
$dbPlans = \App\Models\Plan::where('status', 'Active')->get();
|
|
if ($dbPlans->isEmpty()) {
|
|
$plans = [
|
|
[
|
|
'id' => 'basic',
|
|
'name' => 'Basic Search',
|
|
'price' => '99 AED',
|
|
'period' => 'month',
|
|
'features' => ['Browse 500+ verified workers', 'Shortlist up to 10 candidates', 'Standard OCR verification'],
|
|
'popular' => false,
|
|
],
|
|
[
|
|
'id' => 'premium',
|
|
'name' => 'Premium Employer Pass',
|
|
'price' => '199 AED',
|
|
'period' => 'month',
|
|
'features' => ['Unlimited shortlisting', 'Direct candidate messaging', 'Priority interview scheduling', 'Dedicated support'],
|
|
'popular' => true,
|
|
],
|
|
[
|
|
'id' => 'vip',
|
|
'name' => 'VIP Concierge',
|
|
'price' => '499 AED',
|
|
'period' => 'month',
|
|
'features' => ['All Premium features', 'Assigned recruitment manager', 'Background medical verification guarantee', 'Free replacement within 30 days'],
|
|
'popular' => false,
|
|
],
|
|
];
|
|
} else {
|
|
$plans = $dbPlans->map(function ($p) {
|
|
$features = is_string($p->features) ? json_decode($p->features, true) : $p->features;
|
|
return [
|
|
'id' => $p->id,
|
|
'name' => $p->name,
|
|
'price' => round($p->price) . ' AED',
|
|
'period' => strtolower($p->duration) === 'monthly' ? 'month' : (strtolower($p->duration) === 'yearly' ? 'year' : 'period'),
|
|
'features' => $features ?: [],
|
|
'popular' => $p->id === 'premium',
|
|
];
|
|
})->toArray();
|
|
}
|
|
|
|
$planName = 'Premium Employer Pass';
|
|
$expiresAt = '2026-12-31';
|
|
|
|
if ($sub) {
|
|
$expiresAt = date('Y-m-d', strtotime($sub->expires_at));
|
|
$associatedPlan = \App\Models\Plan::find($sub->plan_id);
|
|
$planName = $associatedPlan ? $associatedPlan->name : (ucfirst($sub->plan_id) . ' Pass');
|
|
}
|
|
|
|
$invoices = [];
|
|
if ($user) {
|
|
$invoices = \Illuminate\Support\Facades\DB::table('subscriptions')
|
|
->leftJoin('plans', 'subscriptions.plan_id', '=', 'plans.id')
|
|
->where('subscriptions.user_id', $user->id)
|
|
->orderBy('subscriptions.created_at', 'desc')
|
|
->select('subscriptions.*', 'plans.name as plan_name')
|
|
->get()
|
|
->map(function($s) {
|
|
$planLabel = $s->plan_name ?: (ucfirst($s->plan_id) . ' Pass');
|
|
$subStatus = strtolower($s->status);
|
|
if ($subStatus !== 'active' && $subStatus !== 'pending' && $subStatus !== 'expired') {
|
|
$subStatus = 'expired';
|
|
}
|
|
return [
|
|
'id' => 'INV-' . date('Y', strtotime($s->created_at)) . '-' . str_pad($s->id, 3, '0', STR_PAD_LEFT),
|
|
'plan_name' => $planLabel,
|
|
'purchase_date' => date('M d, Y', strtotime($s->created_at)),
|
|
'activation_date' => $s->starts_at ? date('M d, Y', strtotime($s->starts_at)) : 'N/A',
|
|
'expiry_date' => $s->expires_at ? date('M d, Y', strtotime($s->expires_at)) : 'N/A',
|
|
'amount' => round($s->amount_aed) . ' AED',
|
|
'payment_status' => 'Paid',
|
|
'status' => ucfirst($subStatus),
|
|
];
|
|
})->toArray();
|
|
}
|
|
|
|
return Inertia::render('Employer/Subscription', [
|
|
'currentPlan' => $planName,
|
|
'expiresAt' => $expiresAt,
|
|
'plans' => $plans,
|
|
'invoices' => $invoices
|
|
]);
|
|
})->name('employer.subscription');
|
|
|
|
Route::post('/subscription/purchase', [\App\Http\Controllers\Employer\PaymentController::class, 'purchase'])->name('employer.subscription.purchase');
|
|
|
|
Route::get('/messages', [\App\Http\Controllers\Employer\MessageController::class, 'index'])->name('employer.messages');
|
|
Route::get('/messages/{id}', [\App\Http\Controllers\Employer\MessageController::class, 'show'])->name('employer.messages.show');
|
|
Route::post('/messages/{id}/send', [\App\Http\Controllers\Employer\MessageController::class, 'send'])->name('employer.messages.send');
|
|
Route::get('/messages/start/{workerId}', [\App\Http\Controllers\Employer\MessageController::class, 'startConversation'])->name('employer.messages.start');
|
|
|
|
Route::get('/shortlist', [\App\Http\Controllers\Employer\ShortlistController::class, 'index'])->name('employer.shortlist');
|
|
Route::post('/shortlist/toggle', [\App\Http\Controllers\Employer\ShortlistController::class, 'toggle'])->name('employer.shortlist.toggle');
|
|
Route::post('/shortlist/{id}/remove', [\App\Http\Controllers\Employer\ShortlistController::class, 'remove'])->name('employer.shortlist.remove');
|
|
|
|
Route::get('/candidates', [\App\Http\Controllers\Employer\CandidateController::class, 'index'])->name('employer.candidates');
|
|
Route::post('/candidates/{id}/status', [\App\Http\Controllers\Employer\CandidateController::class, 'updateStatus'])->name('employer.candidates.status');
|
|
|
|
Route::get('/events', [\App\Http\Controllers\Employer\AnnouncementController::class, 'index'])->name('employer.events');
|
|
Route::post('/events/create', [\App\Http\Controllers\Employer\AnnouncementController::class, 'store'])->name('employer.events.store');
|
|
|
|
Route::get('/profile', [\App\Http\Controllers\Employer\ProfileController::class, 'index'])->name('employer.profile');
|
|
Route::get('/profile/edit', [\App\Http\Controllers\Employer\ProfileController::class, 'edit'])->name('employer.profile.edit');
|
|
Route::post('/profile/update', [\App\Http\Controllers\Employer\ProfileController::class, 'update'])->name('employer.profile.update');
|
|
|
|
Route::get('/payments', [\App\Http\Controllers\Employer\PaymentController::class, 'index'])->name('employer.payments');
|
|
|
|
// Employer Support Tickets
|
|
Route::get('/support', [\App\Http\Controllers\Employer\SupportTicketController::class, 'index'])->name('employer.support.index');
|
|
Route::get('/support/create', [\App\Http\Controllers\Employer\SupportTicketController::class, 'create'])->name('employer.support.create');
|
|
Route::post('/support/create', [\App\Http\Controllers\Employer\SupportTicketController::class, 'store'])->name('employer.support.store');
|
|
Route::get('/support/{id}', [\App\Http\Controllers\Employer\SupportTicketController::class, 'show'])->name('employer.support.show');
|
|
Route::post('/support/{id}/reply', [\App\Http\Controllers\Employer\SupportTicketController::class, 'reply'])->name('employer.support.reply');
|
|
});
|
|
|
|
Route::get('/api/documentation', function () {
|
|
return view('swagger');
|
|
})->name('api.documentation');
|
|
|
|
Route::redirect('/api/documention', '/api/documentation');
|
|
|