@@ -5,7 +5,7 @@ import { Chip, cn } from '@sim/emcn'
55import { createLogger } from '@sim/logger'
66import { getErrorMessage } from '@sim/utils/errors'
77import { GithubIcon , GoogleIcon , MicrosoftIcon } from '@/components/icons'
8- import { client } from '@/lib/auth/auth-client '
8+ import { type SocialSignInProvider , startSocialSignIn } from '@/lib/auth/social-sign-in '
99import { DEFAULT_POST_AUTH_ROUTE } from '@/app/(auth)/auth-redirect'
1010import { AUTH_BUTTON_CLASS } from '@/app/(auth)/components/constants'
1111
@@ -15,107 +15,63 @@ interface SocialLoginButtonsProps {
1515 githubAvailable : boolean
1616 googleAvailable : boolean
1717 microsoftAvailable : boolean
18+ view : 'login' | 'signup'
1819 callbackURL ?: string
1920 children ?: ReactNode
2021}
2122
23+ /** Display order of the provider buttons. */
24+ const PROVIDERS = [
25+ { provider : 'google' , label : 'Google' , icon : GoogleIcon } ,
26+ { provider : 'microsoft' , label : 'Microsoft' , icon : MicrosoftIcon } ,
27+ { provider : 'github' , label : 'GitHub' , icon : GithubIcon } ,
28+ ] as const
29+
2230export function SocialLoginButtons ( {
2331 githubAvailable,
2432 googleAvailable,
2533 microsoftAvailable,
34+ view,
2635 callbackURL = DEFAULT_POST_AUTH_ROUTE ,
2736 children,
2837} : SocialLoginButtonsProps ) {
29- const [ isGithubLoading , setIsGithubLoading ] = useState ( false )
30- const [ isGoogleLoading , setIsGoogleLoading ] = useState ( false )
31- const [ isMicrosoftLoading , setIsMicrosoftLoading ] = useState ( false )
32-
33- async function signInWithGithub ( ) {
34- if ( ! githubAvailable ) return
38+ const [ loadingProvider , setLoadingProvider ] = useState < SocialSignInProvider | null > ( null )
3539
36- setIsGithubLoading ( true )
37- try {
38- await client . signIn . social ( { provider : 'github' , callbackURL } )
39- } catch ( err ) {
40- logger . error ( 'GitHub sign-in failed' , { error : getErrorMessage ( err ) } )
41- } finally {
42- setIsGithubLoading ( false )
43- }
40+ const available : Record < SocialSignInProvider , boolean > = {
41+ github : githubAvailable ,
42+ google : googleAvailable ,
43+ microsoft : microsoftAvailable ,
4444 }
4545
46- async function signInWithGoogle ( ) {
47- if ( ! googleAvailable ) return
48-
49- setIsGoogleLoading ( true )
46+ async function signIn ( provider : SocialSignInProvider , label : string ) {
47+ setLoadingProvider ( provider )
5048 try {
51- await client . signIn . social ( { provider : 'google ' , callbackURL } )
49+ await startSocialSignIn ( { provider, view , surface : 'auth_page ' , callbackURL } )
5250 } catch ( err ) {
53- logger . error ( 'Google sign-in failed' , { error : getErrorMessage ( err ) } )
51+ logger . error ( ` ${ label } sign-in failed` , { error : getErrorMessage ( err ) } )
5452 } finally {
55- setIsGoogleLoading ( false )
53+ setLoadingProvider ( null )
5654 }
5755 }
5856
59- async function signInWithMicrosoft ( ) {
60- if ( ! microsoftAvailable ) return
61-
62- setIsMicrosoftLoading ( true )
63- try {
64- await client . signIn . social ( { provider : 'microsoft' , callbackURL } )
65- } catch ( err ) {
66- logger . error ( 'Microsoft sign-in failed' , { error : getErrorMessage ( err ) } )
67- } finally {
68- setIsMicrosoftLoading ( false )
69- }
70- }
71-
72- const githubButton = (
73- < Chip
74- fullWidth
75- leftIcon = { GithubIcon }
76- className = { cn ( AUTH_BUTTON_CLASS , 'border border-[var(--border-1)]' ) }
77- disabled = { ! githubAvailable || isGithubLoading }
78- onClick = { signInWithGithub }
79- >
80- { isGithubLoading ? 'Connecting…' : 'GitHub' }
81- </ Chip >
82- )
83-
84- const googleButton = (
85- < Chip
86- fullWidth
87- leftIcon = { GoogleIcon }
88- className = { cn ( AUTH_BUTTON_CLASS , 'border border-[var(--border-1)]' ) }
89- disabled = { ! googleAvailable || isGoogleLoading }
90- onClick = { signInWithGoogle }
91- >
92- { isGoogleLoading ? 'Connecting…' : 'Google' }
93- </ Chip >
94- )
95-
96- const microsoftButton = (
97- < Chip
98- fullWidth
99- leftIcon = { MicrosoftIcon }
100- className = { cn ( AUTH_BUTTON_CLASS , 'border border-[var(--border-1)]' ) }
101- disabled = { ! microsoftAvailable || isMicrosoftLoading }
102- onClick = { signInWithMicrosoft }
103- >
104- { isMicrosoftLoading ? 'Connecting…' : 'Microsoft' }
105- </ Chip >
106- )
107-
108- const hasAnyOAuthProvider = githubAvailable || googleAvailable || microsoftAvailable
109-
110- if ( ! hasAnyOAuthProvider && ! children ) {
57+ if ( ! githubAvailable && ! googleAvailable && ! microsoftAvailable && ! children ) {
11158 return null
11259 }
11360
11461 return (
11562 < div className = 'grid gap-3' >
116- { googleAvailable && googleButton }
117- { microsoftAvailable && microsoftButton }
118- { githubAvailable && githubButton }
63+ { PROVIDERS . filter ( ( { provider } ) => available [ provider ] ) . map ( ( { provider, label, icon } ) => (
64+ < Chip
65+ key = { provider }
66+ fullWidth
67+ leftIcon = { icon }
68+ className = { cn ( AUTH_BUTTON_CLASS , 'border border-[var(--border)]' ) }
69+ disabled = { loadingProvider !== null }
70+ onClick = { ( ) => signIn ( provider , label ) }
71+ >
72+ { loadingProvider === provider ? 'Connecting…' : label }
73+ </ Chip >
74+ ) ) }
11975 { children }
12076 </ div >
12177 )
0 commit comments