From b5e9c8ba3482af538364672f4baa89c8f68868d5 Mon Sep 17 00:00:00 2001 From: louiscklaw Date: Sun, 11 May 2025 07:55:16 +0800 Subject: [PATCH] "update user popover with dynamic user metadata loading and improved UI consistency," --- .../layout/user-popover/custom-sign-out.tsx | 6 +- .../layout/user-popover/user-popover.tsx | 48 +++++++++++++--- .../dashboard/layout/vertical/main-nav.tsx | 57 +++++++++++++++---- .../dashboard/settings/side-nav.tsx | 45 ++++++++++++--- 002_source/cms/src/lib/auth/custom/client.ts | 47 ++++++++++----- 5 files changed, 164 insertions(+), 39 deletions(-) diff --git a/002_source/cms/src/components/dashboard/layout/user-popover/custom-sign-out.tsx b/002_source/cms/src/components/dashboard/layout/user-popover/custom-sign-out.tsx index 5ed0219..ff52e59 100644 --- a/002_source/cms/src/components/dashboard/layout/user-popover/custom-sign-out.tsx +++ b/002_source/cms/src/components/dashboard/layout/user-popover/custom-sign-out.tsx @@ -37,7 +37,11 @@ export function CustomSignOut(): React.JSX.Element { }, [checkSession, router]); return ( - + Sign out ); diff --git a/002_source/cms/src/components/dashboard/layout/user-popover/user-popover.tsx b/002_source/cms/src/components/dashboard/layout/user-popover/user-popover.tsx index cdd96d8..5db2776 100644 --- a/002_source/cms/src/components/dashboard/layout/user-popover/user-popover.tsx +++ b/002_source/cms/src/components/dashboard/layout/user-popover/user-popover.tsx @@ -23,8 +23,10 @@ import { CognitoSignOut } from './cognito-sign-out'; import { CustomSignOut } from './custom-sign-out'; import { FirebaseSignOut } from './firebase-sign-out'; import { SupabaseSignOut } from './supabase-sign-out'; +import { authClient } from '@/lib/auth/custom/client'; +import { logger } from '@/lib/default-logger'; -const user = { +const defaultUser = { id: 'USR-000', name: 'Sofia Rivers', avatar: '/assets/avatar.png', @@ -38,6 +40,23 @@ export interface UserPopoverProps { } export function UserPopover({ anchorEl, onClose, open }: UserPopoverProps): React.JSX.Element { + const [userMeta, setUserMeta] = React.useState(defaultUser); + async function loadUserMeta(): Promise { + try { + const tempUserMeta = await authClient.getUser(); + if (tempUserMeta.error) throw new Error(tempUserMeta.error); + setUserMeta(tempUserMeta.data as unknown as User); + } catch (error) { + logger.error(error); + } + } + + React.useEffect(() => { + void loadUserMeta(); + }, []); + + if (!userMeta) return <>loading; + return ( - {user.name} - - {user.email} + {userMeta.name} + + {userMeta.email} - + Account - + Security - + diff --git a/002_source/cms/src/components/dashboard/layout/vertical/main-nav.tsx b/002_source/cms/src/components/dashboard/layout/vertical/main-nav.tsx index 25fbb83..83095c1 100644 --- a/002_source/cms/src/components/dashboard/layout/vertical/main-nav.tsx +++ b/002_source/cms/src/components/dashboard/layout/vertical/main-nav.tsx @@ -60,7 +60,11 @@ export function MainNav({ items }: MainNavProps): React.JSX.Element { py: 1, }} > - + { setOpenNav(true); @@ -105,11 +109,17 @@ function SearchButton(): React.JSX.Element { return ( - + - + ); } @@ -120,11 +130,18 @@ function ContactsButton(): React.JSX.Element { return ( - + - + ); } @@ -140,12 +157,19 @@ function NotificationsButton(): React.JSX.Element { sx={{ '& .MuiBadge-dot': { borderRadius: '50%', height: '10px', right: '6px', top: '6px', width: '10px' } }} variant="dot" > - + - + ); } @@ -165,11 +189,20 @@ function LanguageSwitch(): React.JSX.Element { sx={{ display: { xs: 'none', lg: 'inline-flex' } }} > - + - + ); } @@ -210,7 +243,11 @@ function UserButton(): React.JSX.Element { - + ); } diff --git a/002_source/cms/src/components/dashboard/settings/side-nav.tsx b/002_source/cms/src/components/dashboard/settings/side-nav.tsx index 55f5f3f..868e793 100644 --- a/002_source/cms/src/components/dashboard/settings/side-nav.tsx +++ b/002_source/cms/src/components/dashboard/settings/side-nav.tsx @@ -71,29 +71,55 @@ export function SideNav(): React.JSX.Element { width: { xs: '100%', md: '240px' }, }} > - + {navItems.map((group) => ( - + {group.title ? (
- + {group.title}
) : null} - + {group.items.map((item) => ( - + ))} ))}
- + AV
Sofia Rivers - + sofia@devias.io
@@ -112,7 +138,10 @@ function NavItem({ disabled, external, href, icon, pathname, title }: NavItemPro const Icon = icon ? icons[icon] : null; return ( - + v.toString(16).padStart(2, '0')).join(''); } -const user = { +const user_xxx = { id: 'USR-000', avatar: '/assets/avatar.png', firstName: 'Sofia', @@ -54,17 +57,23 @@ class AuthClient { async signInWithPassword(params: SignInWithPasswordParams): Promise<{ error?: string }> { const { email, password } = params; - // Make API request + try { + // Make API request + await pb.collection('users').authWithPassword(email, password); - // We do not handle the API, so we'll check if the credentials match with the hardcoded ones. - if (email !== 'sofia@devias.io' || password !== 'Secret1') { + // // We do not handle the API, so we'll check if the credentials match with the hardcoded ones. + // if (email !== 'sofia@devias.io' || password !== 'Secret1') { + // return { error: 'Invalid credentials' }; + // } + // const token = generateToken(); + + localStorage.setItem('custom-auth-token', pb.authStore.token); + + return {}; + } catch (error) { + logger.error(error); return { error: 'Invalid credentials' }; } - - const token = generateToken(); - localStorage.setItem('custom-auth-token', token); - - return {}; } async resetPassword(_: ResetPasswordParams): Promise<{ error?: string }> { @@ -79,16 +88,28 @@ class AuthClient { // Make API request // We do not handle the API, so just check if we have a token in localStorage. - const token = localStorage.getItem('custom-auth-token'); + // const token = localStorage.getItem('custom-auth-token'); + // if (!token) { + // return { data: null }; + // } + try { + logger.debug(JSON.stringify(`getUser: ${pb.authStore.record?.id}`)); + // + if (pb.authStore.record?.id !== undefined) { + const userMeta = await getUserMetaById(pb.authStore.record?.id); + logger.debug({ userMeta }); + return { data: userMeta as unknown as User }; + } - if (!token) { return { data: null }; + } catch (error) { + return { error: 'sorry cannot get user meta' }; } - - return { data: user }; } async signOut(): Promise<{ error?: string }> { + pb.authStore.clear(); + localStorage.removeItem('custom-auth-token'); return {};