@tern-secure/nextjs 4.0.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/app-router/client/TernSecureProvider.js +17 -2
- package/dist/cjs/app-router/client/TernSecureProvider.js.map +1 -1
- package/dist/cjs/app-router/client/actions.js +49 -49
- package/dist/cjs/app-router/client/actions.js.map +1 -1
- package/dist/cjs/app-router/route-handler/internal-route.js +17 -2
- package/dist/cjs/app-router/route-handler/internal-route.js.map +1 -1
- package/dist/cjs/app-router/server/auth.js +42 -28
- package/dist/cjs/app-router/server/auth.js.map +1 -1
- package/dist/cjs/app-router/server/edge-session.js +80 -0
- package/dist/cjs/app-router/server/edge-session.js.map +1 -0
- package/dist/cjs/app-router/server/index.js +4 -0
- package/dist/cjs/app-router/server/index.js.map +1 -1
- package/dist/cjs/app-router/server/jwt.js +141 -0
- package/dist/cjs/app-router/server/jwt.js.map +1 -0
- package/dist/cjs/app-router/server/sessionTernSecure.js +14 -9
- package/dist/cjs/app-router/server/sessionTernSecure.js.map +1 -1
- package/dist/cjs/app-router/server/ternSecureMiddleware.js +134 -13
- package/dist/cjs/app-router/server/ternSecureMiddleware.js.map +1 -1
- package/dist/cjs/boundary/TernSecureClientProvider.js +163 -40
- package/dist/cjs/boundary/TernSecureClientProvider.js.map +1 -1
- package/dist/cjs/boundary/TernSecureCtx.js.map +1 -1
- package/dist/cjs/boundary/hooks/useAuth.js +7 -8
- package/dist/cjs/boundary/hooks/useAuth.js.map +1 -1
- package/dist/cjs/components/sign-in.js +136 -45
- package/dist/cjs/components/sign-in.js.map +1 -1
- package/dist/cjs/components/sign-out-button.js +10 -1
- package/dist/cjs/components/sign-out-button.js.map +1 -1
- package/dist/cjs/components/sign-out.js +12 -3
- package/dist/cjs/components/sign-out.js.map +1 -1
- package/dist/cjs/components/sign-up.js +10 -5
- package/dist/cjs/components/sign-up.js.map +1 -1
- package/dist/cjs/errors.js +232 -5
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/index.js +0 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types.js +14 -0
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/utils/construct.js +50 -18
- package/dist/cjs/utils/construct.js.map +1 -1
- package/dist/cjs/utils/redirect.js +57 -0
- package/dist/cjs/utils/redirect.js.map +1 -0
- package/dist/esm/app-router/client/TernSecureProvider.js +17 -2
- package/dist/esm/app-router/client/TernSecureProvider.js.map +1 -1
- package/dist/esm/app-router/client/actions.js +59 -51
- package/dist/esm/app-router/client/actions.js.map +1 -1
- package/dist/esm/app-router/route-handler/internal-route.js +13 -1
- package/dist/esm/app-router/route-handler/internal-route.js.map +1 -1
- package/dist/esm/app-router/server/auth.js +40 -28
- package/dist/esm/app-router/server/auth.js.map +1 -1
- package/dist/esm/app-router/server/edge-session.js +56 -0
- package/dist/esm/app-router/server/edge-session.js.map +1 -0
- package/dist/esm/app-router/server/index.js +4 -2
- package/dist/esm/app-router/server/index.js.map +1 -1
- package/dist/esm/app-router/server/jwt.js +117 -0
- package/dist/esm/app-router/server/jwt.js.map +1 -0
- package/dist/esm/app-router/server/sessionTernSecure.js +14 -9
- package/dist/esm/app-router/server/sessionTernSecure.js.map +1 -1
- package/dist/esm/app-router/server/ternSecureMiddleware.js +132 -13
- package/dist/esm/app-router/server/ternSecureMiddleware.js.map +1 -1
- package/dist/esm/boundary/TernSecureClientProvider.js +164 -41
- package/dist/esm/boundary/TernSecureClientProvider.js.map +1 -1
- package/dist/esm/boundary/TernSecureCtx.js.map +1 -1
- package/dist/esm/boundary/hooks/useAuth.js +7 -8
- package/dist/esm/boundary/hooks/useAuth.js.map +1 -1
- package/dist/esm/components/sign-in.js +137 -46
- package/dist/esm/components/sign-in.js.map +1 -1
- package/dist/esm/components/sign-out-button.js +11 -2
- package/dist/esm/components/sign-out-button.js.map +1 -1
- package/dist/esm/components/sign-out.js +13 -4
- package/dist/esm/components/sign-out.js.map +1 -1
- package/dist/esm/components/sign-up.js +10 -5
- package/dist/esm/components/sign-up.js.map +1 -1
- package/dist/esm/errors.js +228 -4
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.js +0 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types.js +6 -0
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/construct.js +46 -17
- package/dist/esm/utils/construct.js.map +1 -1
- package/dist/esm/utils/redirect.js +32 -0
- package/dist/esm/utils/redirect.js.map +1 -0
- package/dist/types/app-router/client/TernSecureProvider.d.ts +14 -3
- package/dist/types/app-router/client/TernSecureProvider.d.ts.map +1 -1
- package/dist/types/app-router/client/actions.d.ts +23 -21
- package/dist/types/app-router/client/actions.d.ts.map +1 -1
- package/dist/types/app-router/route-handler/internal-route.d.ts +3 -0
- package/dist/types/app-router/route-handler/internal-route.d.ts.map +1 -1
- package/dist/types/app-router/server/auth.d.ts +13 -1
- package/dist/types/app-router/server/auth.d.ts.map +1 -1
- package/dist/types/app-router/server/edge-session.d.ts +15 -0
- package/dist/types/app-router/server/edge-session.d.ts.map +1 -0
- package/dist/types/app-router/server/index.d.ts +3 -2
- package/dist/types/app-router/server/index.d.ts.map +1 -1
- package/dist/types/app-router/server/jwt.d.ts +20 -0
- package/dist/types/app-router/server/jwt.d.ts.map +1 -0
- package/dist/types/app-router/server/sessionTernSecure.d.ts +4 -1
- package/dist/types/app-router/server/sessionTernSecure.d.ts.map +1 -1
- package/dist/types/app-router/server/ternSecureMiddleware.d.ts +17 -4
- package/dist/types/app-router/server/ternSecureMiddleware.d.ts.map +1 -1
- package/dist/types/boundary/TernSecureClientProvider.d.ts +17 -1
- package/dist/types/boundary/TernSecureClientProvider.d.ts.map +1 -1
- package/dist/types/boundary/TernSecureCtx.d.ts +3 -1
- package/dist/types/boundary/TernSecureCtx.d.ts.map +1 -1
- package/dist/types/boundary/hooks/useAuth.d.ts +4 -1
- package/dist/types/boundary/hooks/useAuth.d.ts.map +1 -1
- package/dist/types/components/sign-in.d.ts +1 -2
- package/dist/types/components/sign-in.d.ts.map +1 -1
- package/dist/types/components/sign-out-button.d.ts +2 -1
- package/dist/types/components/sign-out-button.d.ts.map +1 -1
- package/dist/types/components/sign-out.d.ts +2 -1
- package/dist/types/components/sign-out.d.ts.map +1 -1
- package/dist/types/components/sign-up.d.ts.map +1 -1
- package/dist/types/components/ui/alert.d.ts +1 -1
- package/dist/types/components/ui/button.d.ts +1 -1
- package/dist/types/errors.d.ts +36 -2
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types.d.ts +35 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/construct.d.ts +20 -4
- package/dist/types/utils/construct.d.ts.map +1 -1
- package/dist/types/utils/redirect.d.ts +9 -0
- package/dist/types/utils/redirect.d.ts.map +1 -0
- package/package.json +7 -6
- package/dist/cjs/boundary/hooks/useUser.js +0 -44
- package/dist/cjs/boundary/hooks/useUser.js.map +0 -1
- package/dist/esm/boundary/hooks/useUser.js +0 -20
- package/dist/esm/boundary/hooks/useUser.js.map +0 -1
- package/dist/types/boundary/hooks/useUser.d.ts +0 -7
- package/dist/types/boundary/hooks/useUser.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/sign-in.tsx"],"sourcesContent":["'use client'\n\nimport React, { useState, useCallback, useEffect } from 'react'\nimport { useSearchParams, useRouter, usePathname} from 'next/navigation'\nimport { signInWithEmail, signInWithRedirectGoogle, signInWithMicrosoft, type SignInResponse } from '../app-router/client/actions'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from \"./ui/card\"\nimport { Input } from \"./ui/input\"\nimport { Label } from \"./ui/label\"\nimport { Button } from \"./ui/button\"\nimport { Alert, AlertDescription } from \"./ui/alert\"\nimport { Separator } from \"./ui/separator\"\nimport { cn } from \"../lib/utils\"\nimport { Loader2 } from 'lucide-react'\nimport { getRedirectResult } from 'firebase/auth'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { createSessionCookie } from '../app-router/server/sessionTernSecure'\nimport { AuthBackground } from './background'\nimport { getValidRedirectUrl } from '../utils/construct'\nimport { ERRORS } from '../errors'\nimport { handleInternalRoute } from '../app-router/route-handler/internal-route'\n\n\nconst authDomain = process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN;\nconst appName = process.env.NEXT_PUBLIC_FIREBASE_APP_NAME || 'TernSecure';\n\n\nexport interface SignInProps {\n redirectUrl?: string\n onError?: (error: Error) => void\n onSuccess?: () => void\n requiresVerification?: boolean\n className?: string\n customStyles?: {\n card?: string\n input?: string\n button?: string\n label?: string\n separator?: string\n title?: string\n description?: string\n socialButton?: string\n }\n}\n\nexport function SignIn({\n redirectUrl,\n onError,\n onSuccess,\n requiresVerification = true,\n className,\n customStyles = {}\n}: SignInProps) {\n const [loading, setLoading] = useState(false)\n const [checkingRedirect, setCheckingRedirect] = useState(true)\n const [error, setError] = useState('')\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [authResponse, setAuthResponse] = useState<SignInResponse | null>(null)\n const searchParams = useSearchParams()\n const isRedirectSignIn = searchParams.get('signInRedirect') === 'true'\n const router = useRouter()\n const pathname = usePathname()\n const InternalComponent = handleInternalRoute(pathname)\n\n if (InternalComponent) {\n return <InternalComponent />\n }\n\n\n const handleRedirectResult = useCallback(async () => {\n if (!isRedirectSignIn) return false\n setCheckingRedirect(true)\n try {\n console.log('Checking redirect result...');\n console.log('Current hostname:', window.location.hostname);\n console.log('Auth domain hostname:', authDomain);\n\n const isOnAuth = authDomain && \n window.location.hostname === authDomain.replace(/https?:\\/\\//, '');\n console.log('Is on AuthDomain:', isOnAuth);\n\n\n const result = await getRedirectResult(ternSecureAuth)\n console.log('Redirect result:', result);\n if (result) {\n const idToken = await result.user.getIdToken()\n const sessionResult = await createSessionCookie(idToken)\n if (!sessionResult.success) {\n throw new Error('Failed to create session')\n }\n const storedRedirectUrl = sessionStorage.getItem('auth_return_url')\n sessionStorage.removeItem('auth_redirect_url') \n onSuccess?.()\n window.location.href = storedRedirectUrl || getValidRedirectUrl(redirectUrl, searchParams)\n return true\n }\n setCheckingRedirect(false)\n } catch (err) {\n console.error('Redirect result error:', err)\n const errorMessage = err instanceof Error ? err.message : 'Authentication failed'\n setError(errorMessage)\n onError?.(err instanceof Error ? err : new Error(errorMessage))\n sessionStorage.removeItem('auth_redirect_url')\n return false\n }\n }, [isRedirectSignIn, redirectUrl, searchParams, onSuccess, onError])\n\n ///const REDIRECT_TIMEOUT = 5000;\n\n useEffect(() => {\n //let timeoutId: NodeJS.Timeout;\n\n if (isRedirectSignIn) {\n handleRedirectResult();\n\n /*timeoutId = setTimeout(() => {\n console.warn('Redirect check timed out');\n setCheckingRedirect(false);\n setError('Sign in took too long. Please try again.');\n \n }, REDIRECT_TIMEOUT);\n }\n\n return () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }*/\n };\n }, [handleRedirectResult, isRedirectSignIn])\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n setLoading(true)\n setAuthResponse(null)\n try {\n const response = await signInWithEmail(email, password)\n setAuthResponse(response)\n\n // if (response.error === ERRORS.REQUIRES_VERIFICATION) {\n // if (requiresVerification) {\n // setError(response.message || 'Email verification required')\n // return\n // }\n // }\n\n if (response.user) {\n if (requiresVerification && !response.user.emailVerified) {\n setError('Email verification required')\n return\n }\n\n const idToken = await response.user.getIdToken()\n const sessionResult = await createSessionCookie(idToken)\n\n if(!sessionResult.success) {\n throw new Error(sessionResult.message || 'Failed to create session')\n }\n\n onSuccess?.()\n window.location.href = getValidRedirectUrl(redirectUrl, searchParams)\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Failed to sign in'\n setError(errorMessage)\n onError?.(err instanceof Error ? err : new Error('Failed to sign in'))\n } finally {\n setLoading(false)\n }\n }\n\n const handleSocialSignIn = async (provider: 'google' | 'microsoft') => {\n setLoading(true)\n try {\n\n const validRedirectUrl = getValidRedirectUrl(redirectUrl, searchParams)\n sessionStorage.setItem('auth_redirect_url', validRedirectUrl)\n\n const currentUrl = new URL(window.location.href)\n currentUrl.searchParams.set('signInRedirect', 'true')\n window.history.replaceState({}, '', currentUrl.toString())\n\n const result = provider === 'google' ? await signInWithRedirectGoogle() : await signInWithMicrosoft()\n if (!result.success) {\n throw new Error(result.error)\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : `Failed to sign in with ${provider}`\n setError(errorMessage)\n onError?.(err instanceof Error ? err : new Error(`Failed to sign in with ${provider}`))\n setLoading(false)\n sessionStorage.removeItem('auth_redirect_url')\n }\n }\n\n if (checkingRedirect && isRedirectSignIn) {\n return (\n <div className=\"flex min-h-screen items-center justify-center\">\n <div className=\"text-center space-y-4\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto\" />\n \n </div>\n </div>\n )\n }\n\n return (\n <div className=\"relative flex items-center justify-center\">\n <AuthBackground />\n <Card className={cn(\"w-full max-w-md mx-auto mt-8\", className, customStyles.card)}>\n <CardHeader className=\"space-y-1 text-center\">\n <CardTitle className={cn(\"font-bold\", customStyles.title)}>Sign in to {`${appName}`}</CardTitle>\n <CardDescription className={cn(\"text-muted-foreground\", customStyles.description)}>\n Please sign in to continue\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {error && (\n <Alert variant={authResponse?.error === ERRORS.REQUIRES_VERIFICATION ? \"destructive\" : \"destructive\"}>\n <AlertDescription>\n <span>{error}</span>\n {authResponse?.error === ERRORS.REQUIRES_VERIFICATION && (\n <Button\n variant=\"link\"\n className=\"p-0 h-auto font-normal text-sm hover:underline\"\n onClick={() => router.push(`/sign-in/verify`)}\n >\n Request new verification email →\n </Button>\n )}\n </AlertDescription>\n </Alert>\n )}\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\" className={cn(customStyles.label)}>Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"m@example.com\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n disabled={loading}\n className={cn(customStyles.input)}\n required\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"password\" className={cn(customStyles.label)}>Password</Label>\n <Input\n id=\"password\"\n type=\"password\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n disabled={loading}\n className={cn(customStyles.input)}\n required\n />\n </div>\n <Button type=\"submit\" disabled={loading} className={cn(\"w-full\", customStyles.button)}>\n {loading ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n Signing in...\n </>\n ) : (\n 'Sign in'\n )}\n </Button>\n </form>\n <div className=\"relative\">\n <div className=\"absolute inset-0 flex items-center\">\n <Separator className={cn(customStyles.separator)} />\n </div>\n <div className=\"relative flex justify-center text-xs uppercase\">\n <span className=\"bg-background px-2 text-muted-foreground\">Or continue with</span>\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <Button \n variant=\"outline\" \n disabled={loading} \n onClick={() => handleSocialSignIn('google')} \n className={cn(\"flex items-center justify-center\", customStyles.socialButton)}\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\" fill=\"#4285F4\"/>\n <path d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" fill=\"#34A853\"/>\n <path d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" fill=\"#FBBC05\"/>\n <path d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" fill=\"#EA4335\"/>\n </svg>\n Google\n </Button>\n <Button \n variant=\"outline\" \n disabled={loading} \n onClick={() => handleSocialSignIn('microsoft')} \n className={cn(\"flex items-center justify-center\", customStyles.socialButton)}\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 23 23\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill=\"#f3f3f3\" d=\"M0 0h23v23H0z\"/>\n <path fill=\"#f35325\" d=\"M1 1h10v10H1z\"/>\n <path fill=\"#81bc06\" d=\"M12 1h10v10H12z\"/>\n <path fill=\"#05a6f0\" d=\"M1 12h10v10H1z\"/>\n <path fill=\"#ffba08\" d=\"M12 12h10v10H12z\"/>\n </svg>\n Microsoft\n </Button>\n </div>\n </CardContent>\n <CardFooter className=\"flex justify-center\">\n <p className=\"text-sm text-muted-foreground\">\n Don't have an account?{' '}\n <a href=\"/sign-up\" className=\"text-primary hover:underline\">\n Sign up\n </a>\n </p>\n </CardFooter>\n </Card>\n </div>\n )\n}\n\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/sign-in.tsx"],"sourcesContent":["'use client'\n\nimport React, { useState, useCallback, useEffect } from 'react'\nimport { useSearchParams, useRouter, usePathname} from 'next/navigation'\nimport { signInWithEmail, signInWithRedirectGoogle, signInWithMicrosoft } from '../app-router/client/actions'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from \"./ui/card\"\nimport { Input } from \"./ui/input\"\nimport { Label } from \"./ui/label\"\nimport { Button } from \"./ui/button\"\nimport { Alert, AlertDescription } from \"./ui/alert\"\nimport { Separator } from \"./ui/separator\"\nimport { cn } from \"../lib/utils\"\nimport { Loader2, Eye, EyeOff } from 'lucide-react'\nimport { getRedirectResult, User } from 'firebase/auth'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { createSessionCookie } from '../app-router/server/sessionTernSecure'\nimport { AuthBackground } from './background'\nimport { getValidRedirectUrl } from '../utils/construct'\nimport { handleInternalRoute } from '../app-router/route-handler/internal-route'\nimport type { SignInResponse } from '../types'\nimport { useAuth } from '../boundary/hooks/useAuth'\nimport { getErrorAlertVariant, ErrorCode } from '../errors'\n\n\n\nconst authDomain = process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN;\nconst appName = process.env.NEXT_PUBLIC_FIREBASE_APP_NAME || 'TernSecure';\n\n\nexport interface SignInProps {\n redirectUrl?: string\n onError?: (error: Error) => void\n onSuccess?: () => void\n className?: string\n customStyles?: {\n card?: string\n input?: string\n button?: string\n label?: string\n separator?: string\n title?: string\n description?: string\n socialButton?: string\n }\n}\n\n\nexport function SignIn({\n redirectUrl,\n onError,\n onSuccess,\n className,\n customStyles = {}\n}: SignInProps) {\n const [loading, setLoading] = useState(false)\n const [checkingRedirect, setCheckingRedirect] = useState(true)\n const [formError, setFormError] = useState<SignInResponse | null>(null)\n const [error, setError] = useState('')\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [showPassword, setShowPassword] = useState(false)\n const [passwordFocused, setPasswordFocused] = useState(false)\n const [authResponse, setAuthResponse] = useState<SignInResponse | null>(null)\n const [authErrorMessage, setAuthErrorMessage] = useState<string | null>(null)\n const searchParams = useSearchParams()\n const isRedirectSignIn = searchParams.get('signInRedirect') === 'true'\n const router = useRouter()\n const pathname = usePathname()\n const InternalComponent = handleInternalRoute(pathname || \"\")\n const { requiresVerification, error: authError, status } = useAuth()\n const validRedirectUrl = getValidRedirectUrl(searchParams, redirectUrl)\n\n\n if (InternalComponent) {\n return <InternalComponent />\n }\n\n useEffect(() => {\n if (authError && status !== \"loading\" && status !== \"unauthenticated\") {\n\n const message = authError.message || \"Authentication failed\"\n setAuthErrorMessage(message)\n\n if(!authResponse || authResponse.message !== message) {\n setAuthResponse(authError as SignInResponse)\n }\n } else {\n setAuthErrorMessage(null)\n }\n }, [authError, status, authResponse])\n\n const handleSuccessfulAuth = useCallback(\n async (user: User) => {\n try {\n const idToken = await user.getIdToken()\n const sessionResult = await createSessionCookie(idToken)\n\n if (!sessionResult.success) {\n setFormError({\n success: false, \n message: sessionResult.message || \"Failed to create session\", \n error: 'INTERNAL_ERROR', \n user: null\n })\n }\n\n onSuccess?.()\n\n // Use the finalRedirectUrl for navigation\n if (process.env.NODE_ENV === \"production\") {\n // Use window.location.href in production for a full page reload\n window.location.href = validRedirectUrl\n } else {\n // Use router.push in development\n router.push(validRedirectUrl)\n }\n } catch (err) {\n setFormError({\n success: false, \n message: \"Failed to complete authentication\", \n error: 'INTERNAL_ERROR', \n user: null\n })\n }\n },\n [validRedirectUrl, router, onSuccess],\n )\n\n\n const handleRedirectResult = useCallback(async () => {\n if (!isRedirectSignIn) return false\n setCheckingRedirect(true)\n try {\n console.log('Checking redirect result...');\n console.log('Current hostname:', window.location.hostname);\n console.log('Auth domain hostname:', authDomain);\n\n const isOnAuth = authDomain && \n window.location.hostname === authDomain.replace(/https?:\\/\\//, '');\n console.log('Is on AuthDomain:', isOnAuth);\n\n\n const result = await getRedirectResult(ternSecureAuth)\n console.log('Redirect result:', result);\n if (result) {\n const idToken = await result.user.getIdToken()\n const sessionResult = await createSessionCookie(idToken)\n if (!sessionResult.success) {\n throw new Error('Failed to create session')\n }\n const storedRedirectUrl = sessionStorage.getItem('auth_return_url')\n sessionStorage.removeItem('auth_redirect_url') \n onSuccess?.()\n window.location.href = storedRedirectUrl || getValidRedirectUrl(searchParams, redirectUrl)\n return true\n }\n setCheckingRedirect(false)\n } catch (err) { \n const errorMessage = err as SignInResponse\n setFormError(errorMessage)\n if (onError && err instanceof Error) {\n onError(err)\n }\n sessionStorage.removeItem('auth_redirect_url')\n return false\n }\n }, [isRedirectSignIn, redirectUrl, searchParams, onSuccess, onError])\n\n //const REDIRECT_TIMEOUT = 5000;\n\n useEffect(() => {\n if (isRedirectSignIn) {\n handleRedirectResult()\n }\n }, [handleRedirectResult, isRedirectSignIn])\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n setLoading(true)\n setFormError(null)\n setAuthResponse(null)\n\n try {\n const response= await signInWithEmail(email, password)\n setAuthResponse(response)\n\n if (!response.success) {\n setFormError({\n success: false, \n message: response.message, \n error: response.error, \n user: null\n })\n return\n }\n\n if (response.user) {\n if(requiresVerification && !response.user.emailVerified) {\n setFormError({\n success: false, \n message: 'Email verification required', \n error: 'REQUIRES_VERIFICATION', \n user: response.user\n })\n return\n }\n\n await handleSuccessfulAuth(response.user)\n }\n } catch (err) {\n const errorMessage = err as SignInResponse\n setFormError(errorMessage)\n if (onError && err instanceof Error) {\n onError(err)\n }\n } finally {\n setLoading(false)\n }\n }\n\n const handleSocialSignIn = async (provider: 'google' | 'microsoft') => {\n setLoading(true)\n try {\n\n const validRedirectUrl = getValidRedirectUrl(searchParams, redirectUrl)\n sessionStorage.setItem('auth_redirect_url', validRedirectUrl)\n\n const currentUrl = new URL(window.location.href)\n currentUrl.searchParams.set('signInRedirect', 'true')\n window.history.replaceState({}, '', currentUrl.toString())\n\n const result = provider === 'google' ? await signInWithRedirectGoogle() : await signInWithMicrosoft()\n if (!result.success) {\n throw new Error(result.error)\n }\n } catch (err) {\n const errorMessage = err as SignInResponse\n setFormError(errorMessage)\n if (onError && err instanceof Error) {\n onError(err)\n }\n setLoading(false)\n sessionStorage.removeItem('auth_redirect_url')\n }\n }\n\n const handleVerificationRedirect = (e: React.MouseEvent) => {\n e.preventDefault()\n router.push(\"/sign-in/verify\")\n }\n\n\n if (checkingRedirect && isRedirectSignIn) {\n return (\n <div className=\"flex min-h-screen items-center justify-center\">\n <div className=\"text-center space-y-4\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto\" />\n \n </div>\n </div>\n )\n }\n\n\nconst activeError = formError || authResponse\nconst showEmailVerificationButton =\n activeError?.error === \"EMAIL_NOT_VERIFIED\" || activeError?.error === \"REQUIRES_VERIFICATION\"\n\n return (\n <div className=\"relative flex items-center justify-center\">\n <AuthBackground />\n <Card className={cn(\"w-full max-w-md mx-auto mt-8\", className, customStyles.card)}>\n <CardHeader className=\"space-y-1 text-center\">\n <CardTitle className={cn(\"font-bold\", customStyles.title)}>Sign in to {`${appName}`} </CardTitle>\n <CardDescription className={cn(\"text-muted-foreground\", customStyles.description)}>\n Please sign in to continue\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {activeError && (\n <Alert variant={getErrorAlertVariant(activeError)} className=\"animate-in fade-in-50\">\n <AlertDescription>\n <span>{activeError.message}</span>\n {showEmailVerificationButton && (\n <Button\n type='button'\n variant=\"link\"\n className=\"p-0 h-auto font-normal text-sm hover:underline\"\n onClick={handleVerificationRedirect}\n >\n Request new verification email →\n </Button>\n )}\n </AlertDescription>\n </Alert>\n )}\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\" className={cn(customStyles.label)}>Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"m@example.com\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n disabled={loading}\n className={cn(customStyles.input)}\n required\n aria-invalid={activeError?.error === \"INVALID_EMAIL\"}\n aria-describedby={activeError ? \"error-message\" : undefined}\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"password\" className={cn(customStyles.label)}>Password</Label>\n <div className=\"relative\">\n <Input\n id=\"password\"\n name=\"password\"\n type={showPassword ? \"text\" : \"password\"}\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n onFocus={() => setPasswordFocused(true)}\n onBlur={() => setPasswordFocused(false)}\n disabled={loading}\n className={cn(customStyles.input)}\n required\n aria-invalid={activeError?.error === \"INVALID_CREDENTIALS\"}\n aria-describedby={activeError ? \"error-message\" : undefined}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-2 top-1/2 -translate-y-1/2 h-8 w-8 hover:bg-transparent\"\n onClick={() => setShowPassword(!showPassword)}\n >\n {showPassword ? (\n <EyeOff className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />\n ) : (\n <Eye className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />\n )}\n <span className=\"sr-only\">{showPassword ? \"Hide password\" : \"Show password\"}</span>\n </Button>\n </div>\n </div>\n <Button type=\"submit\" disabled={loading} className={cn(\"w-full\", customStyles.button)}>\n {loading ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n Signing in...\n </>\n ) : (\n 'Sign in'\n )}\n </Button>\n </form>\n <div className=\"relative\">\n <Separator className={cn(customStyles.separator)} />\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <span className=\"bg-background px-2 text-muted-foreground text-sm\">Or continue with</span>\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <Button \n variant=\"outline\" \n disabled={loading} \n onClick={() => handleSocialSignIn('google')} \n className={cn(\"flex items-center justify-center\", customStyles.socialButton)}\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\" fill=\"#4285F4\"/>\n <path d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" fill=\"#34A853\"/>\n <path d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" fill=\"#FBBC05\"/>\n <path d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" fill=\"#EA4335\"/>\n </svg>\n Google\n </Button>\n <Button \n variant=\"outline\" \n disabled={loading} \n onClick={() => handleSocialSignIn('microsoft')} \n className={cn(\"flex items-center justify-center\", customStyles.socialButton)}\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 23 23\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill=\"#f3f3f3\" d=\"M0 0h23v23H0z\"/>\n <path fill=\"#f35325\" d=\"M1 1h10v10H1z\"/>\n <path fill=\"#81bc06\" d=\"M12 1h10v10H12z\"/>\n <path fill=\"#05a6f0\" d=\"M1 12h10v10H1z\"/>\n <path fill=\"#ffba08\" d=\"M12 12h10v10H12z\"/>\n </svg>\n Microsoft\n </Button>\n </div>\n </CardContent>\n <CardFooter className=\"flex justify-center\">\n <p className=\"text-sm text-muted-foreground\">\n Don't have an account?{' '}\n <a href=\"/sign-up\" className=\"text-primary hover:underline\">\n Sign up\n </a>\n </p>\n </CardFooter>\n </Card>\n </div>\n )\n}\n\n"],"mappings":"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","names":["validRedirectUrl"]}
|
|
@@ -30,24 +30,33 @@ var import_button = require("./ui/button");
|
|
|
30
30
|
var import_client_init = require("../utils/client-init");
|
|
31
31
|
var import_sessionTernSecure = require("../app-router/server/sessionTernSecure");
|
|
32
32
|
var import_utils = require("../lib/utils");
|
|
33
|
+
var import_construct = require("../utils/construct");
|
|
33
34
|
function SignOutButton({
|
|
34
35
|
children = "Sign out",
|
|
35
36
|
onError,
|
|
36
37
|
onSignOutSuccess,
|
|
38
|
+
redirectPath,
|
|
37
39
|
className,
|
|
38
40
|
variant = "outline",
|
|
39
41
|
size = "default",
|
|
40
42
|
...buttonProps
|
|
41
43
|
}) {
|
|
44
|
+
const pathname = (0, import_navigation.usePathname)();
|
|
42
45
|
const router = (0, import_navigation.useRouter)();
|
|
43
46
|
const [isLoading, setIsLoading] = (0, import_react.useState)(false);
|
|
47
|
+
const loginPath = process.env.NEXT_PUBLIC_LOGIN_PATH || "/sign-in";
|
|
44
48
|
const handleSignOut = async () => {
|
|
45
49
|
setIsLoading(true);
|
|
46
50
|
try {
|
|
47
51
|
await (0, import_auth.signOut)(import_client_init.ternSecureAuth);
|
|
48
52
|
await (0, import_sessionTernSecure.clearSessionCookie)();
|
|
49
53
|
onSignOutSuccess == null ? void 0 : onSignOutSuccess();
|
|
50
|
-
|
|
54
|
+
const loginUrl = (0, import_construct.constructUrlWithRedirect)(loginPath, pathname);
|
|
55
|
+
if (process.env.NODE_ENV === "production") {
|
|
56
|
+
window.location.href = loginUrl;
|
|
57
|
+
} else {
|
|
58
|
+
router.push(loginUrl);
|
|
59
|
+
}
|
|
51
60
|
} catch (error) {
|
|
52
61
|
console.error("Sign out error:", error);
|
|
53
62
|
onError == null ? void 0 : onError(error instanceof Error ? error : new Error("Failed to sign out"));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/sign-out-button.tsx"],"sourcesContent":["'use client'\n\nimport { useState } from 'react'\nimport { useRouter } from 'next/navigation'\nimport { signOut } from 'firebase/auth'\nimport { Button, type ButtonProps } from './ui/button'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { clearSessionCookie } from '../app-router/server/sessionTernSecure'\nimport { cn } from '../lib/utils'\n\ntype SignOutCustomProps = {\n children?: React.ReactNode\n onError?: (error: Error) => void\n onSignOutSuccess?: () => void\n className?: string\n variant?: ButtonProps['variant']\n size?: ButtonProps['size']\n}\n\ntype SignOutProps = Omit<ButtonProps, 'onClick'> & SignOutCustomProps\n\nexport function SignOutButton({ \n children = 'Sign out', \n onError,\n onSignOutSuccess,\n className,\n variant = 'outline',\n size = 'default',\n ...buttonProps \n}: SignOutProps) {\n const router = useRouter()\n const [isLoading, setIsLoading] = useState(false)\n\n const handleSignOut = async () => {\n setIsLoading(true)\n try {\n // Sign out from Firebase\n await signOut(ternSecureAuth)\n \n await clearSessionCookie()\n \n // Call success callback if provided\n onSignOutSuccess?.()\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/sign-out-button.tsx"],"sourcesContent":["'use client'\n\nimport { useState } from 'react'\nimport { usePathname, useRouter } from 'next/navigation'\nimport { signOut } from 'firebase/auth'\nimport { Button, type ButtonProps } from './ui/button'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { clearSessionCookie } from '../app-router/server/sessionTernSecure'\nimport { cn } from '../lib/utils'\nimport { constructUrlWithRedirect } from '../utils/construct'\n\n\ntype SignOutCustomProps = {\n children?: React.ReactNode\n onError?: (error: Error) => void\n onSignOutSuccess?: () => void\n redirectPath?: string\n className?: string\n variant?: ButtonProps['variant']\n size?: ButtonProps['size']\n}\n\ntype SignOutProps = Omit<ButtonProps, 'onClick'> & SignOutCustomProps\n\nexport function SignOutButton({ \n children = 'Sign out', \n onError,\n onSignOutSuccess,\n redirectPath,\n className,\n variant = 'outline',\n size = 'default',\n ...buttonProps \n}: SignOutProps) {\n const pathname = usePathname()\n const router = useRouter()\n const [isLoading, setIsLoading] = useState(false)\n const loginPath = process.env.NEXT_PUBLIC_LOGIN_PATH || '/sign-in'\n\n const handleSignOut = async () => {\n setIsLoading(true)\n try {\n // Sign out from Firebase\n await signOut(ternSecureAuth)\n \n await clearSessionCookie()\n \n // Call success callback if provided\n onSignOutSuccess?.()\n\n // Construct login URL with redirect parameter\n const loginUrl = constructUrlWithRedirect(loginPath, pathname)\n\n // Use router for development and window.location for production\n if (process.env.NODE_ENV === \"production\") {\n window.location.href = loginUrl\n } else {\n router.push(loginUrl)\n }\n } catch (error) {\n console.error('Sign out error:', error)\n onError?.(error instanceof Error ? error : new Error('Failed to sign out'))\n } finally {\n setIsLoading(false)\n }\n }\n\n return (\n <Button\n variant={variant}\n size={size}\n onClick={handleSignOut}\n disabled={isLoading}\n className={cn(\"\", className)}\n {...buttonProps}\n >\n {isLoading ? 'Signing out...' : children}\n </Button>\n )\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAoEI;AAlEJ,mBAAyB;AACzB,wBAAuC;AACvC,kBAAwB;AACxB,oBAAyC;AACzC,yBAA+B;AAC/B,+BAAmC;AACnC,mBAAmB;AACnB,uBAAyC;AAelC,SAAS,cAAc;AAAA,EAC5B,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,OAAO;AAAA,EACP,GAAG;AACL,GAAiB;AACf,QAAM,eAAW,+BAAY;AAC7B,QAAM,aAAS,6BAAU;AACzB,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAS,KAAK;AAChD,QAAM,YAAY,QAAQ,IAAI,0BAA0B;AAExD,QAAM,gBAAgB,YAAY;AAChC,iBAAa,IAAI;AACjB,QAAI;AAEF,gBAAM,qBAAQ,iCAAc;AAE5B,gBAAM,6CAAmB;AAGzB;AAGA,YAAM,eAAW,2CAAyB,WAAW,QAAQ;AAG7D,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,eAAO,SAAS,OAAO;AAAA,MACzB,OAAO;AACL,eAAO,KAAK,QAAQ;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,mBAAmB,KAAK;AACtC,yCAAU,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,oBAAoB;AAAA,IAC3E,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,UAAU;AAAA,MACV,eAAW,iBAAG,IAAI,SAAS;AAAA,MAC1B,GAAG;AAAA,MAEH,sBAAY,mBAAmB;AAAA;AAAA,EAClC;AAEJ;","names":[]}
|
|
@@ -40,16 +40,20 @@ var import_client_init = require("../utils/client-init");
|
|
|
40
40
|
var import_sessionTernSecure = require("../app-router/server/sessionTernSecure");
|
|
41
41
|
var import_utils = require("../lib/utils");
|
|
42
42
|
var import_link = __toESM(require("next/link"));
|
|
43
|
+
var import_construct = require("../utils/construct");
|
|
43
44
|
function SignOut({
|
|
44
45
|
children = "Sign out",
|
|
45
46
|
onError,
|
|
46
47
|
onSignOutSuccess,
|
|
47
48
|
className,
|
|
48
49
|
activeClassName,
|
|
49
|
-
disabled = false
|
|
50
|
+
disabled = false,
|
|
51
|
+
redirectPath
|
|
50
52
|
}) {
|
|
51
|
-
const router = (0, import_navigation.useRouter)();
|
|
52
53
|
const [isLoading, setIsLoading] = (0, import_react.useState)(false);
|
|
54
|
+
const pathname = (0, import_navigation.usePathname)();
|
|
55
|
+
const router = (0, import_navigation.useRouter)();
|
|
56
|
+
const loginPath = process.env.NEXT_PUBLIC_LOGIN_PATH || "/sign-in";
|
|
53
57
|
const handleSignOut = async (e) => {
|
|
54
58
|
e.preventDefault();
|
|
55
59
|
if (disabled || isLoading) return;
|
|
@@ -58,7 +62,12 @@ function SignOut({
|
|
|
58
62
|
await (0, import_auth.signOut)(import_client_init.ternSecureAuth);
|
|
59
63
|
await (0, import_sessionTernSecure.clearSessionCookie)();
|
|
60
64
|
onSignOutSuccess == null ? void 0 : onSignOutSuccess();
|
|
61
|
-
|
|
65
|
+
const loginUrl = (0, import_construct.constructUrlWithRedirect)(loginPath, pathname);
|
|
66
|
+
if (process.env.NODE_ENV === "production") {
|
|
67
|
+
window.location.href = loginUrl;
|
|
68
|
+
} else {
|
|
69
|
+
router.push(loginUrl);
|
|
70
|
+
}
|
|
62
71
|
} catch (error) {
|
|
63
72
|
console.error("Sign out error:", error);
|
|
64
73
|
onError == null ? void 0 : onError(error instanceof Error ? error : new Error("Failed to sign out"));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/sign-out.tsx"],"sourcesContent":["'use client'\n\nimport { useState } from 'react'\nimport { useRouter } from 'next/navigation'\nimport { signOut } from 'firebase/auth'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { clearSessionCookie } from '../app-router/server/sessionTernSecure'\nimport { cn } from '../lib/utils'\nimport Link from 'next/link'\n\ninterface SignOutLinkProps {\n children?: React.ReactNode\n onError?: (error: Error) => void\n onSignOutSuccess?: () => void\n className?: string\n activeClassName?: string\n disabled?: boolean\n}\n\nexport function SignOut({\n children = 'Sign out',\n onError,\n onSignOutSuccess,\n className,\n activeClassName,\n disabled = false,\n}: SignOutLinkProps) {\n const
|
|
1
|
+
{"version":3,"sources":["../../../src/components/sign-out.tsx"],"sourcesContent":["'use client'\n\nimport { useState } from 'react'\nimport { usePathname, useRouter } from 'next/navigation'\nimport { signOut } from 'firebase/auth'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { clearSessionCookie } from '../app-router/server/sessionTernSecure'\nimport { cn } from '../lib/utils'\nimport Link from 'next/link'\nimport { constructUrlWithRedirect } from '../utils/construct'\n\n\ninterface SignOutLinkProps {\n children?: React.ReactNode\n onError?: (error: Error) => void\n onSignOutSuccess?: () => void\n className?: string\n activeClassName?: string\n disabled?: boolean\n redirectPath?: string\n}\n\nexport function SignOut({\n children = 'Sign out',\n onError,\n onSignOutSuccess,\n className,\n activeClassName,\n disabled = false,\n redirectPath,\n}: SignOutLinkProps) {\n const [isLoading, setIsLoading] = useState(false)\n const pathname = usePathname()\n const router = useRouter()\n const loginPath = process.env.NEXT_PUBLIC_LOGIN_PATH || \"/sign-in\"\n\n const handleSignOut = async (e: React.MouseEvent<HTMLAnchorElement>) => {\n e.preventDefault()\n if (disabled || isLoading) return\n\n setIsLoading(true)\n try {\n // Sign out from Firebase\n await signOut(ternSecureAuth)\n\n // Clear the session cookie\n await clearSessionCookie()\n\n // Call success callback if provided\n onSignOutSuccess?.()\n\n // Construct login URL with redirect parameter\n const loginUrl = constructUrlWithRedirect(loginPath, pathname)\n\n // Use router for development and window.location for production\n if (process.env.NODE_ENV === \"production\") {\n window.location.href = loginUrl\n } else {\n router.push(loginUrl)\n }\n } catch (error) {\n console.error('Sign out error:', error)\n onError?.(error instanceof Error ? error : new Error('Failed to sign out'))\n } finally {\n setIsLoading(false)\n }\n }\n\n return (\n <Link\n href=\"#\"\n onClick={handleSignOut}\n className={cn(\n 'text-sm font-medium transition-colors hover:text-primary',\n disabled && 'pointer-events-none opacity-50',\n isLoading && 'pointer-events-none',\n className,\n isLoading && activeClassName\n )}\n aria-disabled={disabled || isLoading}\n >\n {isLoading ? 'Signing out...' : children}\n </Link>\n )\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAqEI;AAnEJ,mBAAyB;AACzB,wBAAuC;AACvC,kBAAwB;AACxB,yBAA+B;AAC/B,+BAAmC;AACnC,mBAAmB;AACnB,kBAAiB;AACjB,uBAAyC;AAalC,SAAS,QAAQ;AAAA,EACtB,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AACF,GAAqB;AACnB,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAS,KAAK;AAChD,QAAM,eAAW,+BAAY;AAC7B,QAAM,aAAS,6BAAU;AACzB,QAAM,YAAY,QAAQ,IAAI,0BAA0B;AAExD,QAAM,gBAAgB,OAAO,MAA2C;AACtE,MAAE,eAAe;AACjB,QAAI,YAAY,UAAW;AAE3B,iBAAa,IAAI;AACjB,QAAI;AAEF,gBAAM,qBAAQ,iCAAc;AAG5B,gBAAM,6CAAmB;AAGzB;AAGA,YAAM,eAAW,2CAAyB,WAAW,QAAQ;AAG7D,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,eAAO,SAAS,OAAO;AAAA,MACzB,OAAO;AACL,eAAO,KAAK,QAAQ;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,mBAAmB,KAAK;AACtC,yCAAU,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,oBAAoB;AAAA,IAC3E,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SACE;AAAA,IAAC,YAAAA;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT,eAAW;AAAA,QACT;AAAA,QACA,YAAY;AAAA,QACZ,aAAa;AAAA,QACb;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA,iBAAe,YAAY;AAAA,MAE1B,sBAAY,mBAAmB;AAAA;AAAA,EAClC;AAEJ;","names":["Link"]}
|
|
@@ -48,6 +48,7 @@ var import_separator = require("./ui/separator");
|
|
|
48
48
|
var import_actions = require("../app-router/client/actions");
|
|
49
49
|
var import_useSignUp = require("../boundary/hooks/useSignUp");
|
|
50
50
|
var import_internal_route = require("../app-router/route-handler/internal-route");
|
|
51
|
+
var import_errors = require("../errors");
|
|
51
52
|
function SignUp({
|
|
52
53
|
redirectUrl,
|
|
53
54
|
onError,
|
|
@@ -55,10 +56,10 @@ function SignUp({
|
|
|
55
56
|
}) {
|
|
56
57
|
const pathname = (0, import_navigation.usePathname)();
|
|
57
58
|
const InternalComponent = (0, import_internal_route.handleInternalRoute)(pathname);
|
|
59
|
+
const { setEmail: setContextEmail } = (0, import_useSignUp.useSignUp)();
|
|
58
60
|
if (InternalComponent) {
|
|
59
61
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InternalComponent, {});
|
|
60
62
|
}
|
|
61
|
-
const { setEmail: setContextEmail } = (0, import_useSignUp.useSignUp)();
|
|
62
63
|
const [formData, setFormData] = (0, import_react.useState)({
|
|
63
64
|
email: "",
|
|
64
65
|
password: "",
|
|
@@ -67,7 +68,7 @@ function SignUp({
|
|
|
67
68
|
const [showPassword, setShowPassword] = (0, import_react.useState)(false);
|
|
68
69
|
const [showConfirmPassword, setShowConfirmPassword] = (0, import_react.useState)(false);
|
|
69
70
|
const [isLoading, setLoading] = (0, import_react.useState)(false);
|
|
70
|
-
const [error, setError] = (0, import_react.useState)(
|
|
71
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
71
72
|
const [passwordFocused, setPasswordFocused] = (0, import_react.useState)(false);
|
|
72
73
|
const router = (0, import_navigation.useRouter)();
|
|
73
74
|
const passwordRequirements = [
|
|
@@ -102,6 +103,7 @@ function SignUp({
|
|
|
102
103
|
...prev,
|
|
103
104
|
[name]: value
|
|
104
105
|
}));
|
|
106
|
+
setError(null);
|
|
105
107
|
};
|
|
106
108
|
const isFormValid = () => {
|
|
107
109
|
return formData.email.length > 0 && passwordRequirements.every((req) => req.satisfied);
|
|
@@ -110,15 +112,18 @@ function SignUp({
|
|
|
110
112
|
e.preventDefault();
|
|
111
113
|
if (!isFormValid()) return;
|
|
112
114
|
setLoading(true);
|
|
115
|
+
setError(null);
|
|
113
116
|
try {
|
|
114
117
|
const result = await (0, import_actions.createUser)(formData.email, formData.password);
|
|
115
118
|
if (result.success) {
|
|
116
119
|
setContextEmail(formData.email);
|
|
117
120
|
onSuccess == null ? void 0 : onSuccess();
|
|
118
121
|
router.push(`sign-up/verify`);
|
|
122
|
+
} else {
|
|
123
|
+
setError(result);
|
|
119
124
|
}
|
|
120
125
|
} catch (error2) {
|
|
121
|
-
const errorMessage = error2
|
|
126
|
+
const errorMessage = error2;
|
|
122
127
|
setError(errorMessage);
|
|
123
128
|
onError == null ? void 0 : onError(error2 instanceof Error ? error2 : new Error("Failed to create account"));
|
|
124
129
|
} finally {
|
|
@@ -136,7 +141,7 @@ function SignUp({
|
|
|
136
141
|
throw new Error(result.error);
|
|
137
142
|
}
|
|
138
143
|
} catch (err) {
|
|
139
|
-
const errorMessage = err
|
|
144
|
+
const errorMessage = err;
|
|
140
145
|
setError(errorMessage);
|
|
141
146
|
const newUrl = new URL(window.location.href);
|
|
142
147
|
newUrl.searchParams.delete("signInRedirect");
|
|
@@ -152,7 +157,7 @@ function SignUp({
|
|
|
152
157
|
] }),
|
|
153
158
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: handleSubmit, children: [
|
|
154
159
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_card.CardContent, { className: "space-y-4", children: [
|
|
155
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_alert.Alert, { variant: "
|
|
160
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_alert.Alert, { variant: (0, import_errors.getErrorAlertVariant)(error), className: "animate-in fade-in-50", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_alert.AlertDescription, { children: error.message }) }),
|
|
156
161
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2", children: [
|
|
157
162
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.Label, { htmlFor: "email", children: "Email" }),
|
|
158
163
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/sign-up.tsx"],"sourcesContent":["\"use client\"\n\nimport { useState } from \"react\"\nimport { useRouter, usePathname } from 'next/navigation'\nimport Link from \"next/link\"\nimport { Eye, EyeOff, Check, X, Loader2 } from \"lucide-react\"\nimport { Button } from \"./ui/button\"\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from \"./ui/card\"\nimport { Input } from \"./ui/input\"\nimport { Label } from \"./ui/label\"\nimport { Alert, AlertDescription } from \"./ui/alert\"\nimport { cn } from \"../lib/utils\"\nimport { AuthBackground } from \"./background\"\nimport { Separator } from \"./ui/separator\"\nimport { createUser, signInWithRedirectGoogle, signInWithMicrosoft } from '../app-router/client/actions'\nimport { useSignUp } from '../boundary/hooks/useSignUp'\nimport { handleInternalRoute } from '../app-router/route-handler/internal-route'\n\nexport interface SignUpProps {\n redirectUrl?: string\n onError?: (error: Error) => void\n onSuccess?: () => void\n}\n\nexport interface PasswordRequirement {\n text: string\n satisfied: boolean\n}\n\nexport function SignUp({\n redirectUrl, \n onError,\n onSuccess,\n }: SignUpProps) {\n const pathname = usePathname()\n const InternalComponent = handleInternalRoute(pathname)\n\n if (InternalComponent) {\n return <InternalComponent />\n }\n\n const { setEmail: setContextEmail } = useSignUp()\n const [formData, setFormData] = useState({\n email: \"\",\n password: \"\",\n confirmPassword: \"\",\n })\n const [showPassword, setShowPassword] = useState(false)\n const [showConfirmPassword, setShowConfirmPassword] = useState(false)\n const [isLoading, setLoading] = useState(false)\n const [error, setError] = useState(\"\")\n const [passwordFocused, setPasswordFocused] = useState(false)\n const router = useRouter()\n\n const passwordRequirements: PasswordRequirement[] = [\n {\n text: \"At least 8 characters long\",\n satisfied: formData.password.length >= 8,\n },\n {\n text: \"Contains at least one uppercase letter\",\n satisfied: /[A-Z]/.test(formData.password),\n },\n {\n text: \"Contains at least one lowercase letter\",\n satisfied: /[a-z]/.test(formData.password),\n },\n {\n text: \"Contains at least one number\",\n satisfied: /\\d/.test(formData.password),\n },\n {\n text: \"Contains at least one special character\",\n satisfied: /[!@#$%^&*(),.?\":{}|<>]/.test(formData.password),\n },\n {\n text: \"Passwords match\",\n satisfied: formData.password === formData.confirmPassword && formData.password !== \"\",\n },\n ]\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value } = e.target\n setFormData((prev) => ({\n ...prev,\n [name]: value,\n }))\n }\n\n const isFormValid = () => {\n return formData.email.length > 0 && passwordRequirements.every((req) => req.satisfied)\n }\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n if (!isFormValid()) return\n\n setLoading(true)\n try {\n const result = await createUser(formData.email, formData.password)\n if(result.success) {\n setContextEmail(formData.email)\n\n onSuccess?.()\n\n router.push(`sign-up/verify`)\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Failed to sign in'\n setError(errorMessage)\n onError?.(error instanceof Error ? error : new Error('Failed to create account'))\n } finally {\n setLoading(false)\n }\n }\n\n\n const handleSocialSignIn = async (provider: 'google' | 'microsoft') => {\n setLoading(true)\n try {\n const currentUrl = new URL(window.location.href)\n currentUrl.searchParams.set('signInRedirect', 'true')\n window.history.replaceState({}, '', currentUrl.toString())\n\n const result = provider === 'google' ? await signInWithRedirectGoogle() : await signInWithMicrosoft()\n if (!result.success) {\n throw new Error(result.error)\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : `Failed to sign in with ${provider}`\n setError(errorMessage)\n const newUrl = new URL(window.location.href)\n newUrl.searchParams.delete('signInRedirect')\n window.history.replaceState({}, '', newUrl.toString())\n }\n }\n\n return (\n <div className=\"relative flex min-h-screen items-center justify-center\">\n <AuthBackground />\n <Card className=\"w-full max-w-md mx-auto mt-8\">\n <CardHeader className=\"space-y-1 text-center\">\n <CardTitle className=\"text-2xl font-bold\">Create an account</CardTitle>\n <CardDescription>Enter your information below to create your account</CardDescription>\n </CardHeader>\n <form onSubmit={handleSubmit}>\n <CardContent className=\"space-y-4\">\n {error && (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\">Email</Label>\n <Input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n placeholder=\"name@example.com\"\n value={formData.email}\n onChange={handleInputChange}\n required\n disabled={isLoading}\n />\n </div>\n\n <div className=\"space-y-2 relative flex-1\">\n <Label htmlFor=\"password\">Password</Label>\n <div className=\"relative\">\n <Input\n id=\"password\"\n name=\"password\"\n type={showPassword ? \"text\" : \"password\"}\n value={formData.password}\n onChange={handleInputChange}\n onFocus={() => setPasswordFocused(true)}\n onBlur={() => setPasswordFocused(false)}\n required\n disabled={isLoading}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-2 top-1/2 -translate-y-1/2 h-8 w-8 hover:bg-transparent\"\n onClick={() => setShowPassword(!showPassword)}\n >\n {showPassword ? <EyeOff className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" /> : <Eye className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />}\n <span className=\"sr-only\">{showPassword ? \"Hide password\" : \"Show password\"}</span>\n </Button>\n </div>\n </div>\n\n <div className=\"space-y-2 relative flex-1\">\n <Label htmlFor=\"confirmPassword\">Confirm Password</Label>\n <div className=\"relative\">\n <Input\n id=\"confirmPassword\"\n name=\"confirmPassword\"\n type={showConfirmPassword ? \"text\" : \"password\"}\n value={formData.confirmPassword}\n onChange={handleInputChange}\n required\n disabled={isLoading}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-2 top-1/2 -translate-y-1/2 h-8 w-8 hover:bg-transparent\"\n onClick={() => setShowConfirmPassword(!showConfirmPassword)}\n >\n {showConfirmPassword ? <EyeOff className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" /> : <Eye className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />}\n <span className=\"sr-only\">{showConfirmPassword ? \"Hide password\" : \"Show password\"}</span>\n </Button>\n </div>\n </div>\n\n {/* Password Requirements */}\n <div\n className={cn(\n \"rounded-lg border bg-card text-card-foreground shadow-sm\",\n \"p-4 transition-all duration-200\",\n passwordFocused ? \"opacity-100\" : \"opacity-70\",\n )}\n >\n <div className=\"grid gap-2 text-sm\">\n {passwordRequirements.map((requirement, index) => (\n <div\n key={index}\n className={cn(\n \"flex items-center gap-2\",\n requirement.satisfied ? \"text-green-500\" : \"text-muted-foreground\",\n )}\n >\n {requirement.satisfied ? (\n <Check className=\"h-4 w-4 shrink-0\" />\n ) : (\n <X className=\"h-4 w-4 shrink-0\" />\n )}\n <span className=\"text-sm\">{requirement.text}</span>\n </div>\n ))}\n </div>\n </div>\n </CardContent>\n\n <CardFooter className=\"flex flex-col space-y-4\">\n <Button type=\"submit\" className=\"w-full\" disabled={!isFormValid() || isLoading}>\n {isLoading ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n Creating account...\n </>\n ) : (\n \"Create account\"\n )}\n </Button>\n <p className=\"text-sm text-muted-foreground text-center\">\n Already have an account?{\" \"}\n <Link href=\"/sign-in\" className=\"text-primary underline-offset-4 transition-colors hover:underline\">\n Sign in\n </Link> or sign up with email\n </p>\n </CardFooter>\n </form>\n <Separator className=\"my-4 px-6\" />\n <div className=\"px-6 pb-4\">\n <div className=\"relative\">\n <div className=\"absolute inset-0 flex items-center\">\n <Separator className=\"w-full\" />\n </div>\n <div className=\"relative flex justify-center text-xs uppercase\">\n <span className=\"bg-background px-2 text-muted-foreground\">\n Or continue with\n </span>\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4 mt-4\">\n <Button \n variant=\"outline\" \n disabled={isLoading}\n onClick={() => handleSocialSignIn('google')} \n className=\"flex items-center justify-center\"\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\" fill=\"#4285F4\"/>\n <path d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" fill=\"#34A853\"/>\n <path d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" fill=\"#FBBC05\"/>\n <path d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" fill=\"#EA4335\"/>\n </svg>\n Google\n </Button>\n <Button \n variant=\"outline\" \n disabled={isLoading}\n onClick={() => handleSocialSignIn('microsoft')} \n className=\"flex items-center justify-center\"\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 23 23\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill=\"#f3f3f3\" d=\"M0 0h23v23H0z\"/>\n <path fill=\"#f35325\" d=\"M1 1h10v10H1z\"/>\n <path fill=\"#81bc06\" d=\"M12 1h10v10H12z\"/>\n <path fill=\"#05a6f0\" d=\"M1 12h10v10H1z\"/>\n <path fill=\"#ffba08\" d=\"M12 12h10v10H12z\"/>\n </svg>\n Microsoft\n </Button>\n </div>\n </div>\n </Card>\n </div>\n )\n}\n"],"mappings":"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","names":["error","Link"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/sign-up.tsx"],"sourcesContent":["\"use client\"\n\nimport { useState } from \"react\"\nimport { useRouter, usePathname } from 'next/navigation'\nimport Link from \"next/link\"\nimport { Eye, EyeOff, Check, X, Loader2 } from \"lucide-react\"\nimport { Button } from \"./ui/button\"\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from \"./ui/card\"\nimport { Input } from \"./ui/input\"\nimport { Label } from \"./ui/label\"\nimport { Alert, AlertDescription } from \"./ui/alert\"\nimport { cn } from \"../lib/utils\"\nimport { AuthBackground } from \"./background\"\nimport { Separator } from \"./ui/separator\"\nimport { createUser, signInWithRedirectGoogle, signInWithMicrosoft } from '../app-router/client/actions'\nimport { useSignUp } from '../boundary/hooks/useSignUp'\nimport { handleInternalRoute } from '../app-router/route-handler/internal-route'\nimport { SignInResponse } from \"../types\"\nimport { getErrorAlertVariant, ErrorCode} from \"../errors\"\n\nexport interface SignUpProps {\n redirectUrl?: string\n onError?: (error: Error) => void\n onSuccess?: () => void\n}\n\nexport interface PasswordRequirement {\n text: string\n satisfied: boolean\n}\n\n\nexport function SignUp({\n redirectUrl, \n onError,\n onSuccess,\n }: SignUpProps) {\n const pathname = usePathname()\n const InternalComponent = handleInternalRoute(pathname)\n const { setEmail: setContextEmail } = useSignUp()\n\n if (InternalComponent) {\n return <InternalComponent />\n }\n\n \n const [formData, setFormData] = useState({\n email: \"\",\n password: \"\",\n confirmPassword: \"\",\n })\n const [showPassword, setShowPassword] = useState(false)\n const [showConfirmPassword, setShowConfirmPassword] = useState(false)\n const [isLoading, setLoading] = useState(false)\n const [error, setError] = useState<SignInResponse | null>(null)\n const [passwordFocused, setPasswordFocused] = useState(false)\n const router = useRouter()\n\n const passwordRequirements: PasswordRequirement[] = [\n {\n text: \"At least 8 characters long\",\n satisfied: formData.password.length >= 8,\n },\n {\n text: \"Contains at least one uppercase letter\",\n satisfied: /[A-Z]/.test(formData.password),\n },\n {\n text: \"Contains at least one lowercase letter\",\n satisfied: /[a-z]/.test(formData.password),\n },\n {\n text: \"Contains at least one number\",\n satisfied: /\\d/.test(formData.password),\n },\n {\n text: \"Contains at least one special character\",\n satisfied: /[!@#$%^&*(),.?\":{}|<>]/.test(formData.password),\n },\n {\n text: \"Passwords match\",\n satisfied: formData.password === formData.confirmPassword && formData.password !== \"\",\n },\n ]\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const { name, value } = e.target\n setFormData((prev) => ({\n ...prev,\n [name]: value,\n }))\n setError(null)\n }\n\n const isFormValid = () => {\n return formData.email.length > 0 && passwordRequirements.every((req) => req.satisfied)\n }\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n if (!isFormValid()) return\n\n setLoading(true)\n setError(null)\n try {\n const result = await createUser(formData.email, formData.password)\n if(result.success) {\n setContextEmail(formData.email)\n\n onSuccess?.()\n\n router.push(`sign-up/verify`)\n } else {\n setError(result)\n }\n } catch (error) {\n const errorMessage = error as SignInResponse\n setError(errorMessage)\n onError?.(error instanceof Error ? error : new Error('Failed to create account'))\n } finally {\n setLoading(false)\n }\n }\n\n\n const handleSocialSignIn = async (provider: 'google' | 'microsoft') => {\n setLoading(true)\n try {\n const currentUrl = new URL(window.location.href)\n currentUrl.searchParams.set('signInRedirect', 'true')\n window.history.replaceState({}, '', currentUrl.toString())\n\n const result = provider === 'google' ? await signInWithRedirectGoogle() : await signInWithMicrosoft()\n if (!result.success) {\n throw new Error(result.error)\n }\n } catch (err) {\n const errorMessage = err as SignInResponse\n setError(errorMessage)\n const newUrl = new URL(window.location.href)\n newUrl.searchParams.delete('signInRedirect')\n window.history.replaceState({}, '', newUrl.toString())\n }\n }\n\n return (\n <div className=\"relative flex min-h-screen items-center justify-center\">\n <AuthBackground />\n <Card className=\"w-full max-w-md mx-auto mt-8\">\n <CardHeader className=\"space-y-1 text-center\">\n <CardTitle className=\"text-2xl font-bold\">Create an account</CardTitle>\n <CardDescription>Enter your information below to create your account</CardDescription>\n </CardHeader>\n <form onSubmit={handleSubmit}>\n <CardContent className=\"space-y-4\">\n {error && (\n <Alert variant={getErrorAlertVariant(error)} className=\"animate-in fade-in-50\">\n <AlertDescription>{error.message}</AlertDescription>\n </Alert>\n )}\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\">Email</Label>\n <Input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n placeholder=\"name@example.com\"\n value={formData.email}\n onChange={handleInputChange}\n required\n disabled={isLoading}\n />\n </div>\n\n <div className=\"space-y-2 relative flex-1\">\n <Label htmlFor=\"password\">Password</Label>\n <div className=\"relative\">\n <Input\n id=\"password\"\n name=\"password\"\n type={showPassword ? \"text\" : \"password\"}\n value={formData.password}\n onChange={handleInputChange}\n onFocus={() => setPasswordFocused(true)}\n onBlur={() => setPasswordFocused(false)}\n required\n disabled={isLoading}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-2 top-1/2 -translate-y-1/2 h-8 w-8 hover:bg-transparent\"\n onClick={() => setShowPassword(!showPassword)}\n >\n {showPassword ? <EyeOff className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" /> : <Eye className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />}\n <span className=\"sr-only\">{showPassword ? \"Hide password\" : \"Show password\"}</span>\n </Button>\n </div>\n </div>\n\n <div className=\"space-y-2 relative flex-1\">\n <Label htmlFor=\"confirmPassword\">Confirm Password</Label>\n <div className=\"relative\">\n <Input\n id=\"confirmPassword\"\n name=\"confirmPassword\"\n type={showConfirmPassword ? \"text\" : \"password\"}\n value={formData.confirmPassword}\n onChange={handleInputChange}\n required\n disabled={isLoading}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-2 top-1/2 -translate-y-1/2 h-8 w-8 hover:bg-transparent\"\n onClick={() => setShowConfirmPassword(!showConfirmPassword)}\n >\n {showConfirmPassword ? <EyeOff className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" /> : <Eye className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />}\n <span className=\"sr-only\">{showConfirmPassword ? \"Hide password\" : \"Show password\"}</span>\n </Button>\n </div>\n </div>\n\n {/* Password Requirements */}\n <div\n className={cn(\n \"rounded-lg border bg-card text-card-foreground shadow-sm\",\n \"p-4 transition-all duration-200\",\n passwordFocused ? \"opacity-100\" : \"opacity-70\",\n )}\n >\n <div className=\"grid gap-2 text-sm\">\n {passwordRequirements.map((requirement, index) => (\n <div\n key={index}\n className={cn(\n \"flex items-center gap-2\",\n requirement.satisfied ? \"text-green-500\" : \"text-muted-foreground\",\n )}\n >\n {requirement.satisfied ? (\n <Check className=\"h-4 w-4 shrink-0\" />\n ) : (\n <X className=\"h-4 w-4 shrink-0\" />\n )}\n <span className=\"text-sm\">{requirement.text}</span>\n </div>\n ))}\n </div>\n </div>\n </CardContent>\n\n <CardFooter className=\"flex flex-col space-y-4\">\n <Button type=\"submit\" className=\"w-full\" disabled={!isFormValid() || isLoading}>\n {isLoading ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n Creating account...\n </>\n ) : (\n \"Create account\"\n )}\n </Button>\n <p className=\"text-sm text-muted-foreground text-center\">\n Already have an account?{\" \"}\n <Link href=\"/sign-in\" className=\"text-primary underline-offset-4 transition-colors hover:underline\">\n Sign in\n </Link> or sign up with email\n </p>\n </CardFooter>\n </form>\n <Separator className=\"my-4 px-6\" />\n <div className=\"px-6 pb-4\">\n <div className=\"relative\">\n <div className=\"absolute inset-0 flex items-center\">\n <Separator className=\"w-full\" />\n </div>\n <div className=\"relative flex justify-center text-xs uppercase\">\n <span className=\"bg-background px-2 text-muted-foreground\">\n Or continue with\n </span>\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4 mt-4\">\n <Button \n variant=\"outline\" \n disabled={isLoading}\n onClick={() => handleSocialSignIn('google')} \n className=\"flex items-center justify-center\"\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\" fill=\"#4285F4\"/>\n <path d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" fill=\"#34A853\"/>\n <path d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" fill=\"#FBBC05\"/>\n <path d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" fill=\"#EA4335\"/>\n </svg>\n Google\n </Button>\n <Button \n variant=\"outline\" \n disabled={isLoading}\n onClick={() => handleSocialSignIn('microsoft')} \n className=\"flex items-center justify-center\"\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 23 23\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill=\"#f3f3f3\" d=\"M0 0h23v23H0z\"/>\n <path fill=\"#f35325\" d=\"M1 1h10v10H1z\"/>\n <path fill=\"#81bc06\" d=\"M12 1h10v10H12z\"/>\n <path fill=\"#05a6f0\" d=\"M1 12h10v10H1z\"/>\n <path fill=\"#ffba08\" d=\"M12 12h10v10H12z\"/>\n </svg>\n Microsoft\n </Button>\n </div>\n </div>\n </Card>\n </div>\n )\n}\n"],"mappings":"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","names":["error","Link"]}
|