AI Analysis: add support for multiple providers (OpenAI, Claude, Gemini)

This commit is contained in:
jeremy bayse
2026-03-25 07:29:39 +01:00
parent e02c6849fe
commit e3b1a2583f
3 changed files with 149 additions and 36 deletions

View File

@@ -122,6 +122,7 @@ const updateAnswerScore = (answerId, score) => {
const aiAnalysis = ref(props.candidate.ai_analysis || null);
const isAnalyzing = ref(false);
const selectedProvider = ref('ollama');
const runAI = async () => {
if (!props.candidate.job_position_id) {
@@ -131,7 +132,14 @@ const runAI = async () => {
isAnalyzing.value = true;
try {
const response = await fetch(route('admin.candidates.analyze', props.candidate.id));
const response = await fetch(route('admin.candidates.analyze', props.candidate.id), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
},
body: JSON.stringify({ provider: selectedProvider.value })
});
const data = await response.json();
if (data.error) {
alert(data.error);
@@ -363,37 +371,52 @@ const runAI = async () => {
<!-- AI Analysis Section -->
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-sm border border-slate-200 dark:border-slate-700 p-8 overflow-hidden relative">
<div class="flex items-center justify-between mb-8">
<div class="flex flex-col md:flex-row md:items-center justify-between gap-6 mb-8">
<div>
<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-indigo-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
Analyse d'Adéquation IA
Intelligence Artificielle
</h4>
<p class="text-xs text-slate-400 mt-1 uppercase font-bold tracking-widest">Matching CV/Lettre vs Fiche de poste</p>
<p class="text-xs text-slate-400 mt-1 uppercase font-bold tracking-widest">Choisir l'IA pour l'analyse du matching</p>
</div>
<PrimaryButton
@click="runAI"
:disabled="isAnalyzing"
class="!bg-indigo-600 hover:!bg-indigo-500 !border-none !rounded-xl group"
>
<span v-if="isAnalyzing" class="flex items-center gap-2">
<svg class="animate-spin h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Analyse en cours...
</span>
<span v-else class="flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 group-hover:scale-110 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
Lancer l'analyse intelligente
</span>
</PrimaryButton>
<div class="flex flex-wrap items-center gap-4">
<!-- Provider Selector -->
<div class="flex items-center bg-slate-100 dark:bg-slate-900/50 p-1.5 rounded-2xl border border-slate-200 dark:border-slate-800">
<button
v-for="provider in ['ollama', 'openai', 'anthropic', 'gemini']"
:key="provider"
@click="selectedProvider = provider"
class="px-4 py-2 text-[10px] font-black uppercase tracking-widest rounded-xl transition-all"
:class="selectedProvider === provider ? 'bg-white dark:bg-slate-800 shadow-sm text-indigo-600' : 'text-slate-400 hover:text-slate-600 dark:hover:text-slate-300'"
>
{{ provider }}
</button>
</div>
<PrimaryButton
@click="runAI"
:disabled="isAnalyzing"
class="!bg-indigo-600 hover:!bg-indigo-500 !border-none !rounded-xl group"
>
<span v-if="isAnalyzing" class="flex items-center gap-2">
<svg class="animate-spin h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Analyse en cours...
</span>
<span v-else class="flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 group-hover:scale-110 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
Lancer l'analyse intelligente
</span>
</PrimaryButton>
</div>
</div>
<!-- AI Results -->