diff --git a/frontend/app/admin/SettingsPage.tsx b/frontend/app/admin/SettingsPage.tsx index eb96b5f..e156df3 100644 --- a/frontend/app/admin/SettingsPage.tsx +++ b/frontend/app/admin/SettingsPage.tsx @@ -300,7 +300,7 @@ export default function SettingsPage({ section }: SettingsPageProps) { requests_data_source: 'Pick where Magent should read requests from.', log_level: 'How much detail is written to the activity log.', log_file: 'Where the activity log is stored.', - site_build_number: 'Build number shown in the footer (auto-set from releases).', + site_build_number: 'Build number shown in the account menu (auto-set from releases).', site_banner_enabled: 'Enable a sitewide banner for announcements.', site_banner_message: 'Short banner message for maintenance or updates.', site_banner_tone: 'Visual tone for the banner.', diff --git a/frontend/app/globals.css b/frontend/app/globals.css index 15ff479..9826b62 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -175,30 +175,35 @@ body { margin-right: auto; } -.signed-in { - font-size: 12px; - text-transform: uppercase; - letter-spacing: 0.08em; - color: var(--ink-muted); - padding: 6px 10px; - border-radius: 999px; - border: 1px dashed var(--border); - background: transparent; - cursor: pointer; -} - .signed-in-menu { position: relative; display: inline-flex; align-items: center; } +.avatar-button { + width: 44px; + height: 44px; + border-radius: 50%; + border: 1px solid rgba(255, 255, 255, 0.12); + background: linear-gradient(130deg, rgba(28, 107, 255, 0.35), rgba(17, 214, 198, 0.25)); + color: var(--ink); + font-weight: 700; + letter-spacing: 0.04em; + text-transform: uppercase; + display: inline-flex; + align-items: center; + justify-content: center; + box-shadow: 0 10px 20px rgba(28, 107, 255, 0.25); + cursor: pointer; +} + .signed-in-dropdown { position: absolute; top: calc(100% + 8px); right: 0; - min-width: 180px; - background: rgba(14, 20, 32, 0.95); + width: min(260px, 90vw); + background: rgba(14, 20, 32, 0.96); border: 1px solid var(--border); border-radius: 12px; padding: 8px; @@ -206,17 +211,50 @@ body { z-index: 20; } -.signed-in-dropdown a { +.signed-in-header { + font-size: 11px; + letter-spacing: 0.06em; + text-transform: uppercase; + color: var(--ink-muted); + padding: 8px 10px 6px; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); +} + +.signed-in-actions { + display: grid; + gap: 6px; + padding: 8px 4px 4px; +} + +.signed-in-actions a, +.signed-in-signout { display: block; padding: 8px 12px; border-radius: 10px; color: var(--ink); text-decoration: none; - text-align: center; + text-align: left; + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.08); } -.signed-in-dropdown a:hover { - background: rgba(255, 255, 255, 0.08); +.signed-in-signout { + cursor: pointer; + font: inherit; +} + +.signed-in-actions a:hover, +.signed-in-signout:hover { + background: rgba(255, 255, 255, 0.12); +} + +.signed-in-build { + margin-top: 6px; + padding: 6px 10px 8px; + font-size: 11px; + color: var(--ink-muted); + text-align: left; + letter-spacing: 0.04em; } .theme-toggle { @@ -1446,21 +1484,18 @@ button span { } .signed-in-menu { - width: 100%; + margin-left: auto; } - .signed-in { - width: 100%; - text-align: left; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + .avatar-button { + width: 40px; + height: 40px; } .signed-in-dropdown { - position: static; - width: 100%; - margin-top: 8px; + right: 0; + left: auto; + width: min(260px, 92vw); } .header-actions { diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index 81b6d71..fdb99a9 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -29,8 +29,8 @@ export default function RootLayout({ children }: { children: ReactNode }) {
- +
diff --git a/frontend/app/ui/HeaderActions.tsx b/frontend/app/ui/HeaderActions.tsx index b967896..50ba6aa 100644 --- a/frontend/app/ui/HeaderActions.tsx +++ b/frontend/app/ui/HeaderActions.tsx @@ -32,14 +32,6 @@ export default function HeaderActions() { void load() }, []) - const signOut = () => { - clearToken() - setSignedIn(false) - if (typeof window !== 'undefined') { - window.location.href = '/login' - } - } - if (!signedIn) { return null } @@ -49,12 +41,7 @@ export default function HeaderActions() { Send feedback Requests How it works - Changelog - My profile {role === 'admin' && Settings} -
) } diff --git a/frontend/app/ui/HeaderIdentity.tsx b/frontend/app/ui/HeaderIdentity.tsx index cbb8054..ae86a76 100644 --- a/frontend/app/ui/HeaderIdentity.tsx +++ b/frontend/app/ui/HeaderIdentity.tsx @@ -4,13 +4,15 @@ import { useEffect, useState } from 'react' import { authFetch, clearToken, getApiBase, getToken } from '../lib/auth' export default function HeaderIdentity() { - const [identity, setIdentity] = useState(null) + const [identity, setIdentity] = useState<{ username: string; role?: string } | null>(null) + const [buildNumber, setBuildNumber] = useState(null) const [open, setOpen] = useState(false) useEffect(() => { const token = getToken() if (!token) { setIdentity(null) + setBuildNumber(null) return } const load = async () => { @@ -24,7 +26,14 @@ export default function HeaderIdentity() { } const data = await response.json() if (data?.username) { - setIdentity(`${data.username}${data.role ? ` (${data.role})` : ''}`) + setIdentity({ username: data.username, role: data.role }) + } + const siteResponse = await fetch(`${baseUrl}/site/public`) + if (siteResponse.ok) { + const siteInfo = await siteResponse.json() + if (siteInfo?.buildNumber) { + setBuildNumber(siteInfo.buildNumber) + } } } catch (err) { console.error(err) @@ -38,14 +47,42 @@ export default function HeaderIdentity() { return null } + const label = `${identity.username}${identity.role ? ` (${identity.role})` : ''}` + const initial = identity.username.slice(0, 1).toUpperCase() + const signOut = () => { + clearToken() + if (typeof window !== 'undefined') { + window.location.href = '/login' + } + } + return (
- {open && (
- My profile +
Signed in as {label}
+
+ setOpen(false)}> + My profile + + setOpen(false)}> + Changelog + + +
+ {buildNumber ?
Build {buildNumber}
: null}
)}
diff --git a/frontend/app/ui/SiteStatus.tsx b/frontend/app/ui/SiteStatus.tsx index e5e317b..323e520 100644 --- a/frontend/app/ui/SiteStatus.tsx +++ b/frontend/app/ui/SiteStatus.tsx @@ -57,9 +57,6 @@ export default function SiteStatus() { {banner?.enabled && banner.message ? (
{banner.message}
) : null} - {info?.buildNumber ? ( -
Build {info.buildNumber}
- ) : null} ) }