Implemented complete authentication UI with full user flows: **Authentication Pages:** - Login page with email/password validation - Signup page with display name and terms acceptance - Password reset request page - Password reset confirmation page - All pages use AuthLayout for consistent design **Features Implemented:** - Form validation with real-time error feedback - Password strength requirements (8+ chars, uppercase, lowercase, number) - "Remember me" functionality on login - Terms of Service and Privacy Policy acceptance - Success/error state handling - Loading states during API calls - Accessible form controls with proper ARIA labels **User Experience:** - Clear error messages and field validation - Success screens with visual feedback - Proper navigation between auth flows - Link back to login from all pages - Auto-redirect to dashboard on successful auth All forms follow WCAG 2.2 AA+ guidelines with proper labels, error announcements, and keyboard navigation. Job ID: MTAD-IMPL-2025-11-18-CL
144 lines
3.8 KiB
TypeScript
144 lines
3.8 KiB
TypeScript
'use client'
|
|
|
|
import React, { useState } from 'react'
|
|
import { AuthLayout } from '@/components/layouts/AuthLayout'
|
|
import { Input } from '@/components/common/Input'
|
|
import { Button } from '@/components/common/Button'
|
|
import { Link } from '@/components/common/Link'
|
|
import { useApi } from '@/lib/hooks/useApi'
|
|
|
|
export default function ResetPasswordPage() {
|
|
const { execute, isLoading, error } = useApi()
|
|
const [email, setEmail] = useState('')
|
|
const [emailError, setEmailError] = useState('')
|
|
const [success, setSuccess] = useState(false)
|
|
|
|
const validateEmail = () => {
|
|
if (!email) {
|
|
setEmailError('Email is required')
|
|
return false
|
|
} else if (!/\S+@\S+\.\S+/.test(email)) {
|
|
setEmailError('Email is invalid')
|
|
return false
|
|
}
|
|
setEmailError('')
|
|
return true
|
|
}
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault()
|
|
|
|
if (!validateEmail()) {
|
|
return
|
|
}
|
|
|
|
const data = await execute({
|
|
method: 'POST',
|
|
url: '/auth/reset-password/request',
|
|
data: { email },
|
|
})
|
|
|
|
if (data) {
|
|
setSuccess(true)
|
|
}
|
|
}
|
|
|
|
if (success) {
|
|
return (
|
|
<AuthLayout
|
|
title="Check your email"
|
|
subtitle="We've sent you a password reset link"
|
|
>
|
|
<div className="text-center space-y-4">
|
|
<div className="w-16 h-16 bg-success-100 rounded-full flex items-center justify-center mx-auto">
|
|
<svg
|
|
className="w-8 h-8 text-success-600"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M5 13l4 4L19 7"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
|
|
<p className="text-gray-600 dark:text-gray-400">
|
|
We've sent a password reset link to{' '}
|
|
<strong className="text-gray-900 dark:text-white">{email}</strong>
|
|
</p>
|
|
|
|
<p className="text-sm text-gray-500 dark:text-gray-400">
|
|
Please check your email and click the link to reset your password.
|
|
The link will expire in 24 hours.
|
|
</p>
|
|
|
|
<div className="pt-4">
|
|
<Link href="/auth/login" variant="primary">
|
|
<Button variant="ghost" fullWidth>
|
|
Back to login
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</AuthLayout>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<AuthLayout
|
|
title="Reset your password"
|
|
subtitle="Enter your email address and we'll send you a reset link"
|
|
>
|
|
<form onSubmit={handleSubmit} className="space-y-6">
|
|
{error && (
|
|
<div
|
|
className="bg-error-50 border border-error-200 text-error-800 px-4 py-3 rounded-md"
|
|
role="alert"
|
|
>
|
|
<p className="text-sm">
|
|
{error.message || 'Failed to send reset email. Please try again.'}
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
<Input
|
|
type="email"
|
|
name="email"
|
|
label="Email address"
|
|
placeholder="you@example.com"
|
|
value={email}
|
|
onChange={(e) => {
|
|
setEmail(e.target.value)
|
|
if (emailError) setEmailError('')
|
|
}}
|
|
error={emailError}
|
|
required
|
|
fullWidth
|
|
autoComplete="email"
|
|
/>
|
|
|
|
<Button
|
|
type="submit"
|
|
variant="primary"
|
|
size="lg"
|
|
fullWidth
|
|
isLoading={isLoading}
|
|
disabled={isLoading}
|
|
>
|
|
Send reset link
|
|
</Button>
|
|
|
|
<div className="text-center text-sm text-gray-600 dark:text-gray-400">
|
|
Remember your password?{' '}
|
|
<Link href="/auth/login" variant="primary">
|
|
Sign in
|
|
</Link>
|
|
</div>
|
|
</form>
|
|
</AuthLayout>
|
|
)
|
|
}
|