import React, { useState, useEffect } from 'react'; import { applicationsAPI } from '../../services/api'; import PropertyMap from '../Maps/PropertyMap'; import { XMarkIcon, ClockIcon, MapPinIcon, WrenchScrewdriverIcon, BeakerIcon } from '@heroicons/react/24/outline'; const ApplicationViewModal = ({ application, propertyDetails, onClose }) => { const [applicationLog, setApplicationLog] = useState(null); const [sections, setSections] = useState([]); const [planDetails, setPlanDetails] = useState(null); const [loading, setLoading] = useState(true); // Haversine distance between two lat/lng in meters const haversineMeters = (lat1, lng1, lat2, lng2) => { const R = 6371e3; const toRad = (d) => (d * Math.PI) / 180; const dLat = toRad(lat2 - lat1); const dLng = toRad(lng2 - lng1); const a = Math.sin(dLat / 2) ** 2 + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLng / 2) ** 2; return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); }; const computeDistanceFeetFromPoints = (points = []) => { if (!Array.isArray(points) || points.length < 2) return 0; let meters = 0; for (let i = 1; i < points.length; i++) { const p1 = points[i - 1]; const p2 = points[i]; meters += haversineMeters(p1.lat, p1.lng, p2.lat, p2.lng); } return meters * 3.28084; // feet }; const distanceFeet = (log) => { if (!log?.gpsTrack) return 0; const stored = log.gpsTrack.totalDistance; if (typeof stored === 'number' && stored > 0) { // stored value is meters (from execution modal). Convert to feet. return stored * 3.28084; } return computeDistanceFeetFromPoints(log.gpsTrack.points); }; // Calculate coverage percentage based on GPS tracking and equipment specifications const calculateCoverage = (application, log) => { if (!log?.gpsTrack?.points || log.gpsTrack.points.length < 2) return 0; const totalDistanceFeet = distanceFeet(log); const plannedArea = application.totalSectionArea || 0; if (totalDistanceFeet === 0 || plannedArea === 0) return 0; // Estimate equipment width based on type (feet) let equipmentWidth = 4; const equipmentName = application.equipmentName?.toLowerCase() || ''; if (equipmentName.includes('spreader')) equipmentWidth = 12; else if (equipmentName.includes('sprayer')) equipmentWidth = 20; else if (equipmentName.includes('mower')) equipmentWidth = 6; // Distance (ft) * Width (ft) = Area (sq ft) const theoreticalCoverageArea = totalDistanceFeet * equipmentWidth; const coveragePercentage = Math.min((theoreticalCoverageArea / plannedArea) * 100, 100); return Math.round(coveragePercentage); }; useEffect(() => { const fetchApplicationData = async () => { if (!application?.id) return; try { setLoading(true); // Fetch the plan details to get section geometry const planResponse = await applicationsAPI.getPlan(application.id); const fetchedPlanDetails = planResponse.data.data.plan; setPlanDetails(fetchedPlanDetails); if (fetchedPlanDetails.sections) { setSections(fetchedPlanDetails.sections); } // Try to fetch application logs to get GPS tracking data try { const logsResponse = await applicationsAPI.getLogs({ planId: application.id }); const logs = logsResponse.data.data.logs; if (logs && logs.length > 0) { setApplicationLog(logs[0]); // Get the most recent log } } catch (error) { console.log('No application logs found:', error); } } catch (error) { console.error('Failed to fetch application data:', error); } finally { setLoading(false); } }; fetchApplicationData(); }, [application?.id]); // Calculate map center from sections const mapCenter = React.useMemo(() => { if (sections.length === 0) return null; let totalLat = 0; let totalLng = 0; let pointCount = 0; sections.forEach(section => { let polygonData = section.polygonData; if (typeof polygonData === 'string') { try { polygonData = JSON.parse(polygonData); } catch (e) { return; } } if (polygonData?.coordinates?.[0]) { polygonData.coordinates[0].forEach(([lat, lng]) => { totalLat += lat; totalLng += lng; pointCount++; }); } }); if (pointCount > 0) { return [totalLat / pointCount, totalLng / pointCount]; } return null; }, [sections]); if (loading) { return (
Property: {application.propertyName}
Areas: {application.sectionNames}
Total Area: {application.totalSectionArea?.toLocaleString()} sq ft
Equipment: {application.equipmentName}
Status: {application.status}
Planned Date: {new Date(application.plannedDate).toLocaleDateString()}
{application.notes || applicationLog?.notes}