diff --git a/app/routes.ts b/app/routes.ts index 33e9827..3c0ba46 100644 --- a/app/routes.ts +++ b/app/routes.ts @@ -4,4 +4,5 @@ export default [ index('routes/_index.tsx'), route('signup', 'routes/signup.tsx'), route('verify', 'routes/verify.tsx'), + route('login', 'routes/login.tsx'), ] satisfies RouteConfig; diff --git a/app/routes/login.tsx b/app/routes/login.tsx new file mode 100644 index 0000000..e9df225 --- /dev/null +++ b/app/routes/login.tsx @@ -0,0 +1,104 @@ +import { useState } from 'react'; + +const API_URL = import.meta.env.VITE_API_URL ?? 'https://api.t4t-gateway.com'; + +export function meta() { + return [{ title: 'Log in · t4t Gateway' }]; +} + +export default function Login() { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [submitting, setSubmitting] = useState(false); + const [error, setError] = useState(null); + + async function onSubmit(e: React.FormEvent) { + e.preventDefault(); + setError(null); + setSubmitting(true); + try { + const res = await fetch(`${API_URL}/auth/email/login`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, password }), + }); + const body = await res.json(); + if (!res.ok) { + throw new Error(body?.message ?? body?.error ?? `Login failed (${res.status})`); + } + localStorage.setItem('jwt', body.token); + window.location.href = '/account'; + } catch (err) { + setError(err instanceof Error ? err.message : 'Unknown error'); + } finally { + setSubmitting(false); + } + } + + return ( +
+
+

Log in

+

+ Welcome back. +

+ +
+
+ + setEmail(e.target.value)} + className='mt-1 block w-full rounded-md border border-neutral-300 px-3 py-2 text-sm shadow-sm focus:border-neutral-900 focus:outline-none focus:ring-1 focus:ring-neutral-900' + /> +
+ +
+ + setPassword(e.target.value)} + className='mt-1 block w-full rounded-md border border-neutral-300 px-3 py-2 text-sm shadow-sm focus:border-neutral-900 focus:outline-none focus:ring-1 focus:ring-neutral-900' + /> +
+
+ + {error && ( +

+ {error} +

+ )} + + + +

+ No account?{' '} + + Sign up + +

+
+
+ ); +}