From 19120ee7f1e1b129067c07b115c17b201e550906 Mon Sep 17 00:00:00 2001 From: javayhu Date: Thu, 21 Aug 2025 23:54:28 +0800 Subject: [PATCH] refactor: replace password card logic with useHasCredentialProvider hook --- .../security/password-card-wrapper.tsx | 41 ++++------------- src/hooks/use-auth.ts | 44 +++++++++++++++++++ 2 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 src/hooks/use-auth.ts diff --git a/src/components/settings/security/password-card-wrapper.tsx b/src/components/settings/security/password-card-wrapper.tsx index 497de96..a7f5b5f 100644 --- a/src/components/settings/security/password-card-wrapper.tsx +++ b/src/components/settings/security/password-card-wrapper.tsx @@ -10,10 +10,10 @@ import { CardTitle, } from '@/components/ui/card'; import { Skeleton } from '@/components/ui/skeleton'; +import { useHasCredentialProvider } from '@/hooks/use-auth'; import { authClient } from '@/lib/auth-client'; import { cn } from '@/lib/utils'; import { useTranslations } from 'next-intl'; -import { useEffect, useState } from 'react'; /** * PasswordCardWrapper renders either: @@ -24,38 +24,15 @@ import { useEffect, useState } from 'react'; */ export function PasswordCardWrapper() { const { data: session } = authClient.useSession(); - const [hasCredentialProvider, setHasCredentialProvider] = useState(false); - const [isLoading, setIsLoading] = useState(true); + const { hasCredentialProvider, isLoading, error } = useHasCredentialProvider( + session?.user?.id + ); - useEffect(() => { - const checkCredentialProvider = async () => { - if (!session?.user) { - setIsLoading(false); - return; - } - - try { - // Get the user's linked accounts - const accounts = await authClient.listAccounts(); - // console.log('accounts', accounts); - - // Check if the response is successful and contains accounts data - if ('data' in accounts && Array.isArray(accounts.data)) { - // Check if any account has a credential provider (provider === 'credential') - const hasCredential = accounts.data.some( - (account) => account.provider === 'credential' - ); - setHasCredentialProvider(hasCredential); - } - } catch (error) { - console.error('Error checking credential provider:', error); - } finally { - setIsLoading(false); - } - }; - - checkCredentialProvider(); - }, [session]); + // Handle error state + if (error) { + console.error('check credential provider error:', error); + return null; + } // Don't render anything while loading if (isLoading) { diff --git a/src/hooks/use-auth.ts b/src/hooks/use-auth.ts new file mode 100644 index 0000000..4ae3a40 --- /dev/null +++ b/src/hooks/use-auth.ts @@ -0,0 +1,44 @@ +import { authClient } from '@/lib/auth-client'; +import { useQuery } from '@tanstack/react-query'; + +// Query keys +export const userAccountsKeys = { + all: ['userAccounts'] as const, + list: (userId: string) => [...userAccountsKeys.all, 'list', userId] as const, +}; + +// Hook to fetch user accounts +export function useUserAccounts(userId: string | undefined) { + return useQuery({ + queryKey: userAccountsKeys.list(userId || ''), + queryFn: async () => { + if (!userId) { + throw new Error('User ID is required'); + } + + const accounts = await authClient.listAccounts(); + + // Check if the response is successful and contains accounts data + if ('data' in accounts && Array.isArray(accounts.data)) { + return accounts.data; + } + + throw new Error('Failed to fetch user accounts'); + }, + enabled: !!userId, + }); +} + +// Hook to check if user has credential provider +export function useHasCredentialProvider(userId: string | undefined) { + const { data: accounts, isLoading, error } = useUserAccounts(userId); + + const hasCredentialProvider = + accounts?.some((account) => account.provider === 'credential') ?? false; + + return { + hasCredentialProvider, + isLoading, + error, + }; +}