ajinkya-mhetre-mern
Version:
A MERN starter with frontend and backend folders
289 lines (269 loc) • 10.6 kB
JSX
// src/pages/auth/Register.jsx
import React, { useState } from 'react'
import { Link } from 'react-router-dom'
import { useAuth } from '../../contexts/AuthContext'
const baseUrl = import.meta.env.VITE_API_URL;
function Register() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
confirmPassword: '',
phone: '',
role: 'customer',
address: {
street: '',
city: '',
state: '',
zipCode: ''
}
})
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const { login } = useAuth()
const handleChange = (e) => {
const { name, value } = e.target
if (name.includes('.')) {
const [parent, child] = name.split('.')
setFormData({
...formData,
[parent]: {
...formData[parent],
[child]: value
}
})
} else {
setFormData({
...formData,
[name]: value
})
}
if (error) setError('')
}
const validateForm = () => {
if (formData.password !== formData.confirmPassword) {
setError('Passwords do not match')
return false
}
if (formData.password.length < 6) {
setError('Password must be at least 6 characters')
return false
}
return true
}
const handleSubmit = async (e) => {
e.preventDefault()
if (!validateForm()) return
setLoading(true)
setError('')
const requestBody = {
name: formData.name,
email: formData.email,
password: formData.password,
phone: formData.phone,
role: formData.role,
address: formData.address
}
try {
const response = await fetch(`${baseUrl}/auth/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody)
})
const data = await response.json()
if (data.success) {
login(data)
} else {
setError(data.message || 'Registration failed')
}
} catch (error) {
setError('Network error. Please try again.')
console.error('Registration error:', error)
} finally {
setLoading(false)
}
}
return (
<div className="min-h-screen bg-gradient-to-br from-green-50 to-blue-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-2xl mx-auto">
<div className="text-center mb-8">
<div className="mx-auto h-16 w-16 bg-green-600 rounded-full flex items-center justify-center">
<svg className="h-8 w-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" />
</svg>
</div>
<h1 className="mt-6 text-3xl font-extrabold text-gray-900">
Create Customer Account
</h1>
<p className="mt-2 text-gray-600">
Join our platform to buy fresh produce directly from farmers
</p>
</div>
<div className="bg-white rounded-xl shadow-lg p-8">
<form onSubmit={handleSubmit} className="space-y-6">
{error && (
<div className="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-lg">
{error}
</div>
)}
{/* Basic Information */}
<div className="bg-white p-6 rounded-lg border border-gray-200">
<h3 className="text-lg font-medium text-gray-900 mb-4">Basic Information</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Full Name *
</label>
<input
type="text"
name="name"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
value={formData.name}
onChange={handleChange}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Email Address *
</label>
<input
type="email"
name="email"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
value={formData.email}
onChange={handleChange}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Phone Number *
</label>
<input
type="tel"
name="phone"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
value={formData.phone}
onChange={handleChange}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Password *
</label>
<input
type="password"
name="password"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
value={formData.password}
onChange={handleChange}
/>
</div>
<div className="md:col-span-2">
<label className="block text-sm font-medium text-gray-700 mb-2">
Confirm Password *
</label>
<input
type="password"
name="confirmPassword"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
value={formData.confirmPassword}
onChange={handleChange}
/>
</div>
</div>
</div>
{/* Address Information */}
<div className="bg-white p-6 rounded-lg border border-gray-200">
<h3 className="text-lg font-medium text-gray-900 mb-4">Address Information</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="md:col-span-2">
<label className="block text-sm font-medium text-gray-700 mb-2">
Street Address *
</label>
<input
type="text"
name="address.street"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
value={formData.address.street}
onChange={handleChange}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
City *
</label>
<input
type="text"
name="address.city"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
value={formData.address.city}
onChange={handleChange}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
State *
</label>
<input
type="text"
name="address.state"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
value={formData.address.state}
onChange={handleChange}
/>
</div>
<div className="md:col-span-2">
<label className="block text-sm font-medium text-gray-700 mb-2">
ZIP Code *
</label>
<input
type="text"
name="address.zipCode"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
value={formData.address.zipCode}
onChange={handleChange}
/>
</div>
</div>
</div>
<button
type="submit"
disabled={loading}
className="w-full bg-green-600 text-white py-3 px-4 rounded-lg hover:bg-green-700 focus:ring-2 focus:ring-green-500 focus:ring-offset-2 transition duration-200 font-medium disabled:opacity-50 disabled:cursor-not-allowed"
>
{loading ? (
<div className="flex items-center justify-center">
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white mr-2"></div>
Creating Account...
</div>
) : (
'Create Customer Account'
)}
</button>
<div className="text-center">
<span className="text-gray-600">Already have an account? </span>
<Link
to="/login"
className="text-green-600 hover:text-green-500 font-medium"
>
Sign in here
</Link>
</div>
</form>
</div>
</div>
</div>
)
}
export default Register