urmi-ai/frontend/src/features/auth/AuthPage.tsx
2026-10-12 23:19:09 +05:30

92 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ArrowLeft, ArrowRight, Check, Eye, EyeOff, LockKeyhole, Mail, User } from 'lucide-react'
import { useState } from 'react'
import type { FormEvent } from 'react'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import { authApi } from '../../lib/api'
import { useAuth } from './auth-context'
export function AuthPage({ initialMode }: { initialMode: 'login' | 'register' }) {
const [mode, setMode] = useState(initialMode)
const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [showPassword, setShowPassword] = useState(false)
const [error, setError] = useState('')
const [submitting, setSubmitting] = useState(false)
const { setUser } = useAuth()
const navigate = useNavigate()
const location = useLocation()
async function submit(event: FormEvent) {
event.preventDefault()
setError('')
setSubmitting(true)
try {
const user = mode === 'login'
? await authApi.login(email, password)
: await authApi.register(name, email, password)
setUser(user)
const destination = (location.state as { from?: string } | null)?.from ?? '/console'
navigate(destination, { replace: true })
} catch (reason) {
setError(reason instanceof Error ? reason.message : 'Unable to continue')
} finally {
setSubmitting(false)
}
}
function switchMode(nextMode: 'login' | 'register') {
setMode(nextMode)
setError('')
navigate(nextMode === 'login' ? '/login' : '/register', { replace: true })
}
return (
<div className="auth-page">
<div className="auth-visual">
<Link to="/" className="auth-brand"><img src="/urmi-logo.png" alt="Urmi" /></Link>
<div className="auth-message">
<span>CUSTOMER MESSAGING</span>
<h1>Messages your customers actually receive.</h1>
<p>Text, WhatsApp, verification codes, and calls in one workspace, with the approvals Indian businesses need.</p>
<div><span><Check size={15} /> SMS, WhatsApp, and phone</span><span><Check size={15} /> KYC and DLT in setup</span><span><Check size={15} /> Delivery you can check</span></div>
</div>
<small>Set up · Approve · Send · Review</small>
</div>
<main className="auth-main">
<Link to="/" className="back-home"><ArrowLeft size={15} /> Back to Urmi</Link>
<section className="auth-card">
<div className="auth-tabs">
<button className={mode === 'login' ? 'active' : ''} onClick={() => switchMode('login')}>Log in</button>
<button className={mode === 'register' ? 'active' : ''} onClick={() => switchMode('register')}>Create account</button>
</div>
<div className="auth-heading">
<h2>{mode === 'login' ? 'Welcome back' : 'Create your workspace'}</h2>
<p>{mode === 'login' ? 'Sign in to messages, calls, and your account.' : 'Set up Urmi and send your first message.'}</p>
</div>
<a className="google-button" href={authApi.googleUrl}>
<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#4285F4" d="M21.6 12.23c0-.71-.06-1.39-.18-2.05H12v3.87h5.38a4.6 4.6 0 0 1-2 3.02v2.51h3.24c1.9-1.75 2.98-4.33 2.98-7.35Z"/><path fill="#34A853" d="M12 22c2.7 0 4.98-.9 6.63-2.42l-3.24-2.51c-.9.6-2.05.96-3.39.96-2.61 0-4.82-1.76-5.61-4.13H3.04v2.59A10 10 0 0 0 12 22Z"/><path fill="#FBBC05" d="M6.39 13.9A6.01 6.01 0 0 1 6.08 12c0-.66.11-1.3.31-1.9V7.51H3.04A10 10 0 0 0 2 12c0 1.61.38 3.14 1.04 4.49l3.35-2.59Z"/><path fill="#EA4335" d="M12 5.97c1.47 0 2.79.51 3.83 1.5l2.87-2.88A9.64 9.64 0 0 0 12 2a10 10 0 0 0-8.96 5.51l3.35 2.59C7.18 7.73 9.39 5.97 12 5.97Z"/></svg>
Continue with Google
</a>
<div className="auth-divider"><span>or continue with email</span></div>
<form onSubmit={submit}>
{mode === 'register' && <label><span>Name</span><div><User size={17} /><input required minLength={2} autoComplete="name" value={name} onChange={(e) => setName(e.target.value)} placeholder="Your name" /></div></label>}
<label><span>Email address</span><div><Mail size={17} /><input required type="email" autoComplete="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="you@company.com" /></div></label>
<label><span>Password</span><div><LockKeyhole size={17} /><input required minLength={mode === 'register' ? 10 : 1} type={showPassword ? 'text' : 'password'} autoComplete={mode === 'login' ? 'current-password' : 'new-password'} value={password} onChange={(e) => setPassword(e.target.value)} placeholder={mode === 'register' ? 'At least 10 characters' : 'Your password'} /><button type="button" aria-label="Toggle password visibility" onClick={() => setShowPassword(!showPassword)}>{showPassword ? <EyeOff size={17} /> : <Eye size={17} />}</button></div></label>
{mode === 'login' && <div className="forgot-row"><span>Secure, encrypted sign in</span><button type="button">Forgot password?</button></div>}
{error && <p className="auth-error">{error}</p>}
<button className="auth-submit" disabled={submitting}>{submitting ? 'Please wait…' : mode === 'login' ? 'Log in to Urmi' : 'Create my account'} {!submitting && <ArrowRight size={17} />}</button>
</form>
<p className="auth-terms">
By continuing, you agree to Urmi’s Terms of Service and{' '}
<Link to="/privacy">Privacy Policy</Link>.
</p>
</section>
</main>
</div>
)
}