diff --git a/frontend/src/components/Applications/ApplicationPlanModal.js b/frontend/src/components/Applications/ApplicationPlanModal.js index 343ba95..4662e1c 100644 --- a/frontend/src/components/Applications/ApplicationPlanModal.js +++ b/frontend/src/components/Applications/ApplicationPlanModal.js @@ -23,6 +23,9 @@ const ApplicationPlanModal = ({ const [plannedDate, setPlannedDate] = useState(''); const [notes, setNotes] = useState(''); const [loading, setLoading] = useState(false); + const [spreaderSettings, setSpreaderSettings] = useState({}); + const [showSpreaderSettingsForm, setShowSpreaderSettingsForm] = useState(false); + const [currentProductForSettings, setCurrentProductForSettings] = useState(null); // Calculate map center from property or sections const mapCenter = React.useMemo(() => { @@ -223,6 +226,93 @@ const ApplicationPlanModal = ({ )); }; + // Check spreader settings for granular products + const checkSpreaderSettings = async (product, equipmentId) => { + try { + const productApiId = product.isShared ? product.id : product.id; + const endpoint = product.isShared + ? `/api/product-spreader-settings/product/${productApiId}` + : `/api/product-spreader-settings/user-product/${productApiId}`; + + const response = await fetch(endpoint, { + headers: { + 'Authorization': `Bearer ${localStorage.getItem('authToken')}` + } + }); + + if (response.ok) { + const data = await response.json(); + const settings = data.data?.settings || []; + const equipmentSetting = settings.find(s => s.equipmentId === parseInt(equipmentId)); + + if (!equipmentSetting) { + // No spreader setting found, prompt user to add one + setCurrentProductForSettings(product); + setShowSpreaderSettingsForm(true); + } else { + // Store the spreader setting for calculations + setSpreaderSettings(prev => ({ + ...prev, + [`${product.id}_${equipmentId}`]: equipmentSetting + })); + } + } + } catch (error) { + console.error('Failed to check spreader settings:', error); + } + }; + + // Calculate application amounts + const calculateApplicationAmounts = () => { + if (!selectedPropertyDetails?.sections || selectedAreas.length === 0) return null; + + const totalArea = selectedAreas.reduce((total, areaId) => { + const area = selectedPropertyDetails.sections.find(s => s.id === areaId); + return total + (area?.area || 0); + }, 0); + + const calculations = selectedProducts.map(product => { + const rateAmount = parseFloat(product.rateAmount) || 0; + const areaIn1000s = totalArea / 1000; + + if (product.productType === 'granular') { + // Granular calculations + const totalProductNeeded = rateAmount * areaIn1000s; + return { + productName: product.productName, + totalProductNeeded: totalProductNeeded.toFixed(2), + unit: product.rateUnit, + waterNeeded: 0 // No water for granular + }; + } else { + // Liquid calculations + const totalProductNeeded = rateAmount * areaIn1000s; + + // Calculate water needed based on nozzle and equipment settings + let waterNeeded = 0; + if (selectedNozzleId) { + const selectedNozzle = nozzles.find(n => n.id === parseInt(selectedNozzleId)); + if (selectedNozzle && selectedNozzle.flowRateGpm) { + // Basic calculation - this would need equipment speed settings for accuracy + waterNeeded = (selectedNozzle.flowRateGpm * 60 * areaIn1000s) / 1000; // Rough estimate + } + } + + return { + productName: product.productName, + totalProductNeeded: totalProductNeeded.toFixed(2), + unit: product.rateUnit, + waterNeeded: waterNeeded.toFixed(1) + }; + } + }); + + return { + totalArea: totalArea.toLocaleString(), + calculations + }; + }; + // Handle form submission const handleSubmit = async (e) => { e.preventDefault(); @@ -397,15 +487,15 @@ const ApplicationPlanModal = ({ if (!applicationType) return true; // Filter by application type - granular needs Spreader, liquid needs Sprayer if (applicationType === 'granular') { - return eq.category_name === 'Spreader'; + return eq.categoryName === 'Spreader'; } else if (applicationType === 'liquid') { - return eq.category_name === 'Sprayer'; + return eq.categoryName === 'Sprayer'; } return true; }) .map(eq => ( ))} @@ -427,9 +517,9 @@ const ApplicationPlanModal = ({ {nozzles.map(nozzle => ( ))} @@ -468,25 +558,27 @@ const ApplicationPlanModal = ({ updateProduct(index, 'productId', selectedProduct.isShared ? selectedProduct.id : null); updateProduct(index, 'userProductId', !selectedProduct.isShared ? selectedProduct.id : null); updateProduct(index, 'isUserProduct', !selectedProduct.isShared); - updateProduct(index, 'productName', selectedProduct.name || selectedProduct.product_name); - updateProduct(index, 'productBrand', selectedProduct.brand || selectedProduct.product_brand); - updateProduct(index, 'productType', selectedProduct.productType || selectedProduct.product_type); + updateProduct(index, 'productName', selectedProduct.name); + updateProduct(index, 'productBrand', selectedProduct.brand); + updateProduct(index, 'productType', selectedProduct.productType); // Pre-populate application rate if available - if (selectedProduct.applicationRate) { - updateProduct(index, 'rateAmount', selectedProduct.applicationRate); - } else if (selectedProduct.application_rate) { - updateProduct(index, 'rateAmount', selectedProduct.application_rate); - } else if (selectedProduct.recommendedRate) { - updateProduct(index, 'rateAmount', selectedProduct.recommendedRate); + if (selectedProduct.rates && selectedProduct.rates.length > 0) { + const defaultRate = selectedProduct.rates[0]; + updateProduct(index, 'rateAmount', defaultRate.amount); + updateProduct(index, 'rateUnit', defaultRate.unit); + } else { + // Set default rate unit based on product type + if (selectedProduct.productType === 'granular') { + updateProduct(index, 'rateUnit', 'lb/1000sqft'); + } else if (selectedProduct.productType === 'liquid') { + updateProduct(index, 'rateUnit', 'oz/1000sqft'); + } } - // Set appropriate rate unit based on product type - const productType = selectedProduct.productType || selectedProduct.product_type; - if (productType === 'granular') { - updateProduct(index, 'rateUnit', 'lb/1000sqft'); - } else if (productType === 'liquid') { - updateProduct(index, 'rateUnit', 'oz/1000sqft'); + // For granular products, check if spreader settings exist + if (selectedProduct.productType === 'granular' && selectedEquipmentId) { + checkSpreaderSettings(selectedProduct, selectedEquipmentId); } } }} @@ -495,15 +587,10 @@ const ApplicationPlanModal = ({ > {products - .filter(prod => !applicationType || - (prod.productType === applicationType) || - (prod.product_type === applicationType) || - (prod.type === applicationType) - ) + .filter(prod => !applicationType || prod.productType === applicationType) .map(prod => ( ))} @@ -571,6 +658,26 @@ const ApplicationPlanModal = ({ )} + {/* Application Calculations */} + {selectedProducts.length > 0 && selectedAreas.length > 0 && (() => { + const calculations = calculateApplicationAmounts(); + return calculations ? ( +
Total Area: {calculations.totalArea} sq ft
+ {calculations.calculations.map((calc, index) => ( +{calc.productName}:
+Product needed: {calc.totalProductNeeded} {calc.unit}
+ {calc.waterNeeded > 0 &&Water needed: {calc.waterNeeded} gallons
} ++ No spreader settings found for "{currentProductForSettings.name}". + Please add the spreader setting for accurate calculations. +
+