feat(aep-v1.1): PA5 chatbot pratiques regeneratives

- Nouveau endpoint server/api/chatbot-pratiques.post.ts qui interroge
  le JSON statique pratiques-regeneratives.json (52 fiches V1) avec
  Mistral Small. Prompt systeme adapte aux 8 criteres rege et types
  d'entites. Rate limit 10/jour, circuit breaker partage.
- ChatbotPlaceholder + ChatbotSheet rendus generiques via props
  (endpoint, title, placeholder, ficheBasePath) + slot onboarding.
  La carte ecosysteme AEP continue d'utiliser /api/chatbot, la carte
  pratiques rege utilise /api/chatbot-pratiques.
- pratiques-regeneratives.vue : ChatbotPlaceholder integre sous la
  carte Europe desktop (replie par defaut), FAB mobile + ChatbotSheet
  bottom sheet, handler highlightOrgs pour surligner la fiche reco.
This commit is contained in:
Jules Neny
2026-04-30 02:29:16 +02:00
parent a6fff9a950
commit 914759a815
4 changed files with 421 additions and 29 deletions

View File

@@ -61,7 +61,7 @@
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
</svg>
</div>
<span class="font-bold text-sm" style="color: var(--nav-text);">Chatbot</span>
<span class="font-bold text-sm" style="color: var(--nav-text);">{{ title }}</span>
</div>
</div>
@@ -69,18 +69,20 @@
<div ref="messagesContainer" class="flex-1 overflow-y-auto px-4 py-4 flex flex-col gap-3">
<!-- Message onboarding (avant la première question) -->
<div v-if="messages.length === 0" class="onboarding-bubble">
<p>Ce chatbot fonctionne sur un serveur européen souverain
<slot name="onboarding">
<p>Ce chatbot fonctionne sur un serveur européen souverain
(Mistral FR, zéro rétention), conçu sobre en énergie.</p>
<p>Pour m'aider à te répondre efficacement,
<p>Pour m'aider à te répondre efficacement,
formule ta requête ainsi :</p>
<ul>
<li>• Besoin : [ce que tu cherches]</li>
<li>• Thématique : [juridique / technique / économique / ...]</li>
<li>• Lieu : [région ou ville]</li>
</ul>
<p class="example">Exemple : "Je suis salarié d'agence, litige avec mon
<ul>
<li>• Besoin : [ce que tu cherches]</li>
<li>• Thématique : [juridique / technique / économique / ...]</li>
<li>• Lieu : [région ou ville]</li>
</ul>
<p class="example">Exemple : "Je suis salarié d'agence, litige avec mon
employeur, besoin conseil juridique droit du travail,
Île-de-France."</p>
</slot>
</div>
<!-- Messages -->
@@ -100,7 +102,7 @@ employeur, besoin conseil juridique droit du travail,
<a
v-for="fiche in msg.fiches"
:key="fiche.id"
:href="`/fiche/${fiche.id}`"
:href="`${ficheBasePath}/${fiche.id}`"
class="fiche-card"
>
<span class="fiche-nom">{{ fiche.nom }}</span>
@@ -176,9 +178,16 @@ interface ChatMessage {
fiches?: FicheReco[]
}
const props = defineProps<{
const props = withDefaults(defineProps<{
modelValue: boolean
}>()
endpoint?: string
title?: string
ficheBasePath?: string
}>(), {
endpoint: '/api/chatbot',
title: 'Chatbot',
ficheBasePath: '/fiche',
})
const emit = defineEmits<{
'update:modelValue': [value: boolean]
@@ -225,7 +234,7 @@ async function sendMessage() {
const res = await $fetch<{
reponse_texte: string
fiches_recommandees: { id: number | string; nom: string; explication: string }[]
}>('/api/chatbot', {
}>(props.endpoint, {
method: 'POST',
body: { question },
})