Ajout de la section notes d'entretien pour les candidats
This commit is contained in:
@@ -116,6 +116,19 @@ class CandidateController extends Controller
|
|||||||
return back()->with('success', 'Documents mis à jour avec succès.');
|
return back()->with('success', 'Documents mis à jour avec succès.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function updateNotes(Request $request, Candidate $candidate)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'notes' => 'nullable|string',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$candidate->update([
|
||||||
|
'notes' => $request->notes,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return back()->with('success', 'Notes mises à jour avec succès.');
|
||||||
|
}
|
||||||
|
|
||||||
public function resetPassword(Candidate $candidate)
|
public function resetPassword(Candidate $candidate)
|
||||||
{
|
{
|
||||||
$password = Str::random(10);
|
$password = Str::random(10);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
|
||||||
#[Fillable(['user_id', 'phone', 'linkedin_url', 'status'])]
|
#[Fillable(['user_id', 'phone', 'linkedin_url', 'status', 'notes'])]
|
||||||
class Candidate extends Model
|
class Candidate extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('candidates', function (Blueprint $table) {
|
||||||
|
$table->longText('notes')->nullable()->after('status');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('candidates', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('notes');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -23,6 +23,10 @@ const docForm = useForm({
|
|||||||
_method: 'PUT' // For file upload via PUT in Laravel
|
_method: 'PUT' // For file upload via PUT in Laravel
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const notesForm = useForm({
|
||||||
|
notes: props.candidate.notes || ''
|
||||||
|
});
|
||||||
|
|
||||||
const openAttempts = ref([]);
|
const openAttempts = ref([]);
|
||||||
|
|
||||||
const toggleAttempt = (id) => {
|
const toggleAttempt = (id) => {
|
||||||
@@ -71,6 +75,12 @@ const updateDocuments = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const saveNotes = () => {
|
||||||
|
notesForm.patch(route('admin.candidates.update-notes', props.candidate.id), {
|
||||||
|
preserveScroll: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const openPreview = (doc) => {
|
const openPreview = (doc) => {
|
||||||
selectedDocument.value = doc;
|
selectedDocument.value = doc;
|
||||||
};
|
};
|
||||||
@@ -204,6 +214,42 @@ const openPreview = (doc) => {
|
|||||||
|
|
||||||
<!-- Main: Attempts -->
|
<!-- Main: Attempts -->
|
||||||
<div class="xl:col-span-2 space-y-8">
|
<div class="xl:col-span-2 space-y-8">
|
||||||
|
<!-- Notes Section -->
|
||||||
|
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-sm border border-slate-200 dark:border-slate-700 p-8">
|
||||||
|
<div class="flex items-center justify-between mb-6">
|
||||||
|
<h4 class="text-xl font-bold flex items-center gap-2">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-amber-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||||
|
</svg>
|
||||||
|
Notes d'entretien & Préparation
|
||||||
|
</h4>
|
||||||
|
<div v-if="notesForm.isDirty" class="flex items-center gap-2 animate-pulse">
|
||||||
|
<span class="text-[10px] font-black uppercase tracking-widest text-amber-600">Modifications non enregistrées</span>
|
||||||
|
<PrimaryButton @click="saveNotes" class="!px-4 !py-1 text-[10px]" :disabled="notesForm.processing">
|
||||||
|
Enregistrer
|
||||||
|
</PrimaryButton>
|
||||||
|
</div>
|
||||||
|
<div v-else class="flex items-center gap-2 text-emerald-500">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||||
|
</svg>
|
||||||
|
<span class="text-[10px] font-black uppercase tracking-widest">Enregistré</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative group">
|
||||||
|
<textarea
|
||||||
|
v-model="notesForm.notes"
|
||||||
|
rows="12"
|
||||||
|
class="w-full bg-slate-50 dark:bg-slate-900 border-none rounded-2xl p-6 text-sm selection:bg-indigo-100 dark:selection:bg-indigo-900 focus:ring-2 focus:ring-indigo-500/20 transition-all placeholder:text-slate-300 dark:placeholder:text-slate-600 leading-relaxed font-mono"
|
||||||
|
placeholder="Rédigez ici vos questions, observations ou notes pendant l'entretien..."
|
||||||
|
></textarea>
|
||||||
|
<div class="absolute bottom-4 right-4 text-[10px] font-bold text-slate-400 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||||
|
Supporte le texte brut
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-sm border border-slate-200 dark:border-slate-700 p-8">
|
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-sm border border-slate-200 dark:border-slate-700 p-8">
|
||||||
<h3 class="text-xl font-bold mb-8 flex items-center justify-between">
|
<h3 class="text-xl font-bold mb-8 flex items-center justify-between">
|
||||||
Historique des Tests
|
Historique des Tests
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ Route::middleware('auth')->group(function () {
|
|||||||
Route::middleware('admin')->prefix('admin')->name('admin.')->group(function () {
|
Route::middleware('admin')->prefix('admin')->name('admin.')->group(function () {
|
||||||
Route::get('/comparative', [\App\Http\Controllers\CandidateController::class, 'comparative'])->name('comparative');
|
Route::get('/comparative', [\App\Http\Controllers\CandidateController::class, 'comparative'])->name('comparative');
|
||||||
Route::resource('candidates', \App\Http\Controllers\CandidateController::class)->only(['index', 'store', 'show', 'destroy', 'update']);
|
Route::resource('candidates', \App\Http\Controllers\CandidateController::class)->only(['index', 'store', 'show', 'destroy', 'update']);
|
||||||
|
Route::patch('/candidates/{candidate}/notes', [\App\Http\Controllers\CandidateController::class, 'updateNotes'])->name('candidates.update-notes');
|
||||||
Route::post('/candidates/{candidate}/reset-password', [\App\Http\Controllers\CandidateController::class, 'resetPassword'])->name('candidates.reset-password');
|
Route::post('/candidates/{candidate}/reset-password', [\App\Http\Controllers\CandidateController::class, 'resetPassword'])->name('candidates.reset-password');
|
||||||
Route::get('/documents/{document}', [\App\Http\Controllers\DocumentController::class, 'show'])->name('documents.show');
|
Route::get('/documents/{document}', [\App\Http\Controllers\DocumentController::class, 'show'])->name('documents.show');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user