feat(profile): role-aware nav + avatar menu + full editable profile
Build backend images / build content-svc (push) Failing after 1m59s
Build backend images / build file-svc (push) Failing after 3m18s
Build backend images / build gateway (push) Failing after 3m28s
Build backend images / build identity-svc (push) Failing after 2m1s
Build backend images / build notification-svc (push) Failing after 4m45s
Build backend images / build render-svc (push) Failing after 5m18s
Build backend images / build studio-svc (push) Failing after 2m12s
Build backend images / build content-svc (push) Failing after 1m59s
Build backend images / build file-svc (push) Failing after 3m18s
Build backend images / build gateway (push) Failing after 3m28s
Build backend images / build identity-svc (push) Failing after 2m1s
Build backend images / build notification-svc (push) Failing after 4m45s
Build backend images / build render-svc (push) Failing after 5m18s
Build backend images / build studio-svc (push) Failing after 2m12s
Navigation: - UserMenu (avatar + role-aware dropdown: Dashboard, Admin Panel for admins, Profile, Sign out) replaces Sign In/Try Free when logged in (desktop + mobile). - Real avatars in dashboard sidebar + a new admin-shell profile section. - Shared Avatar primitive (image with initials fallback). SiteChrome excludes /admin. Profile (data-collection surface for future AI video generation): - SettingsProfile rebuilt: avatar upload + slogan, about, company, website, country, national code, birthdate, gender. No resume builder (per scope change). - /api/profile forwards all fields; new user-scoped /api/profile/upload (avatar → MinIO via file-svc, sets avatar). Identity UpdateUserRequest/UserResponse widened (country/national/method); no DB migration (columns already exist). - fa+en strings; verified GET/PATCH round-trip + logged-in SSR render. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -60,3 +60,25 @@ export async function getCurrentUser(): Promise<IdentityUser | null> {
|
||||
if (!res.ok) return null;
|
||||
return (await res.json().catch(() => null)) as IdentityUser | null;
|
||||
}
|
||||
|
||||
/** Minimal, serializable user summary for the navbar/profile menu (passed from
|
||||
* server layouts into client components). Null when signed out. */
|
||||
export interface NavUser {
|
||||
name: string;
|
||||
email: string;
|
||||
avatarUrl: string | null;
|
||||
isAdmin: boolean;
|
||||
}
|
||||
|
||||
export async function getNavUser(): Promise<NavUser | null> {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) return null;
|
||||
const email = user.email ?? "";
|
||||
const fullName = typeof user.full_name === "string" ? user.full_name.trim() : "";
|
||||
return {
|
||||
name: fullName || (email ? email.split("@")[0] : "User"),
|
||||
email,
|
||||
avatarUrl: (user.avatar_url as string | null) ?? null,
|
||||
isAdmin: Boolean(user.is_admin) || Boolean((user as Record<string, unknown>).is_tenant_admin),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user