| import { useState } from 'react' |
| import { Globe, Loader2 } from 'lucide-react' |
| import Modal from './Modal' |
| import Button from './Button' |
|
|
| export default function AuthDialog({ |
| open, |
| mode, |
| onModeChange, |
| onClose, |
| onLogin, |
| onRegister, |
| onGoogleLogin, |
| pending, |
| }) { |
| const [username, setUsername] = useState('') |
| const [password, setPassword] = useState('') |
| const [error, setError] = useState('') |
|
|
| const submit = async (event) => { |
| event.preventDefault() |
| setError('') |
|
|
| if (!username || !password) { |
| setError('Please fill in both fields.') |
| return |
| } |
|
|
| try { |
| if (mode === 'register') { |
| await onRegister({ username, password }) |
| } else { |
| await onLogin({ username, password }) |
| } |
| } catch (authError) { |
| setError(authError.message || 'Authentication failed.') |
| } |
| } |
|
|
| return ( |
| <Modal |
| open={open} |
| onOpenChange={(next) => { |
| if (!next) onClose() |
| }} |
| size="sm" |
| title={mode === 'register' ? 'Create your OwnGPT account' : 'Sign in to OwnGPT'} |
| description="Sync your sessions, upload files, and unlock the full workspace." |
| > |
| <div className="space-y-5"> |
| <div className="grid grid-cols-2 gap-2 rounded-2xl bg-panel p-1"> |
| <button |
| type="button" |
| onClick={() => onModeChange('login')} |
| className={`rounded-2xl px-4 py-2 text-sm font-medium transition ${ |
| mode === 'login' |
| ? 'bg-background text-foreground shadow-soft' |
| : 'text-muted-foreground hover:text-foreground' |
| }`} |
| > |
| Sign in |
| </button> |
| <button |
| type="button" |
| onClick={() => onModeChange('register')} |
| className={`rounded-2xl px-4 py-2 text-sm font-medium transition ${ |
| mode === 'register' |
| ? 'bg-background text-foreground shadow-soft' |
| : 'text-muted-foreground hover:text-foreground' |
| }`} |
| > |
| Register |
| </button> |
| </div> |
| |
| <form className="space-y-4" onSubmit={submit}> |
| <label className="block space-y-2"> |
| <span className="text-sm font-medium text-foreground">Username</span> |
| <input |
| className="w-full rounded-2xl border border-input bg-panel px-4 py-3 text-sm text-foreground outline-none transition placeholder:text-muted-foreground focus:border-accent/50 focus:ring-2 focus:ring-ring/20" |
| value={username} |
| onChange={(event) => setUsername(event.target.value)} |
| placeholder={mode === 'register' ? 'letters, numbers, underscores' : 'your username'} |
| autoFocus |
| /> |
| </label> |
| <label className="block space-y-2"> |
| <span className="text-sm font-medium text-foreground">Password</span> |
| <input |
| type="password" |
| className="w-full rounded-2xl border border-input bg-panel px-4 py-3 text-sm text-foreground outline-none transition placeholder:text-muted-foreground focus:border-accent/50 focus:ring-2 focus:ring-ring/20" |
| value={password} |
| onChange={(event) => setPassword(event.target.value)} |
| placeholder="••••••••" |
| /> |
| </label> |
| {error ? <p className="text-sm text-danger">{error}</p> : null} |
| <Button type="submit" variant="primary" className="w-full" loading={pending}> |
| {pending ? <Loader2 className="h-4 w-4 animate-spin" /> : null} |
| {mode === 'register' ? 'Create account' : 'Sign in'} |
| </Button> |
| </form> |
| |
| <div className="relative"> |
| <div className="absolute inset-0 flex items-center"> |
| <div className="h-px w-full bg-border/80" /> |
| </div> |
| <div className="relative flex justify-center"> |
| <span className="bg-card px-3 text-xs uppercase tracking-[0.16em] text-muted-foreground"> |
| Or continue with |
| </span> |
| </div> |
| </div> |
| |
| <Button variant="secondary" className="w-full" onClick={onGoogleLogin}> |
| <Globe className="h-4 w-4" /> |
| Google |
| </Button> |
| </div> |
| </Modal> |
| ) |
| } |
|
|