fix: heartbeat button shows proper errors instead of failing silently

- CSRF check returns JSON instead of die() with raw text
- JS parses non-JSON responses gracefully and shows server error
- Visual feedback (check/cross icon) on success/failure
- 3-second icon revert after result

Claude-Session: https://claude.ai/code/session_01Jo2JpjCwfHAh2HHRSjczKq
This commit is contained in:
2026-06-28 14:19:47 -05:00
parent 6a717342db
commit d0db1f55dc
@@ -112,7 +112,6 @@ document.addEventListener('DOMContentLoaded', function () {
// Heartbeat + PIN send button
var hbBtn = document.getElementById('mokosuiteclient-btn-heartbeat-pin');
var hbIconTimeout = null;
if (hbBtn) {
hbBtn.addEventListener('click', function () {
var btn = this;
@@ -120,7 +119,6 @@ document.addEventListener('DOMContentLoaded', function () {
var token = btn.dataset.token;
var icon = btn.querySelector('span');
if (hbIconTimeout) { clearTimeout(hbIconTimeout); hbIconTimeout = null; }
btn.disabled = true;
if (icon) { icon.className = 'icon-spinner icon-spin'; icon.style.color = ''; }
@@ -150,9 +148,8 @@ document.addEventListener('DOMContentLoaded', function () {
})
.finally(function () {
btn.disabled = false;
hbIconTimeout = setTimeout(function () {
setTimeout(function () {
if (icon) { icon.className = 'icon-upload'; icon.style.color = ''; }
hbIconTimeout = null;
}, 3000);
});
});