Files
RecruIT/resources/js/Pages/Admin/Comparative.vue
jeremy bayse a55a33ae2a Initial commit
2026-03-20 08:25:58 +01:00

125 lines
6.4 KiB
Vue

<script setup>
import AdminLayout from '@/Layouts/AdminLayout.vue';
import { Head, Link } from '@inertiajs/vue3';
import { ref, computed } from 'vue';
const props = defineProps({
candidates: Array
});
const searchQuery = ref('');
const filteredCandidates = computed(() => {
return props.candidates.filter(c =>
c.user.name.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
c.user.email.toLowerCase().includes(searchQuery.value.toLowerCase())
).sort((a, b) => {
const scoreA = a.attempts[0]?.score || 0;
const scoreB = b.attempts[0]?.score || 0;
return scoreB - scoreA;
});
});
const getScorePercentage = (candidate) => {
const attempt = candidate.attempts[0];
if (!attempt || !attempt.quiz) return 0;
// Total points possible (this would ideally be passed from backend or calculated)
// For now, we assume attempt.score is the absolute score.
return attempt.score;
};
const formatDuration = (started, finished) => {
if (!started || !finished) return '--';
const start = new Date(started);
const end = new Date(finished);
const diff = Math.floor((end - start) / 1000 / 60);
return diff + ' min';
};
</script>
<template>
<Head title="Comparateur de Candidats" />
<AdminLayout>
<template #header>
Comparateur de Candidats
</template>
<div class="mb-8 flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
<h3 class="text-2xl font-bold">Classement par Score</h3>
<div class="relative w-full sm:w-64">
<span class="absolute inset-y-0 left-0 pl-3 flex items-center text-slate-400">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</span>
<input
v-model="searchQuery"
type="text"
placeholder="Rechercher..."
class="block w-full pl-10 pr-3 py-2 border border-slate-300 dark:border-slate-700 rounded-lg leading-5 bg-white dark:bg-slate-800 placeholder-slate-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm transition-all"
>
</div>
</div>
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-sm border border-slate-200 dark:border-slate-700 overflow-hidden">
<table class="w-full text-left">
<thead class="bg-slate-50 dark:bg-slate-700/50 border-b border-slate-200 dark:border-slate-700">
<tr>
<th class="px-6 py-4 font-bold text-slate-700 dark:text-slate-300 uppercase tracking-wider text-xs">Rang</th>
<th class="px-6 py-4 font-bold text-slate-700 dark:text-slate-300 uppercase tracking-wider text-xs">Candidat</th>
<th class="px-6 py-4 font-bold text-slate-700 dark:text-slate-300 uppercase tracking-wider text-xs text-center">Score</th>
<th class="px-6 py-4 font-bold text-slate-700 dark:text-slate-300 uppercase tracking-wider text-xs">Temps passé</th>
<th class="px-6 py-4 font-bold text-slate-700 dark:text-slate-300 uppercase tracking-wider text-xs">Test</th>
<th class="px-6 py-4 font-bold text-slate-700 dark:text-slate-300 uppercase tracking-wider text-xs text-right">Date</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
<tr v-for="(candidate, index) in filteredCandidates" :key="candidate.id" class="hover:bg-slate-50/50 dark:hover:bg-slate-700/30 transition-colors group">
<td class="px-6 py-4">
<div
class="w-8 h-8 rounded-full flex items-center justify-center font-bold text-sm"
:class="[
index === 0 ? 'bg-yellow-100 text-yellow-700' :
index === 1 ? 'bg-slate-200 text-slate-700' :
index === 2 ? 'bg-orange-100 text-orange-700' : 'text-slate-500'
]"
>
{{ index + 1 }}
</div>
</td>
<td class="px-6 py-4">
<div class="font-bold text-slate-900 dark:text-slate-100">{{ candidate.user.name }}</div>
<div class="text-xs text-slate-500">{{ candidate.user.email }}</div>
</td>
<td class="px-6 py-4">
<div class="flex flex-col items-center">
<span class="text-xl font-black text-indigo-600 dark:text-indigo-400">{{ candidate.attempts[0]?.score }}</span>
<span class="text-[10px] uppercase font-bold text-slate-400">Points</span>
</div>
</td>
<td class="px-6 py-4 text-slate-600 dark:text-slate-400 font-medium">
{{ formatDuration(candidate.attempts[0]?.started_at, candidate.attempts[0]?.finished_at) }}
</td>
<td class="px-6 py-4">
<span class="text-sm px-2 py-1 bg-slate-100 dark:bg-slate-700 rounded-md font-medium">
{{ candidate.attempts[0]?.quiz?.title }}
</span>
</td>
<td class="px-6 py-4 text-right text-slate-500 text-sm">
{{ new Date(candidate.attempts[0]?.finished_at).toLocaleDateString() }}
</td>
</tr>
<tr v-if="filteredCandidates.length === 0">
<td colspan="6" class="px-6 py-12 text-center text-slate-500 italic">
Aucun candidat n'a encore terminé de test.
</td>
</tr>
</tbody>
</table>
</div>
</AdminLayout>
</template>