fix(toast): show success toast for HTMX JSON responses

Previously, when HTMX form submissions (profile update, password change)
returned a successful JSON response like {"message": "profile updated
successfully"}, the raw JSON was swapped into the target div as plain text.

The htmx:afterSwap listener in toast.ts only handled error responses.
Extend it to also intercept successful 2xx JSON responses that contain a
"message" field, showing a green success toast and clearing the raw JSON
from the target element. Only JSON responses are intercepted (checked via
Content-Type header), so legitimate HTML swaps are unaffected.
This commit is contained in:
2026-05-27 11:22:13 -04:00
parent a4b91393a6
commit 854a888306
+21 -4
View File
@@ -138,14 +138,31 @@ const setupHTMXListeners = (): void => {
const customEvent = evt as CustomEvent<HTMXEventDetail>; const customEvent = evt as CustomEvent<HTMXEventDetail>;
// Check if request failed if (customEvent.detail.xhr) {
if (customEvent.detail.succeeded === false && customEvent.detail.xhr) {
const xhr = customEvent.detail.xhr; const xhr = customEvent.detail.xhr;
// Show toast for HTTP errors if (
if (xhr.status >= 400 && xhr.status < 600) { customEvent.detail.succeeded === false &&
xhr.status >= 400 &&
xhr.status < 600
) {
const errorMessage = parseXHRError(xhr); const errorMessage = parseXHRError(xhr);
showToast(errorMessage, "error"); showToast(errorMessage, "error");
} else if (xhr.status >= 200 && xhr.status < 300) {
const contentType = xhr.getResponseHeader("content-type");
if (contentType && contentType.includes("application/json")) {
try {
const response = JSON.parse(xhr.responseText);
if (response.message) {
showToast(response.message, "success");
if (customEvent.detail.target) {
customEvent.detail.target.innerHTML = "";
}
}
} catch (e) {
// Not valid JSON — ignore
}
}
} }
} }
}); });