Files
cv-site/templates/partials/widgets/chat-widget.html
T
juanatsap 93e33f6496 fix: chat submission and session handling + 37 Playwright tests
- Fix chip auto-submit: use htmx.trigger() instead of native submit
  to bypass browser validation on required field
- Remove required from input (server validates already)
- Fix session_id duplication: use hx-swap-oob to replace single input
- Fix agent context: use background context with 30s timeout instead
  of HTTP request context (prevents premature cancellation)
- Remove redundant close button from header (toggle button handles it)
- Add 83-chat-mascot.test.mjs: 37 tests covering button, panel,
  help card, chips, typed questions, session, Spanish, positioning
2026-04-08 11:31:09 +01:00

118 lines
5.7 KiB
HTML

{{define "chat-widget"}}
{{if .ChatEnabled}}
<!-- AI Chat Widget — CV Assistant Mascot -->
<button
id="chat-toggle-btn"
class="fixed-btn chat-toggle-btn no-print has-tooltip"
aria-label="{{if eq .Lang "es"}}Asistente del CV{{else}}CV Assistant{{end}}"
data-tooltip="{{if eq .Lang "es"}}Asistente del CV{{else}}CV Assistant{{end}}"
_="on click toggle .chat-open on #chat-panel
then if #chat-panel matches .chat-open
then add .mascot-active to me
then set #chat-input.focus to true
then call #chat-input.focus()
else
remove .mascot-active from me
end">
<iconify-icon icon="mdi:robot-happy-outline" class="chat-icon-open"></iconify-icon>
<iconify-icon icon="mdi:close" class="chat-icon-close"></iconify-icon>
</button>
<div id="chat-panel" class="chat-panel no-print">
<div class="chat-header">
<iconify-icon icon="mdi:robot-happy-outline"></iconify-icon>
<span>{{if eq .Lang "es"}}Asistente del CV{{else}}CV Assistant{{end}}</span>
<button class="chat-help-btn"
aria-label="{{if eq .Lang "es"}}Ayuda{{else}}Help{{end}}"
_="on click toggle .visible on #chat-help-card">
<iconify-icon icon="mdi:help-circle-outline"></iconify-icon>
</button>
</div>
<!-- Help / Onboarding Card -->
<div id="chat-help-card" class="chat-help-card visible">
<div class="chat-help-icon">
<iconify-icon icon="mdi:robot-happy-outline"></iconify-icon>
</div>
<p class="chat-help-text">
{{if eq .Lang "es"}}¡Soy el Asistente del CV! Puedo responder preguntas sobre la experiencia profesional, proyectos, habilidades y formación de Juan. Prueba a hacer clic en una sugerencia o escribe tu propia pregunta.{{else}}I'm the CV Assistant! I can answer questions about Juan's professional experience, projects, skills, and education. Try clicking a suggestion or type your own question.{{end}}
</p>
<button class="chat-help-dismiss"
_="on click remove .visible from #chat-help-card">
{{if eq .Lang "es"}}Entendido{{else}}Got it{{end}}
</button>
</div>
<div id="chat-messages" class="chat-messages">
<div class="chat-message chat-agent">
{{if eq .Lang "es"}}¡Hola! Pregúntame lo que quieras sobre este CV.{{else}}Hi! Ask me anything about this CV.{{end}}
</div>
</div>
<!-- Typing Indicator -->
<div id="chat-typing" class="chat-typing">
<span class="chat-typing-dot"></span>
<span class="chat-typing-dot"></span>
<span class="chat-typing-dot"></span>
</div>
<!-- Suggested Questions -->
<div class="chat-suggestions">
{{if eq .Lang "es"}}
<button type="button" class="chat-chip"
_="on click set #chat-input.value to '¿Qué proyectos en Go ha hecho?'
then call htmx.trigger(#chat-form, 'submit')">¿Proyectos en Go?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to '¿Cuántos años de experiencia tiene?'
then call htmx.trigger(#chat-form, 'submit')">¿Años de experiencia?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to '¿En qué empresas ha trabajado?'
then call htmx.trigger(#chat-form, 'submit')">¿Empresas?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to '¿Conoce React?'
then call htmx.trigger(#chat-form, 'submit')">¿Conoce React?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to '¿Qué certificaciones tiene?'
then call htmx.trigger(#chat-form, 'submit')">¿Certificaciones?</button>
{{else}}
<button type="button" class="chat-chip"
_="on click set #chat-input.value to 'What Go projects has he built?'
then call htmx.trigger(#chat-form, 'submit')">Go projects?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to 'How many years of experience?'
then call htmx.trigger(#chat-form, 'submit')">Years of experience?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to 'What companies has he worked at?'
then call htmx.trigger(#chat-form, 'submit')">Companies?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to 'Does he know React?'
then call htmx.trigger(#chat-form, 'submit')">Knows React?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to 'What certifications?'
then call htmx.trigger(#chat-form, 'submit')">Certifications?</button>
{{end}}
</div>
<form id="chat-form" class="chat-input-area"
hx-post="/api/chat"
hx-target="#chat-messages"
hx-swap="beforeend scroll:#chat-messages:bottom"
hx-indicator="#chat-typing"
_="on htmx:afterRequest set #chat-input.value to ''">
<input type="hidden" id="chat-session-id" name="session_id" value="">
<input type="hidden" name="lang" value="{{.Lang}}">
<input
type="text"
id="chat-input"
name="message"
class="chat-input"
placeholder="{{if eq .Lang "es"}}Pregunta algo sobre el CV...{{else}}Ask something about the CV...{{end}}"
autocomplete="off">
<button type="submit" class="chat-send-btn" aria-label="Send">
<iconify-icon icon="mdi:send"></iconify-icon>
</button>
</form>
</div>
{{end}}
{{end}}