ajinkya-mhetre-mern
Version:
A MERN starter with frontend and backend folders
368 lines (345 loc) • 14.4 kB
JSX
// src/pages/auth/FarmerRegister.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 FarmerRegister() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
confirmPassword: '',
phone: '',
role: 'farmer',
address: {
street: '',
city: '',
state: '',
zipCode: ''
},
farmDetails: {
farmName: '',
farmSize: '',
farmLocation: '',
certifications: []
}
})
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const { login } = useAuth()
const certificationOptions = ['Organic', 'Non-GMO', 'Fair Trade', 'Sustainable']
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 handleCertificationChange = (certification) => {
const certifications = formData.farmDetails.certifications.includes(certification)
? formData.farmDetails.certifications.filter(c => c !== certification)
: [...formData.farmDetails.certifications, certification]
setFormData({
...formData,
farmDetails: {
...formData.farmDetails,
certifications
}
})
}
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,
farmDetails: formData.farmDetails
}
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="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<h1 className="mt-6 text-3xl font-extrabold text-gray-900">
Create Farmer Account
</h1>
<p className="mt-2 text-gray-600">
Join our platform to sell your produce directly to customers
</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>
{/* Farm Details */}
<div className="bg-white p-6 rounded-lg border border-gray-200">
<h3 className="text-lg font-medium text-gray-900 mb-4">Farm 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">
Farm Name *
</label>
<input
type="text"
name="farmDetails.farmName"
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.farmDetails.farmName}
onChange={handleChange}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Farm Size *
</label>
<input
type="text"
name="farmDetails.farmSize"
required
placeholder="e.g., 5 acres"
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.farmDetails.farmSize}
onChange={handleChange}
/>
</div>
<div className="md:col-span-2">
<label className="block text-sm font-medium text-gray-700 mb-2">
Farm Location *
</label>
<input
type="text"
name="farmDetails.farmLocation"
required
placeholder="e.g., Pune, Maharashtra"
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.farmDetails.farmLocation}
onChange={handleChange}
/>
</div>
<div className="md:col-span-2">
<label className="block text-sm font-medium text-gray-700 mb-2">
Certifications (Optional)
</label>
<div className="grid grid-cols-2 gap-2">
{certificationOptions.map((cert) => (
<label key={cert} className="flex items-center">
<input
type="checkbox"
checked={formData.farmDetails.certifications.includes(cert)}
onChange={() => handleCertificationChange(cert)}
className="h-4 w-4 text-green-600 focus:ring-green-500 border-gray-300 rounded"
/>
<span className="ml-2 text-sm text-gray-700">{cert}</span>
</label>
))}
</div>
</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 Farmer Account'
)}
</button>
</form>
</div>
</div>
</div>
)
}
export default FarmerRegister