fix: replace Hyperscript with plain JS for chat interactions

The Hyperscript trigger/call commands couldn't reliably trigger HTMX
form submissions or call global JS functions. Moved all chat
interactions to plain JavaScript:

- toggleChatPanel(): open/close panel + icon swap
- sendChatQuestion(q): set input + htmx.trigger(form, 'submit')
- closeChatHelpAndAsk(q): close modal + open chat + send question
- htmx:afterRequest listener clears input after submit

Hyperscript kept only for site-wide patterns (closeOnBackdrop) that
work reliably.

Also: better error message for rate-limited API responses (429).
This commit is contained in:
juanatsap
2026-04-08 14:11:11 +01:00
parent 25ddfff0da
commit 4f558ac842
3 changed files with 76 additions and 50 deletions
+53 -30
View File
@@ -6,14 +6,7 @@
class="chat-toggle-btn no-print has-tooltip tooltip-left"
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">
onclick="toggleChatPanel()">
<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>
@@ -46,27 +39,17 @@
<!-- 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 trigger submit on #chat-form">¿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 trigger submit on #chat-form">¿Años de experiencia?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to '¿En qué empresas ha trabajado?' then trigger submit on #chat-form">¿Empresas?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to '¿Conoce React?' then trigger submit on #chat-form">¿Conoce React?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to '¿Qué certificaciones tiene?' then trigger submit on #chat-form">¿Certificaciones?</button>
<button type="button" class="chat-chip" onclick="sendChatQuestion('¿Qué proyectos en Go ha hecho?')">¿Proyectos en Go?</button>
<button type="button" class="chat-chip" onclick="sendChatQuestion('¿Cuántos años de experiencia tiene?')">¿Años de experiencia?</button>
<button type="button" class="chat-chip" onclick="sendChatQuestion('¿En qué empresas ha trabajado?')">¿Empresas?</button>
<button type="button" class="chat-chip" onclick="sendChatQuestion('¿Conoce React?')">¿Conoce React?</button>
<button type="button" class="chat-chip" onclick="sendChatQuestion('¿Qué certificaciones tiene?')">¿Certificaciones?</button>
{{else}}
<button type="button" class="chat-chip"
_="on click set #chat-input.value to 'What Go projects has he built?' then trigger submit on #chat-form">Go projects?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to 'How many years of experience?' then trigger submit on #chat-form">Years of experience?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to 'What companies has he worked at?' then trigger submit on #chat-form">Companies?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to 'Does he know React?' then trigger submit on #chat-form">Knows React?</button>
<button type="button" class="chat-chip"
_="on click set #chat-input.value to 'What certifications?' then trigger submit on #chat-form">Certifications?</button>
<button type="button" class="chat-chip" onclick="sendChatQuestion('What Go projects has he built?')">Go projects?</button>
<button type="button" class="chat-chip" onclick="sendChatQuestion('How many years of experience?')">Years of experience?</button>
<button type="button" class="chat-chip" onclick="sendChatQuestion('What companies has he worked at?')">Companies?</button>
<button type="button" class="chat-chip" onclick="sendChatQuestion('Does he know React?')">Knows React?</button>
<button type="button" class="chat-chip" onclick="sendChatQuestion('What certifications?')">Certifications?</button>
{{end}}
</div>
@@ -74,8 +57,7 @@
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 ''">
hx-indicator="#chat-typing">
<input type="hidden" id="chat-session-id" name="session_id" value="">
<input type="hidden" name="lang" value="{{.Lang}}">
<input
@@ -90,5 +72,46 @@
</button>
</form>
</div>
<!-- Chat JavaScript — all interactions in plain JS, no Hyperscript -->
<script>
// Toggle chat panel open/close
function toggleChatPanel() {
var panel = document.getElementById('chat-panel');
var btn = document.getElementById('chat-toggle-btn');
panel.classList.toggle('chat-open');
btn.classList.toggle('mascot-active');
if (panel.classList.contains('chat-open')) {
document.getElementById('chat-input').focus();
}
}
// Send a question (from chip or help modal)
function sendChatQuestion(question) {
var input = document.getElementById('chat-input');
var form = document.getElementById('chat-form');
input.value = question;
htmx.trigger(form, 'submit');
}
// Close help modal, open chat, and send question
function closeChatHelpAndAsk(question) {
document.getElementById('chat-help-modal').close();
var panel = document.getElementById('chat-panel');
var btn = document.getElementById('chat-toggle-btn');
if (!panel.classList.contains('chat-open')) {
panel.classList.add('chat-open');
btn.classList.add('mascot-active');
}
sendChatQuestion(question);
}
// Clear input after HTMX request completes
document.addEventListener('htmx:afterRequest', function(event) {
if (event.detail.elt && event.detail.elt.id === 'chat-form') {
document.getElementById('chat-input').value = '';
}
});
</script>
{{end}}
{{end}}