feat(chatbot): persistance des conversations en sessionStorage + bouton Nouvelle conversation

- composables/useChatSession.ts : historique réactif partagé (useState) et persisté sous aep-chat-<clé>, version de schéma {v:1}, 40 derniers messages, restauration au mount uniquement (SSR-safe), try/catch partout, messages transient jamais écrits
- clés : accueil (Placeholder + Sheet), agences (Placeholder réseaux + ChatbotReseaux), taff, pensees (suffixée par l'auteur)
- ChatbotPlaceholder reçoit sa clé par prop chatKey (défaut accueil)
- ChatNewConversation : bouton sobre, visible seulement s'il y a un historique

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015vcVGz8i4WpZm2dixKUiSD
This commit is contained in:
Jules Neny
2026-10-09 03:38:15 +02:00
co-authored by Claude Opus 5.5
parent 31edbd37af
commit 75d8440601
8 changed files with 174 additions and 19 deletions
+8 -14
View File
@@ -16,16 +16,6 @@
<span v-else class="chatbot-corpus-badge">FRACAS</span>
</div>
<div class="chatbot-header-right">
<button
v-if="messages.length > 0"
class="chatbot-clear-btn"
title="Effacer la conversation"
@click="clearMessages"
>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" aria-hidden="true">
<polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/>
</svg>
</button>
<select v-model="corpusMode" class="chatbot-corpus-select" title="Corpus interrogé">
<option value="pensees">Pensées éco.</option>
<option value="both">Pensées + Projets</option>
@@ -66,6 +56,8 @@
<!-- Erreur -->
<div v-if="errorMsg" class="chatbot-error">{{ errorMsg }}</div>
<ChatNewConversation v-if="hasHistory && !loading" @reset="clearMessages" />
</div>
<!-- Input -->
@@ -109,20 +101,22 @@ const props = defineProps<{
inline?: boolean
}>()
const messages = ref<ChatMessage[]>([])
// Une conversation par contexte (corpus général ou un auteur) : changer d'auteur
// ne mélange pas les historiques, et un rechargement restaure le bon.
const sessionKey = computed(() => props.auteurContext ? `pensees-${slugify(props.auteurContext)}` : 'pensees')
const { messages, hasHistory, clear } = useChatSession<ChatMessage>(sessionKey)
const inputText = ref('')
const loading = ref(false)
const errorMsg = ref('')
const corpusMode = ref<'pensees' | 'projets' | 'both'>('pensees')
const messagesContainer = ref<HTMLElement | null>(null)
watch(() => props.auteurContext, () => {
messages.value = []
watch(sessionKey, () => {
errorMsg.value = ''
})
function clearMessages() {
messages.value = []
clear()
errorMsg.value = ''
}