Support Markdown avec guide de syntaxe pour les notes d'entretien

This commit is contained in:
jeremy bayse
2026-03-20 11:06:14 +01:00
parent 27200a6839
commit eeb8d53752
4 changed files with 108 additions and 88 deletions

View File

@@ -2,6 +2,7 @@
import AdminLayout from '@/Layouts/AdminLayout.vue';
import { Head, Link, router, useForm, usePage } from '@inertiajs/vue3';
import { ref, computed } from 'vue';
import { marked } from 'marked';
import Modal from '@/Components/Modal.vue';
import SecondaryButton from '@/Components/SecondaryButton.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
@@ -27,6 +28,9 @@ const notesForm = useForm({
notes: props.candidate.notes || ''
});
const isPreview = ref(false);
const renderedNotes = computed(() => marked.parse(notesForm.notes || ''));
const openAttempts = ref([]);
const toggleAttempt = (id) => {
@@ -223,29 +227,72 @@ const openPreview = (doc) => {
</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 class="flex items-center gap-4">
<div class="flex items-center bg-slate-100 dark:bg-slate-900 p-1 rounded-xl">
<button
@click="isPreview = false"
class="px-4 py-1.5 text-[10px] font-black uppercase tracking-widest rounded-lg transition-all"
:class="!isPreview ? 'bg-white dark:bg-slate-800 shadow-sm text-indigo-600' : 'text-slate-500'"
>
Édition
</button>
<button
@click="isPreview = true"
class="px-4 py-1.5 text-[10px] font-black uppercase tracking-widest rounded-lg transition-all"
:class="isPreview ? 'bg-white dark:bg-slate-800 shadow-sm text-indigo-600' : 'text-slate-500'"
>
Aperçu
</button>
</div>
<div v-if="notesForm.isDirty" class="flex items-center gap-2 animate-pulse">
<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 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>
<!-- Markdown Help Guide -->
<div v-if="!isPreview" class="mb-6 grid grid-cols-2 md:grid-cols-4 gap-2">
<div class="p-2 border border-slate-100 dark:border-slate-700/50 rounded-lg text-[10px] text-slate-500 dark:text-slate-400">
<code class="text-indigo-500 font-bold"># Titre</code>, <code class="text-indigo-500 font-bold">## Sous-titre</code>
</div>
<div class="p-2 border border-slate-100 dark:border-slate-700/50 rounded-lg text-[10px] text-slate-500 dark:text-slate-400">
<code class="text-indigo-500 font-bold">**Gras**</code>, <code class="text-indigo-500 font-bold">*Italique*</code>
</div>
<div class="p-2 border border-slate-100 dark:border-slate-700/50 rounded-lg text-[10px] text-slate-500 dark:text-slate-400">
<code class="text-indigo-500 font-bold">* Liste</code>, <code class="text-indigo-500 font-bold">1. Liste num.</code>
</div>
<div class="p-2 border border-slate-100 dark:border-slate-700/50 rounded-lg text-[10px] text-slate-500 dark:text-slate-400">
<code class="text-indigo-500 font-bold">> Citation</code>, <code class="text-indigo-500 font-bold">--- (Ligne)</code>
</div>
</div>
<div class="relative group">
<div v-if="isPreview"
class="prose dark:prose-invert prose-slate max-w-none w-full bg-slate-50 dark:bg-slate-900 rounded-2xl p-8 min-h-[300px] text-sm leading-relaxed"
v-html="renderedNotes">
</div>
<textarea
v-else
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..."
placeholder="Rédigez ici vos questions (utilisez # pour les titres, * pour les listes...)"
></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 v-if="!isPreview" class="absolute bottom-4 right-4 text-[9px] font-bold text-slate-400 opacity-60 flex items-center gap-1">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M2.166 4.999A11.954 11.954 0 0010 1.944 11.954 11.954 0 0017.834 5c.11.65.166 1.32.166 2.001 0 5.225-3.34 9.67-8 11.317C5.34 16.67 2 12.225 2 7c0-.682.057-1.35.166-2.001zm11.541 3.708a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
Markdown Supporté
</div>
</div>
</div>