diff --git a/frontend/src/pages/Applications/Applications.js b/frontend/src/pages/Applications/Applications.js index 33dbd02..ca6e899 100644 --- a/frontend/src/pages/Applications/Applications.js +++ b/frontend/src/pages/Applications/Applications.js @@ -27,10 +27,8 @@ const Applications = () => { const [propertyCache, setPropertyCache] = useState({}); const [spreaderRecommendation, setSpreaderRecommendation] = useState(null); const [loadingRecommendation, setLoadingRecommendation] = useState(false); - - // Application execution state const [executingApplication, setExecutingApplication] = useState(null); - const [showExecutionModal, setShowExecutionModal] = useState(false); + useEffect(() => { fetchApplications(); @@ -134,21 +132,9 @@ const Applications = () => { } }; - const handleExecuteApplication = async (application) => { - try { - // Set the executing application and show the modal - setExecutingApplication(application); - - // Also fetch the property details if we don't have them - if (!selectedPropertyDetails || selectedPropertyDetails.id !== application.property?.id) { - await fetchPropertyDetails(application.property?.id || application.section?.propertyId); - } - - setShowExecutionModal(true); - } catch (error) { - console.error('Failed to start application execution:', error); - toast.error('Failed to start application execution'); - } + const handleExecuteApplication = (application) => { + setExecutingApplication(application); + alert(`Executing application for ${application.propertyName} - ${application.sectionNames}`); }; if (loading) { @@ -270,10 +256,6 @@ const Applications = () => { onClick={() => { setSelectedPropertyDetails(null); // Clear previous property data setShowPlanForm(true); - // Test the execution state variables - console.log('Test:', showExecutionModal, executingApplication); - setShowExecutionModal(false); - setExecutingApplication(null); }} className="btn-primary flex items-center gap-2" > @@ -1402,337 +1384,9 @@ const ApplicationPlanModal = ({ )} - {/* Application Execution Modal */} - {showExecutionModal && ( -
Test: {executingApplication?.id}
- )} ); }; -// Application Execution Modal Component -const ApplicationExecutionModal = ({ application, propertyDetails, onClose, onComplete }) => { - const [isTracking, setIsTracking] = useState(false); - const [gpsTrack, setGpsTrack] = useState([]); - const [currentLocation, setCurrentLocation] = useState(null); - const [currentSpeed, setCurrentSpeed] = useState(0); - const [startTime, setStartTime] = useState(null); - const [watchId, setWatchId] = useState(null); - const [previousLocation, setPreviousLocation] = useState(null); - const [previousTime, setPreviousTime] = useState(null); - const [totalDistance, setTotalDistance] = useState(0); - const [averageSpeed, setAverageSpeed] = useState(0); - - // Calculate target speed for liquid applications - const targetSpeed = React.useMemo(() => { - if (!application.products || application.products.length === 0) return null; - - // Find the first liquid product to get equipment specs - const firstProduct = application.products[0]; - if (firstProduct.applicationType !== 'liquid') return null; - - // This would be calculated based on equipment specs and application rate - // For now, return a default target speed - this should be calculated from the plan - return 3.0; // 3.0 mph default target - }, [application]); - - const speedStatus = React.useMemo(() => { - if (!targetSpeed || !currentSpeed) return 'normal'; - - const tolerance = 0.1; // 10% tolerance - const lowerBound = targetSpeed * (1 - tolerance); - const upperBound = targetSpeed * (1 + tolerance); - - if (currentSpeed < lowerBound) return 'slow'; - if (currentSpeed > upperBound) return 'fast'; - return 'normal'; - }, [currentSpeed, targetSpeed]); - - // Start GPS tracking - const startTracking = () => { - if (!navigator.geolocation) { - toast.error('GPS not available on this device'); - return; - } - - setIsTracking(true); - setStartTime(new Date()); - setGpsTrack([]); - setTotalDistance(0); - setPreviousLocation(null); - setPreviousTime(null); - - const watchId = navigator.geolocation.watchPosition( - (position) => { - const { latitude, longitude, accuracy, speed } = position.coords; - const timestamp = new Date(position.timestamp); - - const newLocation = { - lat: latitude, - lng: longitude, - accuracy, - timestamp: timestamp.toISOString(), - speed: speed || 0 - }; - - setCurrentLocation(newLocation); - - // Calculate speed if we have a previous location - if (previousLocation && previousTime) { - const distance = calculateDistance( - previousLocation.lat, previousLocation.lng, - latitude, longitude - ); - const timeDiff = (timestamp - previousTime) / 1000; // seconds - - if (timeDiff > 0) { - const speedMph = (distance / timeDiff) * 2.237; // Convert m/s to mph - setCurrentSpeed(speedMph); - - setTotalDistance(prev => prev + distance); - - // Update average speed - const totalTime = (timestamp - startTime) / 1000; // seconds - if (totalTime > 0) { - const avgSpeedMph = (totalDistance + distance) / totalTime * 2.237; - setAverageSpeed(avgSpeedMph); - } - } - } - - setPreviousLocation({ lat: latitude, lng: longitude }); - setPreviousTime(timestamp); - - setGpsTrack(prev => [...prev, newLocation]); - }, - (error) => { - console.error('GPS error:', error); - toast.error(`GPS error: ${error.message}`); - }, - { - enableHighAccuracy: true, - timeout: 5000, - maximumAge: 1000 - } - ); - - setWatchId(watchId); - }; - - // Stop GPS tracking - const stopTracking = () => { - if (watchId) { - navigator.geolocation.clearWatch(watchId); - setWatchId(null); - } - setIsTracking(false); - }; - - // Complete application - const completeApplication = () => { - stopTracking(); - - const endTime = new Date(); - const duration = startTime ? (endTime - startTime) / 1000 : 0; // seconds - - const logData = { - planId: application.id, - lawnSectionId: application.sections?.[0]?.id || application.section?.id, // Use first section for multi-area plans - equipmentId: application.equipment?.id, - applicationDate: endTime.toISOString(), - gpsTrack: gpsTrack, - averageSpeed: averageSpeed, - areaCovered: application.totalSectionArea || application.sectionArea || 0, - notes: `Application completed via mobile tracking. Duration: ${Math.round(duration/60)} minutes`, - products: application.products?.map(product => ({ - productId: product.productId, - userProductId: product.userProductId, - rateAmount: product.rateAmount, - rateUnit: product.rateUnit, - actualProductAmount: product.actualProductAmount || product.productAmount, - actualWaterAmount: product.actualWaterAmount || product.waterAmount, - actualSpeedMph: averageSpeed - })) || [] - }; - - onComplete(logData); - }; - - // Calculate distance between two points in meters - const calculateDistance = (lat1, lng1, lat2, lng2) => { - const R = 6371e3; // Earth's radius in meters - const φ1 = lat1 * Math.PI/180; - const φ2 = lat2 * Math.PI/180; - const Δφ = (lat2-lat1) * Math.PI/180; - const Δλ = (lng2-lng1) * Math.PI/180; - - const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) + - Math.cos(φ1) * Math.cos(φ2) * - Math.sin(Δλ/2) * Math.sin(Δλ/2); - const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); - - return R * c; - }; - - // Cleanup on unmount - React.useEffect(() => { - return () => { - if (watchId) { - navigator.geolocation.clearWatch(watchId); - } - }; - }, [watchId]); - - return ( -
-
-
-

Execute Application

- -
- - {/* Application Details */} -
-

Application Details

-
-
- Property: {application.propertyName} -
-
- Areas: {application.sectionNames} -
-
- Equipment: {application.equipmentName} -
-
- Area: {Math.round(application.totalSectionArea || application.sectionArea || 0).toLocaleString()} sq ft -
-
- - {/* Products */} -
-
Products to Apply:
-
- {application.products?.map((product, index) => ( -
-
{product.productName}
-
- Rate: {product.rateAmount} {product.rateUnit} - {product.productAmount && ` • Product: ${product.productAmount}`} - {product.waterAmount && ` • Water: ${product.waterAmount}`} -
-
- ))} -
-
-
- - {/* Speed Guidance for Liquid Applications */} - {targetSpeed && ( -
-
-
-

Speed Guidance

-

- Target: {targetSpeed.toFixed(1)} mph • Current: {currentSpeed.toFixed(1)} mph -

-
-
- {speedStatus === 'normal' ? '✓ Good Speed' : - speedStatus === 'slow' ? '↑ Go Faster' : - '↓ Slow Down'} -
-
-
- )} - - {/* Map with GPS Track */} -
-

Application Area & GPS Track

-
- {propertyDetails && ( - s.id) || []} - mode="execution" - gpsTrack={gpsTrack} - currentLocation={currentLocation} - /> - )} -
-
- - {/* Tracking Stats */} - {isTracking && ( -
-

Tracking Statistics

-
-
- Duration:
- {startTime ? Math.round((new Date() - startTime) / 60000) : 0} min -
-
- Distance:
- {(totalDistance * 3.28084).toFixed(0)} ft -
-
- Avg Speed:
- {averageSpeed.toFixed(1)} mph -
-
- Track Points:
- {gpsTrack.length} -
-
-
- )} - - {/* Action Buttons */} -
- {!isTracking ? ( - - ) : ( - <> - - - - )} - -
-
-
- ); -}; - -export default Applications; \ No newline at end of file +export default Applications;