asdf
This commit is contained in:
@@ -26,6 +26,18 @@ const ApplicationPlanModal = ({
|
|||||||
const [spreaderSettings, setSpreaderSettings] = useState({});
|
const [spreaderSettings, setSpreaderSettings] = useState({});
|
||||||
const [showSpreaderSettingsForm, setShowSpreaderSettingsForm] = useState(false);
|
const [showSpreaderSettingsForm, setShowSpreaderSettingsForm] = useState(false);
|
||||||
const [currentProductForSettings, setCurrentProductForSettings] = useState(null);
|
const [currentProductForSettings, setCurrentProductForSettings] = useState(null);
|
||||||
|
const [spreaderFormData, setSpreaderFormData] = useState({
|
||||||
|
setting1: '',
|
||||||
|
setting2: '',
|
||||||
|
setting3: '',
|
||||||
|
setting4: '',
|
||||||
|
setting5: '',
|
||||||
|
setting6: '',
|
||||||
|
setting7: '',
|
||||||
|
setting8: '',
|
||||||
|
setting9: '',
|
||||||
|
setting10: ''
|
||||||
|
});
|
||||||
|
|
||||||
// Calculate map center from property or sections
|
// Calculate map center from property or sections
|
||||||
const mapCenter = React.useMemo(() => {
|
const mapCenter = React.useMemo(() => {
|
||||||
@@ -262,6 +274,51 @@ const ApplicationPlanModal = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Save spreader settings
|
||||||
|
const saveSpreaderSettings = async () => {
|
||||||
|
try {
|
||||||
|
const payload = {
|
||||||
|
productId: currentProductForSettings.isShared ? currentProductForSettings.id : null,
|
||||||
|
userProductId: !currentProductForSettings.isShared ? currentProductForSettings.id : null,
|
||||||
|
equipmentId: parseInt(selectedEquipmentId),
|
||||||
|
setting1: parseFloat(spreaderFormData.setting1) || null,
|
||||||
|
setting2: parseFloat(spreaderFormData.setting2) || null,
|
||||||
|
setting3: parseFloat(spreaderFormData.setting3) || null,
|
||||||
|
setting4: parseFloat(spreaderFormData.setting4) || null,
|
||||||
|
setting5: parseFloat(spreaderFormData.setting5) || null,
|
||||||
|
setting6: parseFloat(spreaderFormData.setting6) || null,
|
||||||
|
setting7: parseFloat(spreaderFormData.setting7) || null,
|
||||||
|
setting8: parseFloat(spreaderFormData.setting8) || null,
|
||||||
|
setting9: parseFloat(spreaderFormData.setting9) || null,
|
||||||
|
setting10: parseFloat(spreaderFormData.setting10) || null
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await fetch('/api/product-spreader-settings', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${localStorage.getItem('authToken')}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
toast.success('Spreader settings saved successfully');
|
||||||
|
setShowSpreaderSettingsForm(false);
|
||||||
|
setCurrentProductForSettings(null);
|
||||||
|
setSpreaderFormData({
|
||||||
|
setting1: '', setting2: '', setting3: '', setting4: '', setting5: '',
|
||||||
|
setting6: '', setting7: '', setting8: '', setting9: '', setting10: ''
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error('Failed to save spreader settings');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save spreader settings:', error);
|
||||||
|
toast.error('Failed to save spreader settings');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Calculate application amounts
|
// Calculate application amounts
|
||||||
const calculateApplicationAmounts = () => {
|
const calculateApplicationAmounts = () => {
|
||||||
if (!selectedPropertyDetails?.sections || selectedAreas.length === 0) return null;
|
if (!selectedPropertyDetails?.sections || selectedAreas.length === 0) return null;
|
||||||
@@ -563,12 +620,30 @@ const ApplicationPlanModal = ({
|
|||||||
updateProduct(index, 'productType', selectedProduct.productType);
|
updateProduct(index, 'productType', selectedProduct.productType);
|
||||||
|
|
||||||
// Pre-populate application rate if available
|
// Pre-populate application rate if available
|
||||||
|
console.log('Selected product for rate population:', selectedProduct);
|
||||||
|
|
||||||
|
let rateSet = false;
|
||||||
|
|
||||||
|
// Check for rates array
|
||||||
if (selectedProduct.rates && selectedProduct.rates.length > 0) {
|
if (selectedProduct.rates && selectedProduct.rates.length > 0) {
|
||||||
const defaultRate = selectedProduct.rates[0];
|
const defaultRate = selectedProduct.rates[0];
|
||||||
updateProduct(index, 'rateAmount', defaultRate.amount);
|
updateProduct(index, 'rateAmount', defaultRate.amount);
|
||||||
updateProduct(index, 'rateUnit', defaultRate.unit);
|
updateProduct(index, 'rateUnit', defaultRate.unit);
|
||||||
} else {
|
rateSet = true;
|
||||||
// Set default rate unit based on product type
|
}
|
||||||
|
// Check for applicationRate field (custom products might use this)
|
||||||
|
else if (selectedProduct.applicationRate) {
|
||||||
|
updateProduct(index, 'rateAmount', selectedProduct.applicationRate);
|
||||||
|
rateSet = true;
|
||||||
|
}
|
||||||
|
// Check for recommendedRate field
|
||||||
|
else if (selectedProduct.recommendedRate) {
|
||||||
|
updateProduct(index, 'rateAmount', selectedProduct.recommendedRate);
|
||||||
|
rateSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set default rate unit if no rate was found or if unit wasn't set
|
||||||
|
if (!rateSet || !selectedProduct.rates?.[0]?.unit) {
|
||||||
if (selectedProduct.productType === 'granular') {
|
if (selectedProduct.productType === 'granular') {
|
||||||
updateProduct(index, 'rateUnit', 'lb/1000sqft');
|
updateProduct(index, 'rateUnit', 'lb/1000sqft');
|
||||||
} else if (selectedProduct.productType === 'liquid') {
|
} else if (selectedProduct.productType === 'liquid') {
|
||||||
@@ -590,8 +665,8 @@ const ApplicationPlanModal = ({
|
|||||||
.filter(prod => !applicationType || prod.productType === applicationType)
|
.filter(prod => !applicationType || prod.productType === applicationType)
|
||||||
.map(prod => (
|
.map(prod => (
|
||||||
<option key={prod.uniqueId || prod.id} value={prod.uniqueId || prod.id}>
|
<option key={prod.uniqueId || prod.id} value={prod.uniqueId || prod.id}>
|
||||||
{prod.name} ({prod.brand})
|
{prod.name} - {prod.brand}
|
||||||
{prod.isShared === false && ' - Custom'}
|
{prod.isShared === false && ' (Custom)'}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
@@ -780,19 +855,45 @@ const ApplicationPlanModal = ({
|
|||||||
|
|
||||||
{/* Spreader Settings Form Modal */}
|
{/* Spreader Settings Form Modal */}
|
||||||
{showSpreaderSettingsForm && currentProductForSettings && (
|
{showSpreaderSettingsForm && currentProductForSettings && (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-60">
|
<div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center" style={{zIndex: 9999}}>
|
||||||
<div className="bg-white rounded-lg p-6 w-full max-w-md mx-4">
|
<div className="bg-white rounded-lg p-6 w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto">
|
||||||
<h3 className="text-lg font-semibold mb-4">Add Spreader Settings</h3>
|
<h3 className="text-lg font-semibold mb-4">Add Spreader Settings</h3>
|
||||||
<p className="text-sm text-gray-600 mb-4">
|
<p className="text-sm text-gray-600 mb-4">
|
||||||
No spreader settings found for "{currentProductForSettings.name}".
|
No spreader settings found for "{currentProductForSettings.name}" with the selected equipment.
|
||||||
Please add the spreader setting for accurate calculations.
|
Please add the spreader settings for accurate calculations.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gap-3">
|
|
||||||
|
<div className="grid grid-cols-2 gap-4 mb-6">
|
||||||
|
{Array.from({ length: 10 }, (_, i) => i + 1).map(num => (
|
||||||
|
<div key={num}>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
|
Setting {num}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.1"
|
||||||
|
value={spreaderFormData[`setting${num}`]}
|
||||||
|
onChange={(e) => setSpreaderFormData(prev => ({
|
||||||
|
...prev,
|
||||||
|
[`setting${num}`]: e.target.value
|
||||||
|
}))}
|
||||||
|
className="w-full border border-gray-300 rounded px-3 py-2"
|
||||||
|
placeholder={`Setting ${num} value`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end gap-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowSpreaderSettingsForm(false);
|
setShowSpreaderSettingsForm(false);
|
||||||
setCurrentProductForSettings(null);
|
setCurrentProductForSettings(null);
|
||||||
|
setSpreaderFormData({
|
||||||
|
setting1: '', setting2: '', setting3: '', setting4: '', setting5: '',
|
||||||
|
setting6: '', setting7: '', setting8: '', setting9: '', setting10: ''
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
className="px-4 py-2 text-gray-600 hover:text-gray-800"
|
className="px-4 py-2 text-gray-600 hover:text-gray-800"
|
||||||
>
|
>
|
||||||
@@ -800,15 +901,10 @@ const ApplicationPlanModal = ({
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={saveSpreaderSettings}
|
||||||
// Open spreader settings page in new tab
|
|
||||||
window.open('/spreader-settings', '_blank');
|
|
||||||
setShowSpreaderSettingsForm(false);
|
|
||||||
setCurrentProductForSettings(null);
|
|
||||||
}}
|
|
||||||
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
|
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
|
||||||
>
|
>
|
||||||
Add Settings
|
Save Settings
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user