feat(web): show profile picture avatar in game page header
Build and Deploy / build-and-push (push) Failing after 4m17s

Fetches /api/me with the stored fs_token and renders a 32px circular
avatar in hud-right. Shows the profile photo when set, or the first
letter of the username as initials otherwise. Hidden when not signed in.
Clicking the avatar navigates to /account.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-15 17:37:57 -07:00
parent 8a145154db
commit f6be961419
3 changed files with 51 additions and 0 deletions
+19
View File
@@ -59,6 +59,25 @@ header {
.hud-center { display: flex; gap: 20px; font-size: 14px; font-weight: 600; } .hud-center { display: flex; gap: 20px; font-size: 14px; font-weight: 600; }
.hud-right { display: flex; align-items: center; gap: 10px; } .hud-right { display: flex; align-items: center; gap: 10px; }
.hud-avatar-link { display: flex; align-items: center; text-decoration: none; }
.hud-avatar-inner {
width: 32px;
height: 32px;
border-radius: 50%;
overflow: hidden;
border: 2px solid rgba(255,255,255,0.15);
background: var(--panel-hi);
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
font-weight: 700;
color: var(--text-muted);
transition: border-color 120ms;
}
.hud-avatar-link:hover .hud-avatar-inner { border-color: var(--accent); }
.hud-avatar-inner img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.logo { font-size: 16px; font-weight: 700; } .logo { font-size: 16px; font-weight: 700; }
.muted { color: var(--text-muted); font-size: 12px; } .muted { color: var(--text-muted); font-size: 12px; }
.home-link { .home-link {
+6
View File
@@ -40,6 +40,12 @@
<input type="checkbox" id="chk-draw3"> Draw 3 <input type="checkbox" id="chk-draw3"> Draw 3
</label> </label>
<button id="btn-theme" title="Switch card theme">Dark</button> <button id="btn-theme" title="Switch card theme">Dark</button>
<a id="hud-avatar" href="/account" title="Account" class="hud-avatar-link" style="display:none">
<div class="hud-avatar-inner">
<img id="hud-avatar-img" src="" alt="" style="display:none">
<span id="hud-avatar-initials"></span>
</div>
</a>
</div> </div>
</header> </header>
+26
View File
@@ -663,5 +663,31 @@ function onBoardDblClick(e) {
if (!smartMove(hit.pileName, fromIndex)) flashIllegal([cards[fromIndex].id]); if (!smartMove(hit.pileName, fromIndex)) flashIllegal([cards[fromIndex].id]);
} }
// ── Avatar ────────────────────────────────────────────────────────────────────
async function loadAvatar() {
const token = localStorage.getItem("fs_token");
if (!token) return;
try {
const res = await fetch("/api/me", {
headers: { Authorization: "Bearer " + token },
});
if (!res.ok) return;
const me = await res.json();
const link = document.getElementById("hud-avatar");
const img = document.getElementById("hud-avatar-img");
const init = document.getElementById("hud-avatar-initials");
link.style.display = "flex";
if (me.avatar_url) {
img.src = me.avatar_url;
img.style.display = "block";
init.style.display = "none";
} else {
img.style.display = "none";
init.textContent = (me.username || "P")[0].toUpperCase();
}
} catch { /* not signed in — avatar stays hidden */ }
}
// ── Start ───────────────────────────────────────────────────────────────────── // ── Start ─────────────────────────────────────────────────────────────────────
bootstrap().catch(console.error); bootstrap().catch(console.error);
loadAvatar();