diff --git a/frontend/src/components/Icons/GrassIcon.js b/frontend/src/components/Icons/GrassIcon.js new file mode 100644 index 0000000..ad3f3d9 --- /dev/null +++ b/frontend/src/components/Icons/GrassIcon.js @@ -0,0 +1,33 @@ +import React from 'react'; + +// Simple grass-shaped icons that follow currentColor +export const GrassIconOutline = (props) => ( + +); + +export const GrassIconSolid = (props) => ( + +); + +export default GrassIconOutline; + diff --git a/frontend/src/components/Layout/Layout.js b/frontend/src/components/Layout/Layout.js index 8a16b86..d2aba69 100644 --- a/frontend/src/components/Layout/Layout.js +++ b/frontend/src/components/Layout/Layout.js @@ -24,6 +24,7 @@ import { ClockIcon as ClockIconSolid, CloudIcon as CloudIconSolid, } from '@heroicons/react/24/solid'; +import { GrassIconOutline, GrassIconSolid } from '../Icons/GrassIcon'; import { useAuth } from '../../hooks/useAuth'; import LoadingSpinner from '../UI/LoadingSpinner'; @@ -68,8 +69,8 @@ const Layout = ({ children }) => { { name: 'Mowing', href: '/mowing', - icon: ClockIcon, - iconSolid: ClockIconSolid, + icon: GrassIconOutline, + iconSolid: GrassIconSolid, }, { name: 'History', diff --git a/frontend/src/components/Mowing/MowingPlanModal.js b/frontend/src/components/Mowing/MowingPlanModal.js index 4d75ef5..b65fb69 100644 --- a/frontend/src/components/Mowing/MowingPlanModal.js +++ b/frontend/src/components/Mowing/MowingPlanModal.js @@ -1,6 +1,8 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { propertiesAPI, equipmentAPI, mowingAPI } from '../../services/api'; import toast from 'react-hot-toast'; +import { XMarkIcon, MapPinIcon, WrenchScrewdriverIcon } from '@heroicons/react/24/outline'; +import PropertyMap from '../Maps/PropertyMap'; const directionOptions = [ { value: 'N_S', label: 'North to South' }, @@ -14,6 +16,7 @@ const MowingPlanModal = ({ onClose, onCreated }) => { const [properties, setProperties] = useState([]); const [mowers, setMowers] = useState([]); const [sections, setSections] = useState([]); + const [selectedPropertyDetails, setSelectedPropertyDetails] = useState(null); const [propertyId, setPropertyId] = useState(''); const [lawnSectionIds, setLawnSectionIds] = useState([]); const [equipmentId, setEquipmentId] = useState(''); @@ -36,14 +39,41 @@ const MowingPlanModal = ({ onClose, onCreated }) => { useEffect(() => { const loadSections = async () => { - if (!propertyId) { setSections([]); return; } - try { const r = await propertiesAPI.getById(propertyId); setSections(r.data.data.property.sections || []);} catch { + if (!propertyId) { setSections([]); setSelectedPropertyDetails(null); return; } + try { + const r = await propertiesAPI.getById(propertyId); + const prop = r.data.data.property; + setSelectedPropertyDetails(prop); + setSections(prop.sections || []); + } catch { + setSelectedPropertyDetails(null); setSections([]); } }; loadSections(); }, [propertyId]); + // Map center similar to ApplicationPlanModal + const mapCenter = useMemo(() => { + if (selectedPropertyDetails?.latitude && selectedPropertyDetails?.longitude) { + return [selectedPropertyDetails.latitude, selectedPropertyDetails.longitude]; + } + if (selectedPropertyDetails?.sections?.length > 0) { + let totalLat = 0, totalLng = 0, count = 0; + selectedPropertyDetails.sections.forEach(section => { + let polygonData = section.polygonData; + if (typeof polygonData === 'string') { + try { polygonData = JSON.parse(polygonData); } catch { return; } + } + if (polygonData?.coordinates?.[0]) { + polygonData.coordinates[0].forEach(([lat, lng]) => { totalLat += lat; totalLng += lng; count++; }); + } + }); + if (count > 0) return [totalLat / count, totalLng / count]; + } + return [39.8283, -98.5795]; + }, [selectedPropertyDetails]); + const create = async () => { try { if (!propertyId || lawnSectionIds.length === 0 || !equipmentId) { toast.error('Missing fields'); return; } @@ -56,54 +86,168 @@ const MowingPlanModal = ({ onClose, onCreated }) => { return (
-
-
-

New Mowing Plan

- +
+ {/* Header */} +
+

Plan New Mowing

+
-
-
- - + +
+ {/* Left Column */} +
+ {/* Property */} +
+ + +
+ + {/* Planned Date */} +
+ + setPlannedDate(e.target.value)} + className="w-full border border-gray-300 rounded px-3 py-2" + /> +
+ + {/* Mower */} +
+ + +
+ + {/* Cut height and direction */} +
+
+ + setCutHeightInches(e.target.value)} + className="w-full border border-gray-300 rounded px-3 py-2" + /> +
+
+ + +
+
+ + {/* Notes */} +
+ +