diff --git a/app/Http/Controllers/CandidateController.php b/app/Http/Controllers/CandidateController.php index d36bc48..09405fb 100644 --- a/app/Http/Controllers/CandidateController.php +++ b/app/Http/Controllers/CandidateController.php @@ -237,6 +237,15 @@ class CandidateController extends Controller $this->storeDocument($candidate, $file, $type); } + public function toggleSelection(Candidate $candidate) + { + $candidate->update([ + 'is_selected' => !$candidate->is_selected + ]); + + return back()->with('success', 'Statut de sélection mis à jour.'); + } + private function storeDocument(Candidate $candidate, $file, string $type) { if (!$file) { diff --git a/app/Models/Candidate.php b/app/Models/Candidate.php index 848ad4a..f88c850 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', 'status', 'notes', 'cv_score', 'motivation_score', 'interview_score', 'ai_analysis', 'tenant_id'])] +#[Fillable(['user_id', 'job_position_id', 'phone', 'linkedin_url', 'status', 'is_selected', 'notes', 'cv_score', 'motivation_score', 'interview_score', 'ai_analysis', 'tenant_id'])] class Candidate extends Model { use HasFactory, BelongsToTenant; @@ -30,6 +30,7 @@ class Candidate extends Model protected $casts = [ 'ai_analysis' => 'array', + 'is_selected' => 'boolean', ]; public function jobPosition(): BelongsTo diff --git a/database/migrations/2026_04_16_170459_add_is_selected_to_candidates_table.php b/database/migrations/2026_04_16_170459_add_is_selected_to_candidates_table.php new file mode 100644 index 0000000..970b526 --- /dev/null +++ b/database/migrations/2026_04_16_170459_add_is_selected_to_candidates_table.php @@ -0,0 +1,28 @@ +boolean('is_selected')->default(false)->after('status'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('candidates', function (Blueprint $table) { + $table->dropColumn('is_selected'); + }); + } +}; diff --git a/resources/js/Pages/Admin/Candidates/Index.vue b/resources/js/Pages/Admin/Candidates/Index.vue index 73fdf79..5ab6e3c 100644 --- a/resources/js/Pages/Admin/Candidates/Index.vue +++ b/resources/js/Pages/Admin/Candidates/Index.vue @@ -43,10 +43,14 @@ const submit = () => { const deleteCandidate = (id) => { if (confirm('Voulez-vous vraiment supprimer ce candidat ?')) { - router.delete(route('admin.candidates.destroy', id)); + router.delete(route('admin.candidates.destroy', id), { preserveScroll: true }); } }; +const toggleSelection = (id) => { + router.patch(route('admin.candidates.toggle-selection', id), {}, { preserveScroll: true }); +}; + const openPreview = (doc) => { selectedDocument.value = doc; }; @@ -69,11 +73,24 @@ const getNestedValue = (obj, path) => { }; const selectedJobPosition = ref(''); +const showOnlySelected = ref(false); const filteredCandidates = computed(() => { - if (selectedJobPosition.value === '') return props.candidates; - if (selectedJobPosition.value === 'none') return props.candidates.filter(c => !c.job_position_id); - return props.candidates.filter(c => c.job_position_id === selectedJobPosition.value); + let result = props.candidates; + + if (showOnlySelected.value) { + result = result.filter(c => c.is_selected); + } + + if (selectedJobPosition.value !== '') { + if (selectedJobPosition.value === 'none') { + result = result.filter(c => !c.job_position_id); + } else { + result = result.filter(c => c.job_position_id === selectedJobPosition.value); + } + } + + return result; }); const sortedCandidates = computed(() => { @@ -102,18 +119,26 @@ const sortedCandidates = computed(() => {
|
Nom
@@ -201,6 +227,16 @@ const sortedCandidates = computed(() => {
| ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| + + |
{{ candidate.user.name }}
{{ candidate.phone }}
@@ -294,7 +330,7 @@ const sortedCandidates = computed(() => {
|
|||||||||||||
| + | Aucun candidat trouvé. | |||||||||||||