import React, { useState, useMemo, FormEvent } from 'react'; import { Card, Stack, Text, Button, Input, Divider, Alert, Icon, Spinner } from '..'; import { useTheme } from '../../core'; import { GoogleIcon, GithubIcon } from '../../icons'; export interface AuthProvider { id: string; name: string; type: 'oauth' | 'credentials' | 'magiclink' | 'passkey'; } export interface AuthResponse { error?: string; success?: string; } interface SignInPageProps { providers: AuthProvider[]; signIn: (providerId: string, formData?: Record) => Promise; title?: string; subtitle?: string; className?: string; } const providerIcons: Record = { google: GoogleIcon, github: GithubIcon, }; export const SignInPage: React.FC = ({ providers, signIn, title = 'Sign In', subtitle, className, }) => { const { theme } = useTheme(); const [alert, setAlert] = useState<{ type: 'error' | 'success'; message: string } | null>(null); const [loadingProvider, setLoadingProvider] = useState(null); const [formData, setFormData] = useState>({}); const oauthProviders = useMemo(() => providers.filter(p => p.type === 'oauth'), [providers]); const credentialsProvider = useMemo(() => providers.find(p => p.type === 'credentials'), [providers]); const magicLinkProvider = useMemo(() => providers.find(p => p.type === 'magiclink'), [providers]); const handleOAuthSignIn = async (providerId: string) => { setLoadingProvider(providerId); setAlert(null); try { const response = await signIn(providerId); if (response && response.error) { setAlert({ type: 'error', message: response.error }); } } catch (e: any) { setAlert({ type: 'error', message: e.message || 'An unknown error occurred.' }); } finally { setLoadingProvider(null); } }; const handleFormSubmit = async (e: FormEvent, providerId: string) => { e.preventDefault(); setLoadingProvider(providerId); setAlert(null); try { const response = await signIn(providerId, formData); if (response) { if (response.error) { setAlert({ type: 'error', message: response.error }); } else if (response.success) { setAlert({ type: 'success', message: response.success }); } } } catch (e: any) { setAlert({ type: 'error', message: e.message || 'An unknown error occurred.' }); } finally { setLoadingProvider(null); } }; const handleInputChange = (e: React.ChangeEvent) => { setFormData(prev => ({ ...prev, [e.target.name]: e.target.value })); }; return ( {title} {subtitle && {subtitle}} {alert && ( {alert.message} )} {oauthProviders.length > 0 && ( {oauthProviders.map(provider => { const ProviderIcon = providerIcons[provider.id]; return ( ); })} )} {(oauthProviders.length > 0 && (credentialsProvider || magicLinkProvider)) && ( OR )} {credentialsProvider && (
handleFormSubmit(e, credentialsProvider.id)}>
)} {magicLinkProvider && (
handleFormSubmit(e, magicLinkProvider.id)}>
)}
); };