From 4e4bb49e8cdd4e1ebc07b0d37802551a01262b67 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Mon, 29 Dec 2025 12:01:49 -0800 Subject: [PATCH] Refactor to ES module with localStorage profile and data-bind --- main.go | 11 ++++-- static/app.js | 85 +++++++++++++++++++++++++++++++++++++++++++++++ static/index.html | 74 +++++++---------------------------------- 3 files changed, 105 insertions(+), 65 deletions(-) create mode 100644 static/app.js diff --git a/main.go b/main.go index 0c6e275..b18c290 100644 --- a/main.go +++ b/main.go @@ -21,7 +21,8 @@ var ( ) func init() { - templates = template.Must(template.ParseGlob("static/*.html")) + templates = template.Must(template.New("").ParseGlob("static/*.html")) + template.Must(templates.ParseGlob("static/*.js")) var err error db, err = sql.Open("postgres", os.Getenv("PGCONN")) @@ -63,13 +64,17 @@ func handleStatic(w http.ResponseWriter, r *http.Request) { name := strings.TrimPrefix(path, "/") - if strings.HasSuffix(name, ".html") { + if strings.HasSuffix(name, ".html") || strings.HasSuffix(name, ".js") { t := templates.Lookup(name) if t == nil { http.NotFound(w, r) return } - w.Header().Set("Content-Type", "text/html") + if strings.HasSuffix(name, ".html") { + w.Header().Set("Content-Type", "text/html") + } else { + w.Header().Set("Content-Type", "application/javascript") + } t.Execute(w, templateData()) return } diff --git a/static/app.js b/static/app.js new file mode 100644 index 0000000..7419603 --- /dev/null +++ b/static/app.js @@ -0,0 +1,85 @@ +const CLIENT_ID = '{{.env.GOOGLE_CLIENT_ID}}'; + +function getProfile() { + const data = localStorage.getItem('profile'); + return data ? JSON.parse(data) : null; +} + +function setProfile(profile) { + localStorage.setItem('profile', JSON.stringify(profile)); +} + +export function logout() { + localStorage.removeItem('profile'); + location.reload(); +} + +function bind(data) { + document.querySelectorAll('[data-bind]').forEach(el => { + const key = el.dataset.bind; + const value = key.split('.').reduce((o, k) => o?.[k], data); + if (el.tagName === 'IMG') { + el.src = value; + } else { + el.textContent = value; + } + }); +} + +function waitForGoogle() { + return new Promise((resolve) => { + if (typeof google !== 'undefined') { + resolve(); + return; + } + const check = setInterval(() => { + if (typeof google !== 'undefined') { + clearInterval(check); + resolve(); + } + }, 50); + }); +} + +export async function auth() { + let profile = getProfile(); + if (profile) { + bind(profile); + return profile; + } + + await waitForGoogle(); + + const signin = document.getElementById('signin'); + signin.style.display = 'block'; + document.body.style.opacity = 1; + + profile = await new Promise((resolve) => { + google.accounts.id.initialize({ + client_id: CLIENT_ID, + callback: async (response) => { + const res = await fetch('/auth/google/callback', { + method: 'POST', + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + body: 'credential=' + encodeURIComponent(response.credential) + }); + const profile = await res.json(); + setProfile(profile); + signin.style.display = 'none'; + resolve(profile); + } + }); + + google.accounts.id.renderButton(signin, { + type: 'standard', + size: 'large', + theme: 'outline', + text: 'sign_in_with', + shape: 'rectangular', + logo_alignment: 'left' + }); + }); + + bind(profile); + return profile; +} diff --git a/static/index.html b/static/index.html index 81f1e6a..73109a6 100644 --- a/static/index.html +++ b/static/index.html @@ -31,79 +31,29 @@ -
-
-
- -
+
- Profile + Profile
-
-
+
+

Welcome to HCA Tickets!

- Switch User + Switch User
-