1import{q as R,bB as B,r as w,bC as H,bD as O,j as e,C as g,d as b,e as v,bx as U,B as p,bE as M,l as k,f,c as N,aj as F,b0 as z,bF as E,af as A,M as q,g as L,P as y,a4 as G,bG as J,aw as K,aT as W,bH as V,a8 as Y,aJ as Q,bI as _,bJ as X,ac as Z,a7 as ee,bK as se,aU as S,b9 as ae,bL as te,bM as re,bN as le,bO as ne,bP as ie,bQ as ce,aq as oe,bR as de,S as me,a6 as xe,ay as he,L as pe,T as ue,ax as ge,bv as fe,F as je,bS as Ne}from"./index-FGpVx5RF.js";import{A as be}from"./arrow-left-D4A3Ci2E.js";/** 2 * @license lucide-react v0.462.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const ve=R("Rocket",[["path",{d:"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z",key:"m3kijz"}],["path",{d:"m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z",key:"1fmvmk"}],["path",{d:"M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0",key:"1f8sc4"}],["path",{d:"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5",key:"qeys4"}]]);/** 7 * @license lucide-react v0.462.0 - ISC 8 * 9 * This source code is licensed under the ISC license. 10 * See the LICENSE file in the root directory of this source tree. 11 */const we=R("Users",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["path",{d:"M16 3.13a4 4 0 0 1 0 7.75",key:"1da9ce"}]]),ye={VFR:"bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 border-emerald-500/30",MVFR:"bg-sky-500/15 text-sky-600 dark:text-sky-400 border-sky-500/30",IFR:"bg-red-500/15 text-red-600 dark:text-red-400 border-red-500/30",LIFR:"bg-purple-500/15 text-purple-600 dark:text-purple-400 border-purple-500/30"},ke=a=>!a||a.windSpeed===void 0?"â":`${a.windDirection===void 0?"VRB":`${String(a.windDirection).padStart(3,"0")}°`} ${a.windSpeed}kt${a.windGust?` G${a.windGust}`:""}`,Ce=({favorites:a,onRemove:r})=>{const{metars:i,isLoading:n,refresh:l}=B(a),[t,x]=w.useState({});return w.useEffect(()=>{let c=!1;const s=a.filter(d=>t[d]===void 0);if(s.length!==0)return(async()=>{const d={};for(const h of s.slice(0,12)){let j="";try{const m=await H(h)??await O(h);m&&(j=m.city?`${m.name} · ${m.city}`:m.name)}catch{}d[h]=j}c||x(h=>({...h,...d}))})(),()=>{c=!0}},[a]),e.jsxs(g,{className:"h-full",children:[e.jsxs(b,{className:"pb-3 flex-row items-center justify-between space-y-0",children:[e.jsxs(v,{className:"text-base flex items-center gap-2",children:[e.jsx(U,{className:"h-4 w-4 text-primary"}),"Favourite airports & live weather"]}),e.jsx(p,{variant:"ghost",size:"sm",onClick:l,disabled:n||a.length===0,children:e.jsx(M,{className:k("h-4 w-4",n&&"animate-spin")})})]}),e.jsxs(f,{className:"space-y-2",children:[a.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:"Star airports in the planner or the airport directory and they will appear here with live weather."}),a.map(c=>{const s=i[c],d=s==null?void 0:s.flightCategory;return e.jsxs("div",{className:"rounded-lg border p-3 space-y-1.5",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-mono font-semibold text-sm",children:c}),d&&e.jsx(N,{variant:"outline",className:k("text-xs",ye[d]),children:d}),e.jsx("button",{onClick:()=>r(c),className:"ml-auto text-muted-foreground hover:text-foreground",title:`Remove ${c} from favourites`,children:e.jsx(F,{className:"h-4 w-4 fill-current"})})]}),t[c]!==""&&e.jsx("p",{className:"text-xs text-muted-foreground truncate",children:t[c]??"Loading airport detailsâ¦"}),e.jsxs("div",{className:"flex flex-wrap gap-x-4 gap-y-1 text-xs font-mono",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(z,{className:"h-3 w-3"}),ke(s)]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(E,{className:"h-3 w-3"}),(s==null?void 0:s.temperature)!==void 0?`${s.temperature}°C`:"â"]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(A,{className:"h-3 w-3"}),(s==null?void 0:s.altimeter)!==void 0?`${s.altimeter.toFixed(2)}"`:"â"]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(q,{className:"h-3 w-3"}),(s==null?void 0:s.clouds)??"â"]}
11)]}),(s==null?void 0:s.raw)&&e.jsx("p",{className:"text-[11px] font-mono text-muted-foreground break-words",children:s.raw}),!s&&!n&&e.jsx("p",{className:"text-[11px] text-muted-foreground",children:"No current report available."})]},c)})]})]})},Se=({recentRoutes:a,savedPlans:r,onDispatch:i,onDeleteSaved:n,onClearRecent:l})=>e.jsxs(g,{className:"h-full",children:[e.jsx(b,{className:"pb-3",children:e.jsxs(v,{className:"text-base flex items-center gap-2",children:[e.jsx(ve,{className:"h-4 w-4 text-primary"}),"Quick dispatch"]})}),e.jsxs(f,{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("h3",{className:"text-xs font-semibold uppercase tracking-wide text-muted-foreground flex items-center gap-1",children:[e.jsx(L,{className:"h-3.5 w-3.5"})," Recent routes"]}),a.length>0&&e.jsx(p,{variant:"ghost",size:"sm",className:"h-7 text-xs",onClick:l,children:"Clear"})]}),a.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:"Routes you build in the planner show up here."}),a.map(t=>e.jsxs("div",{className:"flex items-center gap-2 rounded-lg border p-2.5",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("p",{className:"text-sm font-mono font-semibold",children:[t.depIcao," â ",t.arrIcao]}),e.jsxs("p",{className:"text-xs text-muted-foreground truncate",children:[Math.round(t.distance)," NM",t.aircraft?` · ${t.aircraft}`:""]})]}),e.jsxs(p,{size:"sm",variant:"secondary",onClick:()=>i(t.flightPlan),children:[e.jsx(y,{className:"h-3.5 w-3.5 mr-1"})," Fly"]})]},t.id))]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("h3",{className:"text-xs font-semibold uppercase tracking-wide text-muted-foreground flex items-center gap-1",children:[e.jsx(G,{className:"h-3.5 w-3.5"})," Saved plans",r.length>0&&e.jsx(N,{variant:"secondary",className:"text-xs ml-1",children:r.length})]}),r.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:"Save a plan in the planner to keep it here."}),r.slice(0,8).map(t=>{var x,c,s,d;return e.jsxs("div",{className:"flex items-center gap-2 rounded-lg border p-2.5",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:t.name}),e.jsxs("p",{className:"text-xs text-muted-foreground font-mono",children:[((c=(x=t.flightPlan.departure)==null?void 0:x.airport)==null?void 0:c.icao)??"----"," â ",((d=(s=t.flightPlan.arrival)==null?void 0:s.airport)==null?void 0:d.icao)??"----"," · ",Math.round(t.flightPlan.totalDistance)," NM"]})]}),e.jsxs(p,{size:"sm",variant:"secondary",onClick:()=>i(t.flightPlan),children:[e.jsx(y,{className:"h-3.5 w-3.5 mr-1"})," Fly"]}),e.jsx(p,{size:"icon",variant:"ghost",className:"h-8 w-8",onClick:()=>n(t.id),title:"Delete plan",children:e.jsx(J,{className:"h-3.5 w-3.5"})})]},t.id)})]})]})]}),Re=["vatsim","ivao"],Me=(a,r)=>{const i=a.toUpperCase(),n=r.toUpperCase();return!!(i.startsWith(n)||n.length===4&&/^[KPC]/.test(n)&&i.startsWith(n.slice(1)))},Fe=({favorites:a,controllers:r,pilots:i,enabledNetworks:n,loading:l,onToggleNetwork:t,onRefetch:x})=>{const c=n.length>0;return e.jsxs(g,{className:"h-full",children:[e.jsxs(b,{className:"pb-3 flex-row items-center justify-between space-y-0",children:[e.jsxs(v,{className:"text-base flex items-center gap-2",children:[e.jsx(K,{className:"h-4 w-4 text-primary"}),"Live ATC at your airports"]}),e.jsx(p,{variant:"ghost",size:"sm",onClick:x,disabled:l||!c,children:e.jsx(M,{className:k("h-4 w-4",l&&"animate-spin")})})]}),e.jsxs(f,{className:"space-y-3",children:[e.jsx("div",{className:"flex flex-wrap gap-4",children:Re.map(s=>e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx(W,{checked:n.includes(s),onCheckedChange:()=>t(s)}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(Y,{className:"h-3.5 w-3.5"}),V[s]]})]},s))}),!c&&e.jsx("p",{className:"text-sm text-muted-foreground",children:"Turn on a network above to see which of your airports have controllers online right now."}),c&&a.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:"Star some airports to wat
11ch their online coverage."}),c&&a.map(s=>{const d=r.filter(m=>Me(m.callsign,s)),h=i.filter(m=>{var u;return((u=m.arrival)==null?void 0:u.toUpperCase())===s.toUpperCase()}).length,j=i.filter(m=>{var u;return((u=m.departure)==null?void 0:u.toUpperCase())===s.toUpperCase()}).length;return e.jsxs("div",{className:"rounded-lg border p-3 space-y-1.5",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-mono font-semibold text-sm",children:s}),d.length===0?e.jsx(N,{variant:"outline",className:"text-xs",children:"Unicom 122.800"}):e.jsxs(N,{variant:"outline",className:"text-xs bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 border-emerald-500/30",children:[d.length," online"]}),e.jsxs("span",{className:"ml-auto text-xs text-muted-foreground flex items-center gap-1",children:[e.jsx(we,{className:"h-3 w-3"}),j," out · ",h," in"]})]}),d.length>0&&e.jsx("ul",{className:"space-y-0.5",children:d.slice(0,6).map(m=>e.jsxs("li",{className:"text-xs font-mono flex items-center justify-between",children:[e.jsx("span",{children:m.callsign}),e.jsx("span",{className:"text-muted-foreground",children:m.frequency})]},m.id))})]},s)})]})]})},Ae=({itineraries:a,onDispatch:r})=>e.jsxs(g,{className:"h-full",children:[e.jsx(b,{className:"pb-3",children:e.jsxs(v,{className:"text-base flex items-center gap-2",children:[e.jsx(Q,{className:"h-4 w-4 text-primary"}),"Tours & upcoming legs"]})}),e.jsxs(f,{className:"space-y-2",children:[a.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:"Build a multi-leg tour in the planner and your next leg will be waiting here."}),a.map(i=>{var t,x,c,s;const n=_(i),l=[...i.legs].sort((d,h)=>d.order-h.order)[0];return e.jsxs("div",{className:"rounded-lg border p-3 space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:i.name}),e.jsxs(N,{variant:"secondary",className:"text-xs ml-auto",children:[n.legCount," legs"]})]}),e.jsxs("p",{className:"text-xs text-muted-foreground font-mono",children:[Math.round(n.totalDistance)," NM total · ",n.airports.length," airports"]}),l&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("p",{className:"text-xs font-mono flex-1",children:["Next: ",((x=(t=l.flightPlan.departure)==null?void 0:t.airport)==null?void 0:x.icao)??"----"," â ",((s=(c=l.flightPlan.arrival)==null?void 0:c.airport)==null?void 0:s.icao)??"----"]}),e.jsxs(p,{size:"sm",variant:"secondary",onClick:()=>r(l.flightPlan),children:[e.jsx(y,{className:"h-3.5 w-3.5 mr-1"})," Fly leg"]})]})]},i.id)})]})]}),P=["favorite-airports","sfp-recent-routes","msfs-saved-flight-plans","msfs-flight-log","sfp-itineraries","sfp-recent-airports","sfp-recent-aircraft","msfs-quick-plan-templates","msfs-user-preferences","custom-aircraft","custom-airports","msfs-online-networks-enabled"];function Le(){const a={};for(const t of P){const x=localStorage.getItem(t);x!==null&&(a[t]=x)}const r={app:"simple-flight-planner",version:1,exportedAt:new Date().toISOString(),data:a},i=new Blob([JSON.stringify(r,null,2)],{type:"application/json"}),n=URL.createObjectURL(i),l=document.createElement("a");l.href=n,l.download=`simple-flight-planner-backup-${new Date().toISOString().slice(0,10)}.json`,document.body.appendChild(l),l.click(),l.remove(),URL.revokeObjectURL(n)}async function Pe(a){let r;try{r=JSON.parse(await a.text())}catch{return{restored:0,error:"That file is not valid JSON."}}if((r==null?void 0:r.app)!=="simple-flight-planner"||typeof r.data!="object"||r.data===null)return{restored:0,error:"That file is not a Simple Flight Planner backup."};let i=0;for(const n of P){const l=r.data[n];if(typeof l=="string"){try{JSON.parse(l)}catch{continue}localStorage.setItem(n,l),i++}}return i===0?{restored:0,error:"The backup contained no recognizable data."}:{restored:i}}function Te(){const a=w.useRef(null),[r,i]=w.useState(!1),n=async l=>{if(!l)return;i(!0);const t=await Pe(l);if(i(!1),t.error){S.error(t.error);return}S.success(`Restored ${t.restored} item${t.restored===1?"":"s"} â reloadingâ¦`),setTimeout(()=>window.location.reload(),900)};return e.jsxs(g,{children:[e.jsxs(b,{children:[e.jsxs(v,{className:"flex items-center gap-2 text-base",children:[e.jsx(X,{className:"h-4 w-4"}),"Back up & restore"]}),e.jsx(Z,{children:"Your hub lives only in this browser. Download a backup file so you can bring everything back after clearing browsing data â or move it to another computer."})]}),e.jsxs(f,{className:"flex flex-wrap gap-2",children:[e.jsxs(p,{variant:"outline",size:"sm",onClick:Le,children:[e.jsx(ee,{className:"mr-2 h-4 w-4"}),"Download backup"]}),e.jsxs(p,{variant:"outline",size:"sm",disabled:r,onClick:()=>{var l;return(l=a.current)==null?void 0:l.click()},children:[e.jsx(se,{className:"mr-2 h-4 w-4"}),r?"Restoringâ¦":"Restore from file"]}),e.jsx("input",{ref:a,type:"file",accept:"application/json,.json",className:"hidden",onChange:l=>{var t;n((t=l.target.files)==null?void 0:t[0]),l.target.value=""}})]})]})}const De=a=>{const r=a/60;return r>=10?`${Math.round(r)}`:r.toFixed(1)},Be=()=>{const a=ae(),{favorites:r,removeFavorite:i}=te(),{recentRoutes:n,clearRecentRoutes:l}=re(),{savedPlans:t,deleteFlightPlan:x}=le(),{flights:c,stats:s}=ne(),{itineraries:d}=ie(),{enabledNetworks:h,loading:j,allPilots:m,allControllers:u,toggleNetwork:T,refetch:D}=ce(),C=o=>{Ne(o),a("/planner")},$=w.useMemo(()=>s.favoriteAircraft.slice(0,2).map(o=>o.name).join(", ")||"â",[s.favoriteAircraft]),I=[{icon:L,label:"Hours flown",value:De(s.totalFlightTime)},{icon:y,label:"Flights logged",value:`${s.totalFlights}`},{icon:A,label:"Nautical miles",value:Math.round(s.totalDistance).toLocaleStr
11ing()},{icon:oe,label:"Airports visited",value:`${s.uniqueAirports}`},{icon:de,label:"Most flown",value:$}];return e.jsxs(e.Fragment,{children:[e.jsx(me,{title:"Pilot Hub",description:"Your personal flight simulation dashboard: favourite airports with live weather, quick-dispatch routes, live VATSIM and IVAO coverage, tours and logbook stats in one place.",canonicalPath:"/hub"}),e.jsxs("div",{className:"min-h-screen bg-background flex flex-col",children:[e.jsx("header",{className:"border-b bg-card/80 backdrop-blur-sm sticky top-0 z-50",children:e.jsxs("div",{className:"container mx-auto px-3 sm:px-4 py-2 sm:py-3 flex items-center gap-3 justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3 min-w-0",children:[e.jsx("img",{src:xe,alt:"Simple Flight Planner",className:"h-9 w-9 rounded-lg shrink-0"}),e.jsxs("div",{className:"min-w-0",children:[e.jsxs("h1",{className:"font-bold text-sm sm:text-lg leading-tight flex items-center gap-2",children:[e.jsx(he,{className:"h-4 w-4 text-primary shrink-0"}),"Pilot Hub"]}),e.jsx("p",{className:"text-xs text-muted-foreground hidden sm:block",children:"Everything you fly most, in one place"})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(p,{variant:"outline",size:"sm",asChild:!0,children:e.jsxs(pe,{to:"/planner",children:[e.jsx(be,{className:"h-4 w-4 mr-2"}),"Planner"]})}),e.jsx(ue,{})]})]})}),e.jsxs("main",{className:"flex-1 container mx-auto px-3 sm:px-4 py-4 sm:py-6 space-y-4",children:[e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3",children:I.map(o=>e.jsx(g,{children:e.jsxs(f,{className:"p-3",children:[e.jsxs("p",{className:"text-xs text-muted-foreground flex items-center gap-1",children:[e.jsx(o.icon,{className:"h-3.5 w-3.5"}),o.label]}),e.jsx("p",{className:"text-lg font-semibold truncate mt-0.5",children:o.value})]})},o.label))}),e.jsxs("div",{className:"grid lg:grid-cols-2 gap-4",children:[e.jsx(Ce,{favorites:r,onRemove:i}),e.jsx(Se,{recentRoutes:n,savedPlans:t,onDispatch:C,onDeleteSaved:x,onClearRecent:l})]}),e.jsxs("div",{className:"grid lg:grid-cols-2 gap-4",children:[e.jsx(Fe,{favorites:r,controllers:u,pilots:m,enabledNetworks:h,loading:j,onToggleNetwork:T,onRefetch:D}),e.jsx(Ae,{itineraries:d,onDispatch:C})]}),e.jsxs(g,{children:[e.jsx(b,{className:"pb-3",children:e.jsxs(v,{className:"text-base flex items-center gap-2",children:[e.jsx(ge,{className:"h-4 w-4 text-primary"}),"Recent logbook entries"]})}),e.jsxs(f,{className:"space-y-2",children:[c.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:"Log a flight in the planner and your history will build up here."}),c.slice(0,8).map(o=>e.jsxs("div",{className:"flex flex-wrap items-center gap-2 rounded-lg border p-2.5 text-sm",children:[e.jsxs("span",{className:"font-mono font-semibold",children:[o.departureIcao," â ",o.arrivalIcao]}),e.jsx(N,{variant:"outline",className:"text-xs",children:o.flightType}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:[Math.round(o.distance)," NM · ",Math.round(o.duration)," min",o.aircraft?` · ${o.aircraft.name}`:""]}),e.jsx("span",{className:"ml-auto text-xs text-muted-foreground",children:new Date(o.loggedAt).toLocaleDateString()})]},o.id)),s.favoriteAirports.length>0&&e.jsxs("p",{className:"text-xs text-muted-foreground pt-1 flex items-center gap-1",children:[e.jsx(F,{className:"h-3.5 w-3.5"}),"Most visited: ",s.favoriteAirports.slice(0,3).map(o=>`${o.icao} (${o.visits})`).join(" · ")]})]})]}),e.jsx(Te,{}),e.jsxs("p",{className:"text-xs text-muted-foreground flex items-center gap-1.5",children:[e.jsx(fe,{className:"h-3.5 w-3.5 shrink-0"}),"Everything on this page is stored only in this browser â no account, no cloud copy. Clearing your browser data clears your hub."]})]}),e.jsx(je,{})]})]})};export{Be as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.