mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
feat(settings): land the account page from the avatar, tidy the token row
Clicking the avatar (and the name beside it) in the sidebar user menu now routes straight to the account settings. On the per-medication API token row, drop the separate "Copy URL" button in favour of an inline read-only endpoint field with a copy icon, and switch the generate-token button to the standard outline variant so it no longer renders as the lone primary-coloured control on the row.
This commit is contained in:
1 parent
eda79794d9
commit
1b283a9c01
2 files changed
+72
-47
No files matched your search
@@ -124,22 +124,31 @@ function SidebarUserSection({ collapsed }: { collapsed: boolean }) {
|
||||
className="w-60"
|
||||
sideOffset={8}
|
||||
>
|
||||
<div className="flex items-center gap-3 px-2 py-2">
|
||||
<Avatar className="h-9 w-9 shrink-0">
|
||||
{avatarUrl && <AvatarImage src={avatarUrl} alt={user.username} />}
|
||||
<AvatarFallback className="bg-primary/15 text-primary text-xs font-medium">
|
||||
{getInitials(user.username)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="truncate text-sm font-semibold">{user.username}</p>
|
||||
{user.email && (
|
||||
<p className="text-muted-foreground truncate text-xs">
|
||||
{user.email}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* R20 — the user header is the direct route into the account
|
||||
settings. Clicking the avatar / name jumps straight to
|
||||
`/settings/account` rather than making the user hunt for a
|
||||
separate "Settings" entry. */}
|
||||
<DropdownMenuItem asChild>
|
||||
<Link
|
||||
href="/settings/account"
|
||||
className="flex cursor-pointer items-center gap-3 px-2 py-2"
|
||||
>
|
||||
<Avatar className="h-9 w-9 shrink-0">
|
||||
{avatarUrl && <AvatarImage src={avatarUrl} alt={user.username} />}
|
||||
<AvatarFallback className="bg-primary/15 text-primary text-xs font-medium">
|
||||
{getInitials(user.username)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="truncate text-sm font-semibold">{user.username}</p>
|
||||
{user.email && (
|
||||
<p className="text-muted-foreground truncate text-xs">
|
||||
{user.email}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem asChild>
|
||||
<Link href="/notifications" className="cursor-pointer">
|
||||
@@ -219,20 +228,29 @@ function SidebarUserSection({ collapsed }: { collapsed: boolean }) {
|
||||
return (
|
||||
<div className="border-sidebar-border border-t p-3">
|
||||
<div className="flex items-center gap-3 px-2 py-1">
|
||||
<Avatar className="h-8 w-8 shrink-0">
|
||||
{avatarUrl && <AvatarImage src={avatarUrl} alt={user.username} />}
|
||||
<AvatarFallback className="bg-primary/15 text-primary text-xs font-medium">
|
||||
{getInitials(user.username)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="truncate text-sm font-medium">{user.username}</p>
|
||||
{user.email && (
|
||||
<p className="text-muted-foreground truncate text-xs">
|
||||
{user.email}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{/* R20 — the avatar + name in the expanded footer routes straight
|
||||
into the account settings; the kebab to the right still opens
|
||||
the rest of the user menu. */}
|
||||
<Link
|
||||
href="/settings/account"
|
||||
aria-label={t("nav.accountSettings")}
|
||||
className="hover:bg-accent flex min-w-0 flex-1 items-center gap-3 rounded-md transition-colors"
|
||||
>
|
||||
<Avatar className="h-8 w-8 shrink-0">
|
||||
{avatarUrl && <AvatarImage src={avatarUrl} alt={user.username} />}
|
||||
<AvatarFallback className="bg-primary/15 text-primary text-xs font-medium">
|
||||
{getInitials(user.username)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="truncate text-sm font-medium">{user.username}</p>
|
||||
{user.email && (
|
||||
<p className="text-muted-foreground truncate text-xs">
|
||||
{user.email}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger
|
||||
aria-label={t("nav.userMenu")}
|
||||
|
||||
@@ -203,28 +203,35 @@ export function ApiTokensRow({
|
||||
<p className="text-muted-foreground text-xs">
|
||||
{t("medications.detail.api.caption", { name: medicationName })}
|
||||
</p>
|
||||
{/* The raw endpoint URL is redundant with the copy button below, so
|
||||
it is rendered muted + single-line-truncated rather than as a
|
||||
full-width block — the long absolute URL was pure visual noise. */}
|
||||
<code
|
||||
className="text-muted-foreground bg-muted/60 block truncate rounded px-2 py-1 font-mono text-xs"
|
||||
title={endpoint}
|
||||
{/* R26 — the endpoint URL is an inline read-only field with a copy
|
||||
icon on the right rather than a separate "URL kopieren" button.
|
||||
The `<code>` carries the value; the icon button copies it. */}
|
||||
<div
|
||||
className="border-input bg-muted/60 flex items-center gap-2 rounded-md border px-2 py-1"
|
||||
data-slot="api-endpoint-url"
|
||||
>
|
||||
POST {endpoint}
|
||||
</code>
|
||||
<code
|
||||
className="text-muted-foreground min-w-0 flex-1 truncate font-mono text-xs"
|
||||
title={endpoint}
|
||||
>
|
||||
POST {endpoint}
|
||||
</code>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() =>
|
||||
void copy(endpoint, t("medications.detail.api.urlCopied"))
|
||||
}
|
||||
className="h-7 w-7 shrink-0"
|
||||
aria-label={t("medications.detail.api.copyUrl")}
|
||||
data-slot="api-tokens-copy-url"
|
||||
>
|
||||
<Copy aria-hidden="true" className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => void copy(endpoint, t("medications.detail.api.urlCopied"))}
|
||||
className="min-h-11 sm:min-h-9"
|
||||
data-slot="api-tokens-copy-url"
|
||||
>
|
||||
<Copy aria-hidden="true" className="h-4 w-4" />
|
||||
{t("medications.detail.api.copyUrl")}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => void mintToken()}
|
||||
disabled={busy}
|
||||
|
||||
Reference in new issue
Block a user