Files
cv-site/internal/handlers/cv_htmx.go
T
juanatsap 30ed21ff7a refactor: use 'c' alias for constants package
- Update all imports from 'constants' to 'c' for brevity
- Replace all 'constants.' references with 'c.'
- Fix remaining hardcoded content-type headers in httputil
- Fix remaining hardcoded User-Agent and Accept headers
- Rename CSRF receiver from 'c' to 'csrf' to avoid conflict
- Add ContentTypePlainSimple constant for Accept header matching
- Fix JSONCached to use proper integer formatting
2025-12-06 16:31:42 +00:00

134 lines
4.0 KiB
Go

package handlers
import (
"net/http"
c "github.com/juanatsap/cv-site/internal/constants"
"github.com/juanatsap/cv-site/internal/httputil"
"github.com/juanatsap/cv-site/internal/middleware"
)
// ==============================================================================
// HTMX TOGGLE HANDLERS
// These handlers manage user preferences (length, icons, language, theme)
// using atomic out-of-band swaps for a smooth UX
// ==============================================================================
// ToggleLength handles CV length toggle (short/long) using atomic out-of-band swaps
func (h *CVHandler) ToggleLength(w http.ResponseWriter, r *http.Request) {
if !httputil.RequirePost(w, r) {
return
}
// Get current preferences from context (set by middleware, already migrated)
prefs := middleware.GetPreferences(r)
currentLength := prefs.CVLength
// Toggle state
newLength := c.CVLengthLong
if currentLength == c.CVLengthLong {
newLength = c.CVLengthShort
}
// Save new state
middleware.SetPreferenceCookie(w, c.CookieCVLength, newLength)
// Return 204 No Content - frontend uses hx-swap="none" so response body is ignored
// The cookie is set and hyperscript handles the UI state toggle
w.WriteHeader(http.StatusNoContent)
}
// ToggleIcons handles icon visibility toggle using atomic out-of-band swaps
func (h *CVHandler) ToggleIcons(w http.ResponseWriter, r *http.Request) {
if !httputil.RequirePost(w, r) {
return
}
// Get current preferences from context (set by middleware, already migrated)
prefs := middleware.GetPreferences(r)
currentIcons := prefs.CVIcons
// Toggle state
newIcons := c.CVIconsHide
if currentIcons == c.CVIconsHide {
newIcons = c.CVIconsShow
}
// Save new state
middleware.SetPreferenceCookie(w, c.CookieCVIcons, newIcons)
// Return 204 No Content - frontend uses hx-swap="none" so response body is ignored
// The cookie is set and hyperscript handles the UI state toggle
w.WriteHeader(http.StatusNoContent)
}
// SwitchLanguage handles language switching with atomic updates
// Uses HTMX out-of-band swaps to update both the language selector buttons
// and all CV content wrappers in a single response
func (h *CVHandler) SwitchLanguage(w http.ResponseWriter, r *http.Request) {
lang, ok := httputil.LangOrError(r)
if !ok {
HandleError(w, r, BadRequestError("Unsupported language. Use 'en' or 'es'"))
return
}
// Save language preference
middleware.SetPreferenceCookie(w, c.CookieCVLanguage, lang)
// Prepare template data
data, err := h.prepareTemplateData(lang)
if err != nil {
HandleError(w, r, DataLoadError(err, "CV"))
return
}
// Get current preferences from context (set by middleware)
prefs := middleware.GetPreferences(r)
// Add preferences to data
if prefs.CVLength == c.CVLengthLong {
data["CVLengthClass"] = "cv-long"
} else {
data["CVLengthClass"] = "cv-short"
}
data["ShowIcons"] = (prefs.CVIcons == c.CVIconsShow)
data["ThemeClean"] = (prefs.CVTheme == c.CVThemeClean)
// Render language-switch template with out-of-band swaps
tmpl, err := h.templates.Render("language-switch.html")
if err != nil {
HandleError(w, r, TemplateError(err, "language-switch.html"))
return
}
w.Header().Set(c.HeaderContentType, c.ContentTypeHTML)
if err := tmpl.Execute(w, data); err != nil {
HandleError(w, r, TemplateError(err, "language-switch.html"))
return
}
}
// ToggleTheme handles theme toggle (default/clean) using atomic out-of-band swaps
func (h *CVHandler) ToggleTheme(w http.ResponseWriter, r *http.Request) {
if !httputil.RequirePost(w, r) {
return
}
// Get current preferences from context (set by middleware)
prefs := middleware.GetPreferences(r)
currentTheme := prefs.CVTheme
// Toggle state
newTheme := c.CVThemeClean
if currentTheme == c.CVThemeClean {
newTheme = c.CVThemeDefault
}
// Save new state
middleware.SetPreferenceCookie(w, c.CookieCVTheme, newTheme)
// Return 204 No Content - frontend uses hx-swap="none" so response body is ignored
// The cookie is set and hyperscript handles the UI state toggle
w.WriteHeader(http.StatusNoContent)
}