asdfasdf
This commit is contained in:
@@ -9,38 +9,55 @@ const ApplicationViewModal = ({ application, propertyDetails, onClose }) => {
|
|||||||
const [planDetails, setPlanDetails] = useState(null);
|
const [planDetails, setPlanDetails] = useState(null);
|
||||||
const [loading, setLoading] = useState(true);
|
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
|
// Calculate coverage percentage based on GPS tracking and equipment specifications
|
||||||
const calculateCoverage = (application, log) => {
|
const calculateCoverage = (application, log) => {
|
||||||
if (!log?.gpsTrack?.points || log.gpsTrack.points.length < 2) {
|
if (!log?.gpsTrack?.points || log.gpsTrack.points.length < 2) return 0;
|
||||||
return 0; // No movement = no coverage
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalDistance = log.gpsTrack.totalDistance || 0;
|
const totalDistanceFeet = distanceFeet(log);
|
||||||
const plannedArea = application.totalSectionArea || 0;
|
const plannedArea = application.totalSectionArea || 0;
|
||||||
|
if (totalDistanceFeet === 0 || plannedArea === 0) return 0;
|
||||||
if (totalDistance === 0 || plannedArea === 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Estimate equipment width based on type
|
// Estimate equipment width based on type (feet)
|
||||||
let equipmentWidth = 4; // Default 4 feet for unknown equipment
|
let equipmentWidth = 4;
|
||||||
|
|
||||||
const equipmentName = application.equipmentName?.toLowerCase() || '';
|
const equipmentName = application.equipmentName?.toLowerCase() || '';
|
||||||
if (equipmentName.includes('spreader')) {
|
if (equipmentName.includes('spreader')) equipmentWidth = 12;
|
||||||
equipmentWidth = 12; // Spreaders typically 8-16 feet wide
|
else if (equipmentName.includes('sprayer')) equipmentWidth = 20;
|
||||||
} else if (equipmentName.includes('sprayer')) {
|
else if (equipmentName.includes('mower')) equipmentWidth = 6;
|
||||||
equipmentWidth = 20; // Sprayers typically 15-30 feet wide
|
|
||||||
} else if (equipmentName.includes('mower')) {
|
|
||||||
equipmentWidth = 6; // Mowers typically 4-8 feet wide
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate theoretical coverage area
|
// Distance (ft) * Width (ft) = Area (sq ft)
|
||||||
// Distance (feet) * Width (feet) = Coverage area (sq ft)
|
const theoreticalCoverageArea = totalDistanceFeet * equipmentWidth;
|
||||||
const theoreticalCoverageArea = totalDistance * equipmentWidth;
|
|
||||||
|
|
||||||
// Calculate coverage percentage (capped at 100%)
|
|
||||||
const coveragePercentage = Math.min((theoreticalCoverageArea / plannedArea) * 100, 100);
|
const coveragePercentage = Math.min((theoreticalCoverageArea / plannedArea) * 100, 100);
|
||||||
|
|
||||||
return Math.round(coveragePercentage);
|
return Math.round(coveragePercentage);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -231,7 +248,7 @@ const ApplicationViewModal = ({ application, propertyDetails, onClose }) => {
|
|||||||
<div className="bg-orange-50 p-3 rounded-lg">
|
<div className="bg-orange-50 p-3 rounded-lg">
|
||||||
<div className="text-sm text-orange-600 font-medium">Distance</div>
|
<div className="text-sm text-orange-600 font-medium">Distance</div>
|
||||||
<div className="text-xl font-bold text-orange-900">
|
<div className="text-xl font-bold text-orange-900">
|
||||||
{applicationLog.gpsTrack?.totalDistance?.toFixed(0) || 0} ft
|
{Math.round(distanceFeet(applicationLog))} ft
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-emerald-50 p-3 rounded-lg">
|
<div className="bg-emerald-50 p-3 rounded-lg">
|
||||||
@@ -286,4 +303,4 @@ const ApplicationViewModal = ({ application, propertyDetails, onClose }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ApplicationViewModal;
|
export default ApplicationViewModal;
|
||||||
|
|||||||
Reference in New Issue
Block a user