From 9edf79e8bab03c63b28f41ed372b9b779ce09825 Mon Sep 17 00:00:00 2001 From: jeremy bayse Date: Sat, 9 May 2026 11:21:40 +0200 Subject: [PATCH] feat: implementation du role Gestionnaire RH et refonte de la gestion des offres --- app/Http/Controllers/CandidateController.php | 77 +++- .../Controllers/JobPositionController.php | 10 +- .../PublicJobApplicationController.php | 61 ++- app/Http/Controllers/TenantController.php | 8 +- app/Http/Controllers/UserController.php | 10 +- app/Http/Middleware/RestrictHrManager.php | 24 ++ app/Models/Candidate.php | 3 +- app/Models/JobPosition.php | 3 +- app/Models/User.php | 7 +- bootstrap/app.php | 1 + ..._add_expires_at_to_job_positions_table.php | 28 ++ ..._add_detailed_info_to_candidates_table.php | 50 +++ resources/js/Layouts/AdminLayout.vue | 24 +- resources/js/Pages/Admin/Candidates/Index.vue | 26 +- resources/js/Pages/Admin/Candidates/Show.vue | 225 +++++++++-- .../js/Pages/Admin/JobPositions/Index.vue | 241 ++++++++++-- resources/js/Pages/Admin/Users/Index.vue | 4 +- resources/js/Pages/Dashboard.vue | 22 +- resources/js/Pages/Public/Jobs/Index.vue | 4 + resources/js/Pages/Public/Jobs/Show.vue | 368 +++++++++++++----- resources/js/Pages/Public/PrivacyPolicy.vue | 184 +++++++++ resources/js/Pages/Welcome.vue | 10 +- routes/web.php | 65 +++- 23 files changed, 1223 insertions(+), 232 deletions(-) create mode 100644 app/Http/Middleware/RestrictHrManager.php create mode 100644 database/migrations/2026_05_09_073449_add_expires_at_to_job_positions_table.php create mode 100644 database/migrations/2026_05_09_080323_add_detailed_info_to_candidates_table.php create mode 100644 resources/js/Pages/Public/PrivacyPolicy.vue diff --git a/app/Http/Controllers/CandidateController.php b/app/Http/Controllers/CandidateController.php index 3728b16..f7d1f97 100644 --- a/app/Http/Controllers/CandidateController.php +++ b/app/Http/Controllers/CandidateController.php @@ -93,11 +93,20 @@ class CandidateController extends Controller public function store(Request $request) { $request->validate([ - 'name' => 'required|string|max:255', + 'birth_name' => 'nullable|string|max:255', + 'usage_name' => 'nullable|string|max:255', + 'first_name' => 'nullable|string|max:255', + 'address' => 'nullable|string|max:255', + 'zip_code' => 'nullable|string|max:10', 'email' => 'required|string|email|max:255|unique:users', 'phone' => 'nullable|string|max:20', - 'linkedin_url' => 'nullable|url|max:255', 'city' => 'nullable|string|max:255', + 'birth_date' => 'nullable|date', + 'birth_place' => 'nullable|string|max:255', + 'nationality' => 'nullable|string|max:255', + 'current_situation' => 'nullable|string|max:255', + 'education_level' => 'nullable|string|max:255', + 'has_driving_license' => 'nullable|boolean', 'cv' => 'nullable|mimes:pdf|max:5120', 'cover_letter' => 'nullable|mimes:pdf|max:5120', 'tenant_id' => 'nullable|exists:tenants,id', @@ -106,20 +115,34 @@ class CandidateController extends Controller $password = Str::random(10); + $name = $request->first_name + ? ($request->first_name . ' ' . ($request->usage_name ?? '')) + : $request->name; + $user = User::create([ - 'name' => $request->name, + 'name' => $name, 'email' => $request->email, - 'password' => Hash::make(Str::random(12)), + 'password' => Hash::make($password), 'role' => 'candidate', - 'tenant_id' => auth()->user()->isSuperAdmin() ? $request->tenant_id : auth()->user()->tenant_id, + 'tenant_id' => (auth()->user()->isSuperAdmin() || auth()->user()->isGestionnaireRH()) ? $request->tenant_id : auth()->user()->tenant_id, ]); $candidate = $user->candidate()->create([ + 'birth_name' => $request->birth_name, + 'usage_name' => $request->usage_name, + 'first_name' => $request->first_name, + 'address' => $request->address, + 'zip_code' => $request->zip_code, 'phone' => $request->phone, - 'linkedin_url' => $request->linkedin_url, 'city' => $request->city, + 'birth_date' => $request->birth_date, + 'birth_place' => $request->birth_place, + 'nationality' => $request->nationality, + 'current_situation' => $request->current_situation, + 'education_level' => $request->education_level, + 'has_driving_license' => $request->has_driving_license ?? false, 'status' => 'en_attente', - 'tenant_id' => auth()->user()->isSuperAdmin() ? $request->tenant_id : auth()->user()->tenant_id, + 'tenant_id' => (auth()->user()->isSuperAdmin() || auth()->user()->isGestionnaireRH()) ? $request->tenant_id : auth()->user()->tenant_id, 'job_position_id' => $request->job_position_id, ]); @@ -165,7 +188,7 @@ class CandidateController extends Controller ] ]; - if (auth()->user()->isSuperAdmin()) { + if (auth()->user()->isSuperAdmin() || auth()->user()->isGestionnaireRH()) { $data['tenants'] = \App\Models\Tenant::orderBy('name')->get(); } @@ -190,22 +213,42 @@ class CandidateController extends Controller public function update(Request $request, Candidate $candidate) { $request->validate([ + 'birth_name' => 'nullable|string|max:255', + 'usage_name' => 'nullable|string|max:255', + 'first_name' => 'nullable|string|max:255', + 'address' => 'nullable|string|max:255', + 'zip_code' => 'nullable|string|max:10', + 'phone' => 'nullable|string|max:255', + 'city' => 'nullable|string|max:255', + 'birth_date' => 'nullable|date', + 'birth_place' => 'nullable|string|max:255', + 'nationality' => 'nullable|string|max:255', + 'current_situation' => 'nullable|string|max:255', + 'education_level' => 'nullable|string|max:255', + 'has_driving_license' => 'nullable|boolean', + 'email' => 'nullable|string|email|max:255|unique:users,email,' . $candidate->user_id, + 'linkedin_url' => 'nullable|url|max:255', 'cv' => 'nullable|file|mimes:pdf|max:5120', 'cover_letter' => 'nullable|file|mimes:pdf|max:5120', - 'name' => 'nullable|string|max:255', - 'email' => 'nullable|string|email|max:255|unique:users,email,' . $candidate->user_id, - 'phone' => 'nullable|string|max:255', - 'linkedin_url' => 'nullable|url|max:255', - 'city' => 'nullable|string|max:255', ]); // Update User info if name or email present - if ($request->has('name') || $request->has('email')) { - $candidate->user->update($request->only(['name', 'email'])); + if ($request->has('email')) { + $candidate->user->update(['email' => $request->email]); + } + + if ($request->has('first_name') || $request->has('usage_name')) { + $firstName = $request->first_name ?? $candidate->first_name; + $usageName = $request->usage_name ?? $candidate->usage_name; + $candidate->user->update(['name' => $firstName . ' ' . $usageName]); } // Update Candidate info - $candidate->update($request->only(['phone', 'linkedin_url', 'city'])); + $candidate->update($request->only([ + 'birth_name', 'usage_name', 'first_name', 'address', 'zip_code', + 'phone', 'linkedin_url', 'city', 'birth_date', 'birth_place', + 'nationality', 'current_situation', 'education_level', 'has_driving_license' + ])); if ($request->hasFile('cv')) { $this->replaceDocument($candidate, $request->file('cv'), 'cv'); @@ -263,7 +306,7 @@ class CandidateController extends Controller public function updateTenant(Request $request, Candidate $candidate) { - if (!auth()->user()->isSuperAdmin()) { + if (!auth()->user()->isSuperAdmin() && !auth()->user()->isGestionnaireRH()) { abort(403); } diff --git a/app/Http/Controllers/JobPositionController.php b/app/Http/Controllers/JobPositionController.php index 4d237c8..8b0022a 100644 --- a/app/Http/Controllers/JobPositionController.php +++ b/app/Http/Controllers/JobPositionController.php @@ -13,7 +13,7 @@ class JobPositionController extends Controller $this->authorizeAdmin(); return Inertia::render('Admin/JobPositions/Index', [ - 'jobPositions' => JobPosition::with(['tenant', 'quizzes'])->get(), + 'jobPositions' => JobPosition::with(['tenant', 'quizzes'])->withCount('candidates')->get(), 'tenants' => \App\Models\Tenant::orderBy('name')->get(), 'quizzes' => \App\Models\Quiz::all() ]); @@ -33,6 +33,7 @@ class JobPositionController extends Controller 'tenant_id' => 'nullable|exists:tenants,id', 'quiz_ids' => 'nullable|array', 'quiz_ids.*' => 'exists:quizzes,id', + 'expires_at' => 'nullable|date', ]); $jobPosition = JobPosition::create([ @@ -42,7 +43,8 @@ class JobPositionController extends Controller 'ai_prompt' => $request->ai_prompt, 'ai_bypass_base_prompt' => $request->boolean('ai_bypass_base_prompt'), 'fpt_metadata' => $request->fpt_metadata, - 'tenant_id' => auth()->user()->isSuperAdmin() ? $request->tenant_id : auth()->user()->tenant_id, + 'tenant_id' => (auth()->user()->isSuperAdmin() || auth()->user()->isGestionnaireRH()) ? $request->tenant_id : auth()->user()->tenant_id, + 'expires_at' => $request->expires_at, ]); $jobPosition->quizzes()->sync($request->input('quiz_ids', [])); @@ -64,6 +66,7 @@ class JobPositionController extends Controller 'tenant_id' => 'nullable|exists:tenants,id', 'quiz_ids' => 'nullable|array', 'quiz_ids.*' => 'exists:quizzes,id', + 'expires_at' => 'nullable|date', ]); $jobPosition->update([ @@ -73,7 +76,8 @@ class JobPositionController extends Controller 'ai_prompt' => $request->ai_prompt, 'ai_bypass_base_prompt' => $request->boolean('ai_bypass_base_prompt'), 'fpt_metadata' => $request->fpt_metadata, - 'tenant_id' => auth()->user()->isSuperAdmin() ? $request->tenant_id : auth()->user()->tenant_id, + 'tenant_id' => (auth()->user()->isSuperAdmin() || auth()->user()->isGestionnaireRH()) ? $request->tenant_id : auth()->user()->tenant_id, + 'expires_at' => $request->expires_at, ]); $jobPosition->quizzes()->sync($request->input('quiz_ids', [])); diff --git a/app/Http/Controllers/PublicJobApplicationController.php b/app/Http/Controllers/PublicJobApplicationController.php index 8c0e065..c4d8e08 100644 --- a/app/Http/Controllers/PublicJobApplicationController.php +++ b/app/Http/Controllers/PublicJobApplicationController.php @@ -16,10 +16,17 @@ class PublicJobApplicationController extends Controller { public function index() { - $jobs = JobPosition::with('tenant')->orderBy('created_at', 'desc')->get()->map(function($job) { - $job->description = strip_tags(\Illuminate\Support\Str::markdown($job->description)); - return $job; - }); + $jobs = JobPosition::with('tenant') + ->where(function($q) { + $q->whereNull('expires_at') + ->orWhere('expires_at', '>=', now()); + }) + ->orderBy('created_at', 'desc') + ->get() + ->map(function($job) { + $job->description = strip_tags(\Illuminate\Support\Str::markdown($job->description)); + return $job; + }); return Inertia::render('Public/Jobs/Index', [ 'jobs' => $jobs @@ -28,6 +35,10 @@ class PublicJobApplicationController extends Controller public function show(JobPosition $jobPosition) { + if ($jobPosition->expires_at && $jobPosition->expires_at->isPast()) { + abort(404); + } + $data = $jobPosition->toArray(); $data['description_html'] = \Illuminate\Support\Str::markdown($jobPosition->description); @@ -38,12 +49,26 @@ class PublicJobApplicationController extends Controller public function store(Request $request, JobPosition $jobPosition) { + if ($jobPosition->expires_at && $jobPosition->expires_at->isPast()) { + return back()->withErrors(['error' => 'Cette offre a expiré.']); + } + $request->validate([ - 'name' => 'required|string|max:255', - 'email' => 'required|string|email|max:255|unique:users', - 'phone' => 'nullable|string|max:20', - 'linkedin_url' => 'nullable|url|max:255', - 'city' => 'nullable|string|max:255', + 'birth_name' => 'required|string|max:255', + 'usage_name' => 'required|string|max:255', + 'first_name' => 'required|string|max:255', + 'address' => 'required|string|max:255', + 'zip_code' => 'required|string|max:10', + 'city' => 'required|string|max:255', + 'phone' => 'required|string|max:20', + 'email' => 'required|string|email|max:255|unique:users|confirmed', + 'birth_date' => 'required|date', + 'birth_place' => 'required|string|max:255', + 'nationality' => 'required|string|max:255', + 'current_situation' => 'required|string|max:255', + 'education_level' => 'required|string|max:255', + 'has_driving_license' => 'required|boolean', + 'privacy_policy' => 'accepted', 'cv' => 'nullable|mimes:pdf|max:5120', 'cover_letter' => 'nullable|mimes:pdf|max:5120', ]); @@ -51,7 +76,7 @@ class PublicJobApplicationController extends Controller $password = Str::random(10); $user = User::create([ - 'name' => $request->name, + 'name' => $request->first_name . ' ' . $request->usage_name, 'email' => $request->email, 'password' => Hash::make($password), 'role' => 'candidate', @@ -59,9 +84,19 @@ class PublicJobApplicationController extends Controller ]); $candidate = $user->candidate()->create([ - 'phone' => $request->phone, - 'linkedin_url' => $request->linkedin_url, + 'birth_name' => $request->birth_name, + 'usage_name' => $request->usage_name, + 'first_name' => $request->first_name, + 'address' => $request->address, + 'zip_code' => $request->zip_code, 'city' => $request->city, + 'phone' => $request->phone, + 'birth_date' => $request->birth_date, + 'birth_place' => $request->birth_place, + 'nationality' => $request->nationality, + 'current_situation' => $request->current_situation, + 'education_level' => $request->education_level, + 'has_driving_license' => $request->has_driving_license, 'status' => 'en_attente', 'tenant_id' => $jobPosition->tenant_id, 'job_position_id' => $jobPosition->id, @@ -74,7 +109,7 @@ class PublicJobApplicationController extends Controller $this->storeDocument($candidate, $request->file('cover_letter'), 'cover_letter'); } - // Auto-login the candidate so they can take the quiz immediately if they want + // Auto-login Auth::login($user); return redirect()->route('dashboard')->with('success', 'Votre candidature a bien été enregistrée. Voici votre mot de passe temporaire pour vous reconnecter : ' . $password); diff --git a/app/Http/Controllers/TenantController.php b/app/Http/Controllers/TenantController.php index d2a8ef3..af0cadf 100644 --- a/app/Http/Controllers/TenantController.php +++ b/app/Http/Controllers/TenantController.php @@ -10,7 +10,7 @@ class TenantController extends Controller { public function index() { - if (!auth()->user()->isSuperAdmin()) { + if (!auth()->user()->isSuperAdmin() && !auth()->user()->isGestionnaireRH()) { abort(403, 'Unauthorized action.'); } @@ -23,7 +23,7 @@ class TenantController extends Controller public function store(Request $request) { - if (!auth()->user()->isSuperAdmin()) { + if (!auth()->user()->isSuperAdmin() && !auth()->user()->isGestionnaireRH()) { abort(403, 'Unauthorized action.'); } @@ -38,7 +38,7 @@ class TenantController extends Controller public function update(Request $request, Tenant $tenant) { - if (!auth()->user()->isSuperAdmin()) { + if (!auth()->user()->isSuperAdmin() && !auth()->user()->isGestionnaireRH()) { abort(403, 'Unauthorized action.'); } @@ -53,7 +53,7 @@ class TenantController extends Controller public function destroy(Tenant $tenant) { - if (!auth()->user()->isSuperAdmin()) { + if (!auth()->user()->isSuperAdmin() && !auth()->user()->isGestionnaireRH()) { abort(403, 'Unauthorized action.'); } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index e4e8649..9efb207 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -18,7 +18,7 @@ class UserController extends Controller abort(403, 'Unauthorized action.'); } - $users = User::whereIn('role', ['admin', 'super_admin']) + $users = User::whereIn('role', ['admin', 'super_admin', 'gestionnaire_rh']) ->with('tenant') ->orderBy('name') ->get(); @@ -40,7 +40,7 @@ class UserController extends Controller $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:users', - 'role' => ['required', Rule::in(['admin', 'super_admin'])], + 'role' => ['required', Rule::in(['admin', 'super_admin', 'gestionnaire_rh'])], 'tenant_id' => 'nullable|exists:tenants,id', ]); @@ -51,7 +51,7 @@ class UserController extends Controller 'email' => $request->email, 'password' => Hash::make($password), 'role' => $request->role, - 'tenant_id' => $request->role === 'super_admin' ? null : $request->tenant_id, + 'tenant_id' => ($request->role === 'super_admin' || $request->role === 'gestionnaire_rh') ? null : $request->tenant_id, ]); return back()->with('success', 'Administrateur créé avec succès. Mot de passe généré : ' . $password); @@ -66,7 +66,7 @@ class UserController extends Controller $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:users,email,' . $user->id, - 'role' => ['required', Rule::in(['admin', 'super_admin'])], + 'role' => ['required', Rule::in(['admin', 'super_admin', 'gestionnaire_rh'])], 'tenant_id' => 'nullable|exists:tenants,id', ]); @@ -74,7 +74,7 @@ class UserController extends Controller 'name' => $request->name, 'email' => $request->email, 'role' => $request->role, - 'tenant_id' => $request->role === 'super_admin' ? null : $request->tenant_id, + 'tenant_id' => ($request->role === 'super_admin' || $request->role === 'gestionnaire_rh') ? null : $request->tenant_id, ]); return back()->with('success', 'Administrateur mis à jour.'); diff --git a/app/Http/Middleware/RestrictHrManager.php b/app/Http/Middleware/RestrictHrManager.php new file mode 100644 index 0000000..d0906f5 --- /dev/null +++ b/app/Http/Middleware/RestrictHrManager.php @@ -0,0 +1,24 @@ +check() && auth()->user()->isGestionnaireRH()) { + abort(403); + } + + return $next($request); + } +} diff --git a/app/Models/Candidate.php b/app/Models/Candidate.php index be292ea..23998a6 100644 --- a/app/Models/Candidate.php +++ b/app/Models/Candidate.php @@ -11,7 +11,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use App\Traits\BelongsToTenant; -#[Fillable(['user_id', 'job_position_id', 'phone', 'linkedin_url', 'city', 'status', 'is_selected', 'sort_order', 'notes', 'cv_score', 'motivation_score', 'interview_score', 'interview_details', 'ai_analysis', 'tenant_id'])] +#[Fillable(['user_id', 'job_position_id', 'birth_name', 'usage_name', 'first_name', 'address', 'zip_code', 'phone', 'linkedin_url', 'city', 'birth_date', 'birth_place', 'nationality', 'current_situation', 'education_level', 'has_driving_license', 'status', 'is_selected', 'sort_order', 'notes', 'cv_score', 'motivation_score', 'interview_score', 'interview_details', 'ai_analysis', 'tenant_id'])] class Candidate extends Model { use HasFactory, BelongsToTenant; @@ -31,6 +31,7 @@ class Candidate extends Model protected $casts = [ 'ai_analysis' => 'array', 'is_selected' => 'boolean', + 'has_driving_license' => 'boolean', 'interview_details' => 'array', ]; diff --git a/app/Models/JobPosition.php b/app/Models/JobPosition.php index 3445f64..8c08817 100644 --- a/app/Models/JobPosition.php +++ b/app/Models/JobPosition.php @@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use App\Traits\BelongsToTenant; -#[Fillable(['title', 'description', 'requirements', 'ai_prompt', 'ai_bypass_base_prompt', 'gemini_cache_id', 'gemini_cache_expires_at', 'tenant_id', 'fpt_metadata'])] +#[Fillable(['title', 'description', 'requirements', 'ai_prompt', 'ai_bypass_base_prompt', 'gemini_cache_id', 'gemini_cache_expires_at', 'tenant_id', 'fpt_metadata', 'expires_at'])] class JobPosition extends Model { use HasFactory, BelongsToTenant; @@ -19,6 +19,7 @@ class JobPosition extends Model 'ai_bypass_base_prompt' => 'boolean', 'gemini_cache_expires_at' => 'datetime', 'fpt_metadata' => 'array', + 'expires_at' => 'datetime', ]; public function candidates(): HasMany diff --git a/app/Models/User.php b/app/Models/User.php index 33af870..9d96dcd 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -19,7 +19,7 @@ class User extends Authenticatable public function isAdmin(): bool { - return in_array($this->role, ['admin', 'super_admin']); + return in_array($this->role, ['admin', 'super_admin', 'gestionnaire_rh']); } public function isSuperAdmin(): bool @@ -27,6 +27,11 @@ class User extends Authenticatable return $this->role === 'super_admin'; } + public function isGestionnaireRH(): bool + { + return $this->role === 'gestionnaire_rh'; + } + public function isCandidate(): bool { return $this->role === 'candidate'; diff --git a/bootstrap/app.php b/bootstrap/app.php index 6f6ee7d..37f1021 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -20,6 +20,7 @@ return Application::configure(basePath: dirname(__DIR__)) $middleware->alias([ 'admin' => \App\Http\Middleware\AdminMiddleware::class, + 'restrict_hr' => \App\Http\Middleware\RestrictHrManager::class, ]); }) ->withExceptions(function (Exceptions $exceptions): void { diff --git a/database/migrations/2026_05_09_073449_add_expires_at_to_job_positions_table.php b/database/migrations/2026_05_09_073449_add_expires_at_to_job_positions_table.php new file mode 100644 index 0000000..dd6ce8d --- /dev/null +++ b/database/migrations/2026_05_09_073449_add_expires_at_to_job_positions_table.php @@ -0,0 +1,28 @@ +timestamp('expires_at')->nullable()->after('description'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('job_positions', function (Blueprint $table) { + $table->dropColumn('expires_at'); + }); + } +}; diff --git a/database/migrations/2026_05_09_080323_add_detailed_info_to_candidates_table.php b/database/migrations/2026_05_09_080323_add_detailed_info_to_candidates_table.php new file mode 100644 index 0000000..2411f4d --- /dev/null +++ b/database/migrations/2026_05_09_080323_add_detailed_info_to_candidates_table.php @@ -0,0 +1,50 @@ +string('birth_name')->nullable()->after('user_id'); + $table->string('usage_name')->nullable()->after('birth_name'); + $table->string('first_name')->nullable()->after('usage_name'); + $table->string('address')->nullable()->after('first_name'); + $table->string('zip_code')->nullable()->after('address'); + $table->date('birth_date')->nullable()->after('city'); + $table->string('birth_place')->nullable()->after('birth_date'); + $table->string('nationality')->nullable()->after('birth_place'); + $table->string('current_situation')->nullable()->after('nationality'); + $table->string('education_level')->nullable()->after('current_situation'); + $table->boolean('has_driving_license')->default(false)->after('education_level'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('candidates', function (Blueprint $table) { + $table->dropColumn([ + 'birth_name', + 'usage_name', + 'first_name', + 'address', + 'zip_code', + 'birth_date', + 'birth_place', + 'nationality', + 'current_situation', + 'education_level', + 'has_driving_license' + ]); + }); + } +}; diff --git a/resources/js/Layouts/AdminLayout.vue b/resources/js/Layouts/AdminLayout.vue index 3c748b3..252db54 100644 --- a/resources/js/Layouts/AdminLayout.vue +++ b/resources/js/Layouts/AdminLayout.vue @@ -10,7 +10,7 @@ * - Items nav : rounded-xl, active bg-highlight text-highlight-dark * - Footer sidebar : avatar + nom + version + logout */ -import { ref } from 'vue'; +import { ref, computed } from 'vue'; import { Link, usePage } from '@inertiajs/vue3'; import Dropdown from '@/Components/Dropdown.vue'; import DropdownLink from '@/Components/DropdownLink.vue'; @@ -42,7 +42,7 @@ const navItems = [ { route: 'admin.job-positions.index', match: 'admin.job-positions.*', - label: 'Fiches de Poste', + label: 'Offres d\'emploi', icon: 'M21 16V8a2 2 0 00-1-1.73l-7-4a2 2 0 00-2 0l-7 4A2 2 0 003 8v8a2 2 0 001 1.73l7 4a2 2 0 002 0l7-4A2 2 0 0021 16z', }, { @@ -62,6 +62,15 @@ const navItems = [ }, ]; +const filteredNavItems = computed(() => { + const role = page.props.auth.user.role; + if (role === 'gestionnaire_rh') { + // HR Managers cannot see evaluation/selection related tabs + return navItems.filter(item => !['admin.quizzes.index', 'admin.comparative', 'admin.candidates.selected'].includes(item.route)); + } + return navItems; +}); + const superAdminItems = [ { route: 'admin.tenants.index', @@ -119,7 +128,7 @@ const isActive = (item) => {