2 lines
16 KiB
JavaScript
2 lines
16 KiB
JavaScript
import{r as s,j as e,C as fe,o as le,b as de,B as ue,p as te,t as ye,z as P,m as H,Q as je,S as Ne,U as ve,V as be,W as we,X as Se,L as Me,v as _e,J as ke}from"./index-9FS9bw8D.js";import{F as Ce,a as Pe}from"./PlayIcon-CoXqSH0y.js";const Ie=[{value:"N_S",label:"North to South"},{value:"E_W",label:"East to West"},{value:"NE_SW",label:"NE to SW"},{value:"NW_SE",label:"NW to SE"},{value:"CIRCULAR",label:"Circular"}],Le=({onClose:a,onCreated:q})=>{const[T,b]=s.useState([]),[$,O]=s.useState([]),[F,A]=s.useState([]),[r,y]=s.useState(null),[w,B]=s.useState(""),[g,j]=s.useState([]),[n,p]=s.useState(""),[S,M]=s.useState(new Date().toISOString().slice(0,10)),[R,V]=s.useState(3),[G,L]=s.useState("N_S"),[U,J]=s.useState("");s.useEffect(()=>{(async()=>{try{const[l,o]=await Promise.all([te.getAll(),ye.getAll()]);b(l.data.data.properties||[]);const h=(o.data.data.equipment||[]).filter(D=>(D.categoryName||"").toLowerCase().includes("mower"));O(h)}catch{P.error("Failed to load data")}})()},[]),s.useEffect(()=>{(async()=>{if(!w){A([]),y(null);return}try{const o=(await te.getById(w)).data.data.property;y(o),A(o.sections||[])}catch{y(null),A([])}})()},[w]);const se=s.useMemo(()=>{var t;if(r!=null&&r.latitude&&(r!=null&&r.longitude))return[r.latitude,r.longitude];if(((t=r==null?void 0:r.sections)==null?void 0:t.length)>0){let l=0,o=0,h=0;if(r.sections.forEach(D=>{var Q;let N=D.polygonData;if(typeof N=="string")try{N=JSON.parse(N)}catch{return}(Q=N==null?void 0:N.coordinates)!=null&&Q[0]&&N.coordinates[0].forEach(([ae,X])=>{l+=ae,o+=X,h++})}),h>0)return[l/h,o/h]}return[39.8283,-98.5795]},[r]),K=async()=>{var t,l;try{if(!w||g.length===0||!n){P.error("Missing fields");return}await H.createPlan({propertyId:Number(w),lawnSectionIds:g.map(Number),equipmentId:Number(n),plannedDate:S,cutHeightInches:Number(R),direction:G,notes:U}),P.success("Mowing plan created"),q==null||q(),a()}catch(o){P.error(((l=(t=o.response)==null?void 0:t.data)==null?void 0:l.message)||"Failed to create plan")}};return e.jsx("div",{className:"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50",children:e.jsxs("div",{className:"bg-white rounded-lg p-6 w-full max-w-6xl mx-4 max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h2",{className:"text-2xl font-bold text-gray-900",children:"Plan New Mowing"}),e.jsx("button",{onClick:a,className:"text-gray-400 hover:text-gray-600",children:e.jsx(fe,{className:"h-6 w-6"})})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6",children:[e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:[e.jsx(le,{className:"h-4 w-4 inline mr-1"}),"Property"]}),e.jsxs("select",{value:w,onChange:t=>{B(t.target.value),j([])},className:"w-full border border-gray-300 rounded px-3 py-2",children:[e.jsx("option",{value:"",children:"Select a property"}),T.map(t=>e.jsxs("option",{value:t.id,children:[t.name," ",t.address?`- ${t.address}`:""]},t.id))]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Planned Date"}),e.jsx("input",{type:"date",value:S,onChange:t=>M(t.target.value),className:"w-full border border-gray-300 rounded px-3 py-2"})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:[e.jsx(de,{className:"h-4 w-4 inline mr-1"}),"Mower"]}),e.jsxs("select",{value:n,onChange:t=>p(t.target.value),className:"w-full border border-gray-300 rounded px-3 py-2",children:[e.jsx("option",{value:"",children:"Select mower"}),$.map(t=>e.jsxs("option",{value:t.id,children:[t.customName||t.manufacturer||"Mower"," ",t.model||""]},t.id))]})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Cut Height (in)"}),e.jsx("input",{type:"number",step:"0.25",value:R,onChange:t=>V(t.target.value),className:"w-full border border-gray-300 rounded px-3 py-2"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Direction"}),e.jsx("select",{value:G,onChange:t=>L(t.target.value),className:"w-full border border-gray-300 rounded px-3 py-2",children:Ie.map(t=>e.jsx("option",{value:t.value,children:t.label},t.value))})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:"Notes (Optional)"}),e.jsx("textarea",{rows:3,value:U,onChange:t=>J(t.target.value),className:"w-full border border-gray-300 rounded px-3 py-2",placeholder:"Add any notes or special instructions..."})]})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"border rounded-lg p-4 bg-gray-50",children:[e.jsx("h4",{className:"font-medium text-gray-900 mb-3",children:"Select Areas to Mow"}),F.length>0?e.jsx("div",{className:"space-y-2 max-h-40 overflow-auto pr-1",children:F.map(t=>e.jsxs("label",{className:"flex items-center text-sm",children:[e.jsx("input",{type:"checkbox",className:"mr-2",checked:g.includes(t.id.toString())||g.includes(t.id),onChange:l=>{const o=t.id.toString();j(h=>l.target.checked?[...h,o]:h.filter(D=>D.toString()!==o))}}),t.name," ",t.area?`(${Number(t.area).toLocaleString()} sq ft)`:""]},t.id))}):e.jsx("p",{className:"text-sm text-gray-500",children:"Select a property to view areas"})]}),e.jsxs("div",{children:[e.jsx("h4",{className:"font-medium text-gray-900 mb-2",children:"Property Map"}),e.jsx("div",{className:"h-72",children:w?e.jsx(ue,{center:se,zoom:16,property:r,sections:(r==null?void 0:r.sections)||[],selectedSections:g.map(Number),onSectionClick:t=>{j(l=>{const o=t.id.toString();return l.includes(o)?l.filter(h=>h!==o):[...l,o]})},editable:!1,className:"h-72 w-full"}):e.jsx("div",{className:"h-full w-full flex items-center justify-center bg-gray-100 rounded",children:e.jsx("p",{className:"text-gray-500",children:"Select a property to view areas"})})})]})]})]}),e.jsxs("div",{className:"flex justify-end gap-3 mt-6 pt-6 border-t",children:[e.jsx("button",{className:"px-4 py-2 text-gray-600 hover:text-gray-800",onClick:a,children:"Cancel"}),e.jsx("button",{className:"px-6 py-2 bg-blue-600 text-white rounded hover:bg-blue-700",onClick:K,children:"Create Plan"})]})]})})},De=({plan:a,onClose:q,onComplete:T})=>{const[b,$]=s.useState([]),[O,F]=s.useState(!1),[A,r]=s.useState(!1),[y,w]=s.useState([]),[B,g]=s.useState(null),[j,n]=s.useState(null),[p,S]=s.useState(0),[M,R]=s.useState(null),[V,G]=s.useState(null),[L,U]=s.useState(null),[J,se]=s.useState(0),K=s.useRef(0),[t,l]=s.useState(0),[o,h]=s.useState(null),D=s.useRef(null);s.useEffect(()=>{const c=async()=>{var v,x,u,i,_,m;try{const C=(await H.getPlan(a.id)).data.data.sections||[];if($(C),!C.length&&a.property_id){const I=((u=(x=(v=(await te.getById(a.property_id)).data)==null?void 0:v.data)==null?void 0:x.property)==null?void 0:u.sections)||[];$(I),d(I)}else d(C)}catch{try{if(a.property_id){const E=((m=(_=(i=(await te.getById(a.property_id)).data)==null?void 0:i.data)==null?void 0:_.property)==null?void 0:m.sections)||[];$(E),d(E)}}catch{}}},d=v=>{let x=0,u=0,i=0;v.forEach(_=>{var k;let m=_.polygonData||_.polygon_data;if(typeof m=="string")try{m=JSON.parse(m)}catch{return}(k=m==null?void 0:m.coordinates)!=null&&k[0]&&m.coordinates[0].forEach(([C,E])=>{x+=C,u+=E,i++})}),g(i?[x/i,u/i]:null)};c()},[a==null?void 0:a.id,a==null?void 0:a.property_id]);const N=c=>c*Math.PI/180,Q=(c,d)=>{const x=N(d.lat-c.lat),u=N(d.lng-c.lng),i=Math.sin(x/2)**2+Math.cos(N(c.lat))*Math.cos(N(d.lat))*Math.sin(u/2)**2;return 2*6371e3*Math.atan2(Math.sqrt(i),Math.sqrt(1-i))},ae=async()=>{try{"wakeLock"in navigator&&(D.current=await navigator.wakeLock.request("screen"))}catch{}},X=async()=>{var c;try{await((c=D.current)==null?void 0:c.release())}catch{}D.current=null},me=()=>{if(!navigator.geolocation){P.error("GPS not available");return}ae(),F(!0),r(!1),L||U(new Date),R(null),G(null);const c=navigator.geolocation.watchPosition(d=>{const{latitude:v,longitude:x,accuracy:u,speed:i}=d.coords,_=new Date(d.timestamp),m={lat:v,lng:x,accuracy:u,timestamp:_.toISOString(),speed:i||0};if(n({lat:v,lng:x,accuracy:u}),M&&V){const k=Q(M,m),C=(_-V)/1e3;if(C>0){const E=k/C*2.237;S(E);const I=K.current+k;K.current=I,se(I);const W=L?(_-L)/1e3:0;W>0&&l(I/W*2.237)}}R({lat:v,lng:x}),G(_),w(k=>[...k,m])},d=>P.error("GPS error: "+d.message),{enableHighAccuracy:!0,timeout:5e3,maximumAge:1e3});h(c)},ne=()=>{o&&navigator.geolocation.clearWatch(o),h(null),F(!1),r(!0),X()},re=async({requireGps:c,notes:d})=>{var v,x;if(c&&y.length===0){P.error("No GPS tracking data was collected. Please ensure location services are enabled.");return}ne();try{const u=L?Math.round((new Date-L)/1e3):0;let i=null;const _=(a.cutting_width_inches||a.cut_height_inches,null);try{const W=je(y.map(Z=>[Z.lng,Z.lat])),Y=(a.equipment_cut_width_inches||0)/12/2*.3048/1e3;if(Y>0){const Z=Ne(W,Y,{units:"kilometers"}),ce=b.map(ee=>{var ie;let f=ee.polygonData;if(typeof f=="string")try{f=JSON.parse(f)}catch{return null}if(!((ie=f==null?void 0:f.coordinates)!=null&&ie[0]))return null;const z=f.coordinates[0].map(([ge,pe])=>[pe,ge]);return ve([z])}).filter(Boolean);if(ce.length){const ee=ce.reduce((f,z)=>f?be(f,z):z,null);if(ee){const f=we(Z,ee);if(f){const z=Se(f);i=Math.round(z/.092903)}}}}}catch{}const m=b.reduce((W,Y)=>W+(parseFloat(Y.area)||0),0),k=c?{points:y,totalDistance:Math.round(J*100)/100,duration:u,averageSpeed:Math.round(t*100)/100}:{points:[],totalDistance:0,duration:Math.max(u,1),averageSpeed:0},C=c?Math.max(Math.round(J*100)/100,.01):.01,E=c?Math.max(t,.1):.1,I={propertyId:a.property_id,lawnSectionIds:b.map(W=>W.id),equipmentId:a.equipment_id,cutHeightInches:a.cut_height_inches,direction:a.direction,gpsTrack:k,averageSpeed:E,durationSeconds:Math.max(u,1),totalDistanceMeters:C,notes:d};typeof i=="number"&&!Number.isNaN(i)&&i>0?I.areaCoveredSqft=i:!c&&m>0&&(I.areaCoveredSqft=Math.round(m)),await H.createLog(I),await H.updatePlanStatus(a.id,"completed"),P.success("Mowing session saved"),T==null||T(),q()}catch(u){P.error(((x=(v=u.response)==null?void 0:v.data)==null?void 0:x.message)||"Failed to save session")}},he=async()=>re({requireGps:!0,notes:""}),xe=async()=>re({requireGps:!1,notes:`Mowing completed without GPS tracking. Assumed full planned coverage for ${Math.round(b.reduce((c,d)=>c+(parseFloat(d.area)||0),0)).toLocaleString()} sq ft.`});s.useEffect(()=>()=>{o&&navigator.geolocation.clearWatch(o),X()},[o]);const oe=B;return e.jsx("div",{className:"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50",children:e.jsxs("div",{className:"bg-white rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-4",children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Execute Mowing"}),e.jsx("button",{onClick:q,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),e.jsxs("div",{className:"grid grid-cols-5 gap-4 text-sm mb-2",children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Property:"})," ",a.property_name]}),e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Areas:"})," ",a.section_names]}),e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Mower:"})," ",a.equipment_name]}),e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Cut Height:"})," ",a.cut_height_inches,'"']}),e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Direction:"})," ",a.direction]})]}),e.jsx("div",{className:"text-xs text-gray-600 mb-2",children:"Tip: Follow the dashed purple guideline on the map."}),e.jsx("div",{className:"h-80 border rounded mb-4 overflow-hidden",children:e.jsx(ue,{property:null,sections:b,selectedSections:b.map(c=>c.id),mode:"execution",gpsTrack:y,currentLocation:j,center:oe||[39.8283,-98.5795],zoom:oe?19:15,direction:a.direction,className:"h-80 w-full"})}),e.jsx("div",{className:"flex gap-3 mb-4",children:O?e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"btn-secondary",onClick:ne,children:"Pause"}),e.jsx("button",{className:"btn-primary",onClick:he,children:"Complete"})]}):e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"btn-primary",onClick:me,children:A?"Resume":"Start"}),e.jsx("button",{className:"btn-secondary",onClick:xe,children:"Complete Without GPS"})]})}),e.jsxs("div",{className:"grid grid-cols-4 gap-4 text-sm",children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Points:"})," ",y.length]}),e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Distance:"})," ",(J*3.28084).toFixed(0)," ft"]}),e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Avg Speed:"})," ",t.toFixed(1)," mph"]}),e.jsxs("div",{className:"col-span-4 text-xs text-gray-500",children:["Current: ",p.toFixed(1)," mph ",j!=null&&j.accuracy?`(±${Math.round(j.accuracy)}m)`:""]}),e.jsxs("div",{children:[e.jsx("span",{className:"font-medium",children:"Duration:"})," ",L?Math.round((new Date-L)/6e4):0," min"]})]})]})})},Fe=()=>{const[a,q]=s.useState([]),[T,b]=s.useState(!0),[$,O]=s.useState(!1),[F,A]=s.useState(null),[r,y]=s.useState(null),[w,B]=s.useState([]),g=async()=>{var n,p;try{b(!0);const S=await H.getPlans();q(S.data.data.plans||[]);try{const M=await H.getLogs();B(((p=(n=M.data)==null?void 0:n.data)==null?void 0:p.logs)||[])}catch{}}catch{P.error("Failed to load mowing plans")}finally{b(!1)}};s.useEffect(()=>{g()},[]);const j=s.useMemo(()=>(a||[]).filter(p=>p.status!=="archived").sort((p,S)=>new Date(S.planned_date)-new Date(p.planned_date)),[a]);return T?e.jsx("div",{className:"p-6",children:e.jsx(Me,{})}):e.jsxs("div",{className:"p-6",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h1",{className:"text-2xl font-bold text-gray-900",children:"Mowing"}),e.jsx("button",{className:"btn-primary",onClick:()=>O(!0),children:"New Plan"})]}),e.jsx("div",{className:"space-y-4",children:j.length===0?e.jsx("div",{className:"bg-white rounded-lg shadow p-4 text-gray-600",children:"No mowing plans yet."}):j.map(n=>e.jsx("div",{className:"card",children:e.jsxs("div",{className:"flex justify-between items-start",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-2",children:[e.jsx("h3",{className:"font-semibold text-gray-900",children:n.property_name}),e.jsx("span",{className:`px-2 py-1 text-xs font-medium rounded-full ${n.status==="planned"?"bg-blue-100 text-blue-800":n.status==="completed"?"bg-green-100 text-green-800":n.status==="in_progress"?"bg-yellow-100 text-yellow-800":"bg-gray-100 text-gray-800"}`,children:n.status})]}),e.jsxs("p",{className:"text-sm text-gray-600 mb-1",children:[e.jsx(le,{className:"h-4 w-4 inline mr-1"}),"Areas: ",n.section_names," (",Math.round(n.total_area||0).toLocaleString()," sq ft)"]}),e.jsxs("p",{className:"text-sm text-gray-600 mb-1",children:[e.jsx(de,{className:"h-4 w-4 inline mr-1"}),n.equipment_name||"—"," • Cut Height: ",Number(n.cut_height_inches||0).toFixed(2),'" • Direction: ',n.direction||"—"]}),n.notes&&e.jsxs("p",{className:"text-sm text-gray-500 mt-1 italic",children:['"',n.notes,'"']})]}),e.jsxs("div",{className:"text-right",children:[e.jsx("p",{className:"text-sm font-medium text-gray-900",children:n.planned_date?new Date(n.planned_date).toLocaleDateString():"No date"}),e.jsxs("p",{className:"text-xs text-gray-500",children:["Last updated ",new Date(n.updated_at||n.created_at).toLocaleDateString()]}),e.jsxs("div",{className:"flex gap-2 mt-2 justify-end",children:[e.jsx("button",{className:"p-1 text-indigo-600 hover:text-indigo-800 hover:bg-indigo-50 rounded",title:"View recent session",onClick:()=>{const p=(w||[]).filter(M=>M.property_id===n.property_id);if(!p.length){P.error("No sessions yet for this property");return}const S=[...p].sort((M,R)=>new Date(R.created_at||R.session_date||0)-new Date(M.created_at||M.session_date||0))[0];y(S)},children:e.jsx(_e,{className:"h-4 w-4"})}),n.status==="planned"&&e.jsx("button",{className:"p-1 text-green-600 hover:text-green-800 hover:bg-green-50 rounded",title:"Execute",onClick:()=>A(n),children:e.jsx(Ce,{className:"h-4 w-4"})}),n.status!=="archived"&&e.jsx("button",{className:"p-1 text-gray-600 hover:text-gray-800 hover:bg-gray-50 rounded",title:"Archive",onClick:async()=>{await H.updatePlanStatus(n.id,"archived"),g()},children:e.jsx(Pe,{className:"h-4 w-4"})})]})]})]})},n.id))}),$&&e.jsx(Le,{onClose:()=>O(!1),onCreated:g}),F&&e.jsx(De,{plan:F,onClose:()=>A(null),onComplete:g}),r&&e.jsx(ke,{session:r,onClose:()=>y(null)})]})};export{Fe as default};
|