design: premium candidate dashboard with high contrast and better layout

This commit is contained in:
jeremy bayse
2026-04-14 18:59:09 +02:00
parent ec1fe91b35
commit 21d4aaee59
2 changed files with 73 additions and 28 deletions

View File

@@ -142,40 +142,81 @@ const getStatusColor = (status) => {
</div> </div>
</div> </div>
<div v-else class="py-12"> <div v-else class="min-h-[calc(100vh-4rem)] p-8 flex flex-col items-center justify-center bg-slate-50 dark:bg-slate-950 px-4 md:px-8">
<div class="mx-auto max-w-3xl sm:px-6 lg:px-8"> <div class="w-full max-w-4xl">
<div class="bg-white dark:bg-slate-800 p-12 rounded-3xl shadow-xl border border-slate-200 dark:border-slate-700 text-center"> <!-- Welcome Section -->
<h3 class="text-3xl font-black mb-4">Bienvenue, {{ user.name }} !</h3> <div class="mb-12 text-center">
<p class="text-slate-500 dark:text-slate-400 mb-12"> <div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-indigo-50 dark:bg-indigo-900/30 text-indigo-600 dark:text-indigo-400 text-[10px] font-black uppercase tracking-widest mb-6 border border-indigo-100 dark:border-indigo-800">
Veuillez sélectionner le test technique auquel vous avez été invité. Espace Candidat Certifié
Prenez le temps de vous installer confortablement avant de commencer. </div>
<h3 class="text-4xl md:text-5xl font-black mb-6 tracking-tight text-slate-900 dark:text-white">
Bienvenue, <span class="text-indigo-600 dark:text-indigo-400">{{ user.name }}</span> !
</h3>
<p class="text-slate-500 dark:text-slate-400 max-w-xl mx-auto leading-relaxed text-lg font-medium">
C'est l'heure de briller. Voici les défis techniques préparés spécialement pour vous par rapport à votre profil candidat.
</p> </p>
</div>
<div v-if="quizzes.length > 0" class="space-y-4"> <!-- Quizzes Grid -->
<div v-for="quiz in quizzes" :key="quiz.id" class="p-6 bg-slate-50 dark:bg-slate-900 border border-slate-200 dark:border-slate-700 rounded-2xl flex flex-col sm:flex-row items-center justify-between gap-6 group hover:border-indigo-500 transition-all duration-300"> <div v-if="quizzes && quizzes.length > 0" class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div class="text-left flex-1"> <div v-for="quiz in quizzes" :key="quiz.id"
<h4 class="text-xl font-bold group-hover:text-indigo-600 transition-colors">{{ quiz.title }}</h4> class="relative group bg-white dark:bg-slate-900 rounded-[2.5rem] p-10 shadow-2xl shadow-indigo-500/5 border border-slate-100 dark:border-slate-800 hover:border-indigo-500/50 transition-all duration-500 hover:-translate-y-2"
<p class="text-sm text-slate-500 mt-1">{{ quiz.duration_minutes }} minutes {{ quiz.description }}</p> >
</div> <!-- Icon/Decoration -->
<div class="absolute -top-4 -right-4 w-24 h-24 bg-indigo-500/10 rounded-full blur-2xl group-hover:bg-indigo-500/20 transition-all"></div>
<div v-if="quiz.has_finished_attempt" class="flex items-center gap-2 px-6 py-3 bg-emerald-50 dark:bg-emerald-900/20 border border-emerald-200 dark:border-emerald-800 rounded-xl text-emerald-600 dark:text-emerald-400 font-bold whitespace-nowrap">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <div class="relative z-10 flex flex-col h-full">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" /> <div class="mb-8 p-4 bg-slate-50 dark:bg-slate-800 rounded-2xl w-fit group-hover:bg-indigo-600 group-hover:text-white transition-all duration-300">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9l-.707.707M12 21v-1m4.243-4.243l-.707-.707m2.828-9.9l-.707.707" />
</svg> </svg>
Test effectué
</div> </div>
<Link
v-else <h4 class="text-2xl font-black mb-4 tracking-tight group-hover:text-indigo-600 dark:group-hover:text-indigo-400 transition-colors">{{ quiz.title }}</h4>
:href="route('quizzes.take', quiz.id)" <p class="text-slate-500 dark:text-slate-400 text-sm mb-10 leading-relaxed line-clamp-2">
class="bg-indigo-600 text-white px-8 py-3 rounded-xl font-bold hover:bg-slate-900 dark:hover:bg-white dark:hover:text-slate-900 transition-all duration-300 shadow-lg shadow-indigo-600/20 active:scale-95 whitespace-nowrap" {{ quiz.description }}
> </p>
Démarrer le test
</Link> <div class="mt-auto flex items-center justify-between pt-10 border-t border-slate-50 dark:border-slate-800">
<div class="flex flex-col">
<span class="text-[10px] font-black uppercase text-slate-400 tracking-tighter">Temps Estimé</span>
<span class="text-sm font-bold">{{ quiz.duration_minutes }} Minutes</span>
</div>
<div v-if="quiz.has_finished_attempt" class="flex items-center gap-2 text-emerald-500 font-black text-xs uppercase tracking-widest bg-emerald-50 dark:bg-emerald-900/20 px-4 py-2 rounded-xl border border-emerald-100 dark:border-emerald-800">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
Terminé
</div>
<Link
v-else
:href="route('quizzes.take', quiz.id)"
class="inline-flex items-center justify-center px-10 py-4 bg-slate-900 dark:bg-white text-white dark:text-slate-900 rounded-2xl font-black text-sm hover:bg-indigo-600 dark:hover:bg-indigo-400 dark:hover:text-white transition-all duration-300 shadow-xl shadow-slate-900/10 active:scale-95 whitespace-nowrap"
>
Démarrer
</Link>
</div>
</div> </div>
</div> </div>
<div v-else class="py-12 text-slate-500 italic"> </div>
Aucun test ne vous est assigné pour le moment.
<!-- Empty State -->
<div v-else class="text-center p-20 bg-white dark:bg-slate-900 rounded-[3rem] shadow-2xl shadow-indigo-500/5 border border-slate-100 dark:border-slate-800">
<div class="mb-8 inline-flex p-6 bg-slate-50 dark:bg-slate-800 rounded-full text-slate-300">
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div> </div>
<h4 class="text-2xl font-black mb-4">Aucun test assigné</h4>
<p class="text-slate-500 dark:text-slate-400 max-w-sm mx-auto leading-relaxed">
Votre dossier est en cours de traitement. Un administrateur vous assignera des tests techniques après validation de votre candidature.
</p>
</div>
<!-- Footer Support -->
<div class="mt-12 text-center">
<p class="text-[10px] font-black uppercase text-slate-300 dark:text-slate-600 tracking-[0.2em]">RecruitQuizz Platform v{{ $page.props.app_version }}</p>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -48,8 +48,12 @@ Route::get('/dashboard', function () {
->values() ->values()
->all(); ->all();
} else { } else {
$candidate = auth()->user()->candidate?->load('jobPosition.quizzes'); $candidate = auth()->user()->candidate;
if ($candidate) {
$candidate->load('jobPosition.quizzes');
}
$quizzes = ($candidate && $candidate->jobPosition) $quizzes = ($candidate && $candidate->jobPosition)
? $candidate->jobPosition->quizzes ? $candidate->jobPosition->quizzes
: collect(); : collect();