diff --git a/frontend/src/app/products/page.tsx b/frontend/src/app/products/page.tsx index 36c06df..3a658b7 100644 --- a/frontend/src/app/products/page.tsx +++ b/frontend/src/app/products/page.tsx @@ -40,6 +40,10 @@ export default function ProductsPage() { name: '', description: '', }); + const [errors, setErrors] = useState({ + name: '', + description: '', + }); useEffect(() => { loadProducts(); @@ -54,8 +58,29 @@ export default function ProductsPage() { } }; + const validateForm = () => { + const newErrors = { + name: '', + description: '', + }; + + // Product name cannot be empty + if (!formData.name.trim()) { + newErrors.name = 'Product name is required'; + } + + // Description can be empty, no validation needed + setErrors(newErrors); + return !newErrors.name; + }; + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); + + if (!validateForm()) { + return; + } + try { if (editingProduct) { await productApi.update(editingProduct.id, formData); @@ -65,6 +90,7 @@ export default function ProductsPage() { setIsDialogOpen(false); setEditingProduct(null); setFormData({ name: '', description: '' }); + setErrors({ name: '', description: '' }); loadProducts(); } catch (error) { console.error('Error saving product:', error); @@ -77,6 +103,7 @@ export default function ProductsPage() { name: product.name, description: product.description, }); + setErrors({ name: '', description: '' }); setIsDialogOpen(true); }; @@ -91,6 +118,14 @@ export default function ProductsPage() { } }; + const handleInputChange = (field: 'name' | 'description', value: string) => { + setFormData({ ...formData, [field]: value }); + // Clear error when user starts typing + if (errors[field]) { + setErrors({ ...errors, [field]: '' }); + } + }; + return (
@@ -100,6 +135,7 @@ export default function ProductsPage() { @@ -110,21 +146,23 @@ export default function ProductsPage() {
- + setFormData({ ...formData, name: e.target.value })} - required + onChange={(e) => handleInputChange('name', e.target.value)} + className={errors.name ? 'border-red-500' : ''} /> + {errors.name && ( +

{errors.name}

+ )}
setFormData({ ...formData, description: e.target.value })} - required + onChange={(e) => handleInputChange('description', e.target.value)} />
diff --git a/frontend/src/app/users/page.tsx b/frontend/src/app/users/page.tsx index 6685d24..1f11785 100644 --- a/frontend/src/app/users/page.tsx +++ b/frontend/src/app/users/page.tsx @@ -40,6 +40,10 @@ export default function UsersPage() { username: '', email: '', }); + const [errors, setErrors] = useState({ + username: '', + email: '', + }); useEffect(() => { loadUsers(); @@ -54,8 +58,38 @@ export default function UsersPage() { } }; + const validateForm = () => { + const newErrors = { + username: '', + email: '', + }; + + // Username cannot be empty + if (!formData.username.trim()) { + newErrors.username = 'Username is required'; + } + + // Email can be empty, but if provided, should be valid + if (formData.email.trim() && !isValidEmail(formData.email)) { + newErrors.email = 'Please enter a valid email address'; + } + + setErrors(newErrors); + return !newErrors.username && !newErrors.email; + }; + + const isValidEmail = (email: string) => { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); + }; + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); + + if (!validateForm()) { + return; + } + try { if (editingUser) { await userApi.update(editingUser.id, formData); @@ -65,6 +99,7 @@ export default function UsersPage() { setIsDialogOpen(false); setEditingUser(null); setFormData({ username: '', email: '' }); + setErrors({ username: '', email: '' }); loadUsers(); } catch (error) { console.error('Error saving user:', error); @@ -74,6 +109,7 @@ export default function UsersPage() { const handleEdit = (user: User) => { setEditingUser(user); setFormData({ username: user.username, email: user.email }); + setErrors({ username: '', email: '' }); setIsDialogOpen(true); }; @@ -88,6 +124,14 @@ export default function UsersPage() { } }; + const handleInputChange = (field: 'username' | 'email', value: string) => { + setFormData({ ...formData, [field]: value }); + // Clear error when user starts typing + if (errors[field]) { + setErrors({ ...errors, [field]: '' }); + } + }; + return (
@@ -97,6 +141,7 @@ export default function UsersPage() { @@ -107,13 +152,16 @@ export default function UsersPage() {
- + setFormData({ ...formData, username: e.target.value })} - required + onChange={(e) => handleInputChange('username', e.target.value)} + className={errors.username ? 'border-red-500' : ''} /> + {errors.username && ( +

{errors.username}

+ )}
@@ -121,9 +169,12 @@ export default function UsersPage() { id="email" type="email" value={formData.email} - onChange={(e) => setFormData({ ...formData, email: e.target.value })} - required + onChange={(e) => handleInputChange('email', e.target.value)} + className={errors.email ? 'border-red-500' : ''} /> + {errors.email && ( +

{errors.email}

+ )}