diff --git a/backend/src/utils/validation.js b/backend/src/utils/validation.js index 05061ff..700ed1a 100644 --- a/backend/src/utils/validation.js +++ b/backend/src/utils/validation.js @@ -76,11 +76,11 @@ const productRateSchema = Joi.object({ }); const userProductSchema = Joi.object({ - productId: Joi.number().integer().positive(), - customName: Joi.string().max(255), - customRateAmount: Joi.number().positive(), - customRateUnit: Joi.string().max(50), - notes: Joi.string() + productId: Joi.number().integer().positive().allow(null).optional(), + customName: Joi.string().max(255).allow(null).optional(), + customRateAmount: Joi.number().positive().allow(null).optional(), + customRateUnit: Joi.string().max(50).allow(null).optional(), + notes: Joi.string().allow(null, '').optional() }); // Application validation schemas diff --git a/frontend/src/pages/Products/Products.js b/frontend/src/pages/Products/Products.js index 8482099..3b1e8ba 100644 --- a/frontend/src/pages/Products/Products.js +++ b/frontend/src/pages/Products/Products.js @@ -350,6 +350,10 @@ const CreateProductModal = ({ onSubmit, onCancel, sharedProducts, categories }) const [formData, setFormData] = useState({ productId: '', customName: '', + categoryId: '', + productType: 'granular', + brand: '', + activeIngredients: '', customRateAmount: '', customRateUnit: 'lbs/1000 sq ft', notes: '' @@ -363,6 +367,12 @@ const CreateProductModal = ({ onSubmit, onCancel, sharedProducts, categories }) return; } + // If creating a completely custom product (no base product), require more fields + if (!formData.productId && (!formData.categoryId || !formData.productType)) { + toast.error('Please select a category and product type for custom products'); + return; + } + const submitData = { productId: formData.productId ? parseInt(formData.productId) : null, customName: formData.customName || null, @@ -413,6 +423,63 @@ const CreateProductModal = ({ onSubmit, onCancel, sharedProducts, categories })

+ {/* Show additional fields when creating completely custom product */} + {!formData.productId && ( + <> +
+
+ + +
+
+ + +
+
+ +
+ + setFormData({ ...formData, brand: e.target.value })} + placeholder="e.g., Scotts, Syngenta, Custom Mix" + /> +
+ +
+ + setFormData({ ...formData, activeIngredients: e.target.value })} + placeholder="e.g., 2,4-D 25%, Nitrogen 24%, Iron 2%" + /> +
+ + )} +