UNPKG

ajinkya-mhetre-mern

Version:

A MERN starter with frontend and backend folders

368 lines (345 loc) 14.4 kB
// 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