@@ -8,6 +8,7 @@ import { useRouter } from 'next/navigation'
88import { Modal , ModalClose , ModalContent , ModalTitle , ModalTrigger } from '@/components/emcn'
99import { GithubIcon , GoogleIcon } from '@/components/icons'
1010import { client } from '@/lib/auth/auth-client'
11+ import { getEnv , isFalsy , isTruthy } from '@/lib/core/config/env'
1112import { captureClientEvent } from '@/lib/posthog/client'
1213import type { PostHogEventMap } from '@/lib/posthog/events'
1314import { getBrandConfig } from '@/ee/whitelabeling'
@@ -25,13 +26,15 @@ interface AuthModalProps {
2526interface ProviderStatus {
2627 githubAvailable : boolean
2728 googleAvailable : boolean
29+ registrationDisabled : boolean
2830}
2931
3032let fetchPromise : Promise < ProviderStatus > | null = null
3133
3234const FALLBACK_STATUS : ProviderStatus = {
3335 githubAvailable : false ,
3436 googleAvailable : false ,
37+ registrationDisabled : false ,
3538}
3639
3740const SOCIAL_BTN =
@@ -44,9 +47,10 @@ function fetchProviderStatus(): Promise<ProviderStatus> {
4447 if ( ! r . ok ) throw new Error ( `HTTP ${ r . status } ` )
4548 return r . json ( )
4649 } )
47- . then ( ( { githubAvailable, googleAvailable } : ProviderStatus ) => ( {
50+ . then ( ( { githubAvailable, googleAvailable, registrationDisabled } : ProviderStatus ) => ( {
4851 githubAvailable,
4952 googleAvailable,
53+ registrationDisabled,
5054 } ) )
5155 . catch ( ( ) => {
5256 fetchPromise = null
@@ -68,17 +72,20 @@ export function AuthModal({ children, defaultView = 'login', source }: AuthModal
6872 } , [ ] )
6973
7074 const hasSocial = providerStatus ?. githubAvailable || providerStatus ?. googleAvailable
75+ const ssoEnabled = isTruthy ( getEnv ( 'NEXT_PUBLIC_SSO_ENABLED' ) )
76+ const emailEnabled = ! isFalsy ( getEnv ( 'NEXT_PUBLIC_EMAIL_PASSWORD_SIGNUP_ENABLED' ) )
77+ const hasModalContent = hasSocial || ssoEnabled
7178
7279 useEffect ( ( ) => {
73- if ( open && providerStatus && ! hasSocial ) {
80+ if ( open && providerStatus && ! hasModalContent ) {
7481 setOpen ( false )
7582 router . push ( defaultView === 'login' ? '/login' : '/signup' )
7683 }
77- } , [ open , providerStatus , hasSocial , defaultView , router ] )
84+ } , [ open , providerStatus , hasModalContent , defaultView , router ] )
7885
7986 const handleOpenChange = useCallback (
8087 ( nextOpen : boolean ) => {
81- if ( nextOpen && providerStatus && ! hasSocial ) {
88+ if ( nextOpen && providerStatus && ! hasModalContent ) {
8289 router . push ( defaultView === 'login' ? '/login' : '/signup' )
8390 return
8491 }
@@ -88,7 +95,7 @@ export function AuthModal({ children, defaultView = 'login', source }: AuthModal
8895 captureClientEvent ( 'auth_modal_opened' , { view : defaultView , source } )
8996 }
9097 } ,
91- [ defaultView , hasSocial , providerStatus , router , source ]
98+ [ defaultView , hasModalContent , providerStatus , router , source ]
9299 )
93100
94101 const handleSocialLogin = useCallback ( async ( provider : 'github' | 'google' ) => {
@@ -102,6 +109,11 @@ export function AuthModal({ children, defaultView = 'login', source }: AuthModal
102109 }
103110 } , [ ] )
104111
112+ const handleSSOLogin = useCallback ( ( ) => {
113+ setOpen ( false )
114+ router . push ( '/sso' )
115+ } , [ router ] )
116+
105117 const handleEmailContinue = useCallback ( ( ) => {
106118 setOpen ( false )
107119 router . push ( view === 'login' ? '/login' : '/signup' )
@@ -176,38 +188,51 @@ export function AuthModal({ children, defaultView = 'login', source }: AuthModal
176188 </ span >
177189 </ button >
178190 ) }
191+ { ssoEnabled && (
192+ < button type = 'button' onClick = { handleSSOLogin } className = { SOCIAL_BTN } >
193+ Sign in with SSO
194+ </ button >
195+ ) }
179196 </ div >
180197
181- < div className = 'relative my-4' >
182- < div className = 'absolute inset-0 flex items-center' >
183- < div className = 'w-full border-[var(--landing-bg-elevated)] border-t' />
184- </ div >
185- < div className = 'relative flex justify-center text-[13.5px]' >
186- < span className = 'bg-[var(--landing-bg)] px-4 text-[var(--landing-text-muted)]' >
187- Or
188- </ span >
189- </ div >
190- </ div >
198+ { emailEnabled && (
199+ < >
200+ < div className = 'relative my-4' >
201+ < div className = 'absolute inset-0 flex items-center' >
202+ < div className = 'w-full border-[var(--landing-bg-elevated)] border-t' />
203+ </ div >
204+ < div className = 'relative flex justify-center text-[13.5px]' >
205+ < span className = 'bg-[var(--landing-bg)] px-4 text-[var(--landing-text-muted)]' >
206+ Or
207+ </ span >
208+ </ div >
209+ </ div >
191210
192- < button
193- type = 'button'
194- onClick = { handleEmailContinue }
195- className = 'flex h-[32px] w-full items-center justify-center rounded-[5px] border border-[var(--auth-primary-btn-border)] bg-[var(--auth-primary-btn-bg)] text-[13.5px] text-[var(--auth-primary-btn-text)] transition-colors hover:border-[var(--auth-primary-btn-hover-border)] hover:bg-[var(--auth-primary-btn-hover-bg)]'
196- >
197- Continue with email
198- </ button >
211+ < button
212+ type = 'button'
213+ onClick = { handleEmailContinue }
214+ className = 'flex h-[32px] w-full items-center justify-center rounded-[5px] border border-[var(--auth-primary-btn-border)] bg-[var(--auth-primary-btn-bg)] text-[13.5px] text-[var(--auth-primary-btn-text)] transition-colors hover:border-[var(--auth-primary-btn-hover-border)] hover:bg-[var(--auth-primary-btn-hover-bg)]'
215+ >
216+ Continue with email
217+ </ button >
218+ </ >
219+ ) }
199220
200221 < div className = 'mt-4 text-center text-[13.5px]' >
201222 < span className = 'text-[var(--landing-text-muted)]' >
202223 { view === 'login' ? "Don't have an account? " : 'Already have an account? ' }
203224 </ span >
204- < button
205- type = 'button'
206- onClick = { ( ) => setView ( view === 'login' ? 'signup' : 'login' ) }
207- className = 'text-[var(--landing-text)] underline-offset-4 transition hover:text-white hover:underline'
208- >
209- { view === 'login' ? 'Sign up' : 'Sign in' }
210- </ button >
225+ { view === 'login' && providerStatus . registrationDisabled ? (
226+ < span className = 'text-[var(--landing-text-muted)]' > Registration is disabled</ span >
227+ ) : (
228+ < button
229+ type = 'button'
230+ onClick = { ( ) => setView ( view === 'login' ? 'signup' : 'login' ) }
231+ className = 'text-[var(--landing-text)] underline-offset-4 transition hover:text-white hover:underline'
232+ >
233+ { view === 'login' ? 'Sign up' : 'Sign in' }
234+ </ button >
235+ ) }
211236 </ div >
212237 </ >
213238 ) }
0 commit comments