| 12 |
- import{r as t,j as e}from"./react-DnK_pEU5.js";import{d as c,t as r,L as se,B as i,I as z,S as be,k as te,l as ae,m as ne,n as re,K as ie,o as Se,e as le}from"./index-LUV-rsLw.js";import{L as oe}from"./label-CyGXWE6X.js";import{C as y,d as b}from"./card-CF36l7bR.js";import{A as ce,a as de}from"./alert-nibgKJd5.js";import"./dnd-Bgdma8TD.js";import"./motion-8nKk6_RD.js";function me({signal:n}){const E=n>=75?"signal_wifi_4_bar":n>=50?"network_wifi_3_bar":n>=25?"network_wifi_2_bar":"network_wifi_1_bar",d=n>=50?"text-green-500":n>=25?"text-yellow-500":"text-red-500";return e.jsx("span",{className:`material-icons text-lg ${d}`,"aria-hidden":"true",children:E})}function Ee(){const[n,E]=t.useState(null),[d,xe]=t.useState([]),[W,he]=t.useState([]),[l,I]=t.useState(null),[m,S]=t.useState(""),[k,C]=t.useState(!1),[F,L]=t.useState(!1),[h,M]=t.useState(!1),[_,B]=t.useState(!1),[x,K]=t.useState(!1),[j,T]=t.useState(""),[u,P]=t.useState(null),[H,Y]=t.useState(""),[o,q]=t.useState(""),[D,ue]=t.useState(!1),[G,J]=t.useState(!1),[Q,p]=t.useState(null),[A,U]=t.useState("idle"),O=t.useCallback(async()=>{try{const s=await c.get("/api/wifi/status");E(s)}catch{}},[]),w=t.useCallback(async()=>{try{const s=await c.get("/api/wifi/saved");he(s)}catch{}},[]),V=t.useCallback(async()=>{try{const s=await c.get("/api/wifi/hotspot/password");Y(s.password),q(s.password)}catch{}},[]),N=t.useCallback(async()=>{L(!0);try{const s=await c.get("/api/wifi/networks");xe(s)}catch{r.error("Failed to scan networks")}finally{L(!1)}},[]);t.useEffect(()=>{O(),N(),w(),V()},[O,N,w,V]),t.useEffect(()=>{if(A!=="restarting")return;let s=!1,a;const g=async()=>{try{if((await fetch("/api/wifi/status")).ok&&!s){window.location.reload();return}}catch{}s||(a=setTimeout(g,3e3))};return a=setTimeout(g,5e3),()=>{s=!0,clearTimeout(a)}},[A]);const v=x||l&&l.security!=="Open"&&!l.saved,f=n?.mode==="hotspot",$=async()=>{const s=x?j.trim():l?.ssid;if(s){M(!0);try{const a=await c.post("/api/wifi/connect",{ssid:s,password:v?m:""});a.success?(r.success(a.message),R(),O(),w(),N()):r.error(a.message||"Failed to connect to network")}catch(a){const g=!(a instanceof Error)||!a.message.startsWith("HTTP");if(f&&g)r.info("If the hotspot dropped, the table is connecting to your WiFi — rejoin your network and reload.");else{const ee=a instanceof Error?a.message:"Connection failed";r.error(ee)}}finally{M(!1)}}},pe=async()=>{const s=j.trim();if(s){B(!0);try{const a=await c.post("/api/wifi/save",{ssid:s,password:m||""});a.success?(r.success(a.message),R(),w()):r.error(a.message||"Failed to save network")}catch(a){const g=a instanceof Error?a.message:"Failed to save network";r.error(g)}finally{B(!1)}}},fe=async()=>{if(!u)return;const s=u;P(null);try{await c.post("/api/wifi/forget",{ssid:s}),r.success(`Forgot '${s}'`),w(),N()}catch{r.error("Failed to forget network")}},X=u===n?.ssid,ge=W.filter(s=>s.ssid!==u).length,je=X&&ge===0,Z=async()=>{J(!0);try{const s=await c.post("/api/wifi/hotspot/password",{password:o});s.success?(Y(o),r.success(s.message)):r.error(s.message||"Failed to update password")}catch(s){const a=s instanceof Error?s.message:"Failed to update password";r.error(a)}finally{J(!1)}},we=s=>{I(s),S(""),C(!1)},R=()=>{!h&&!_&&(I(null),S(""),C(!1),K(!1),T(""))},Ne=()=>{K(!0),T(""),S(""),C(!1),I({ssid:"",signal:0,security:"Manual",saved:!1,active:!1})},ve=async()=>{p(null);try{await c.post("/api/system/restart"),U("restarting")}catch{r.error("Failed to restart")}},ye=async()=>{p(null);try{await c.post("/api/system/shutdown"),U("shutdown")}catch{r.error("Failed to shutdown")}};return e.jsxs("div",{className:"container max-w-lg mx-auto px-3 py-4 space-y-3",children:[f&&e.jsxs(ce,{className:"border-blue-200 bg-blue-50 dark:bg-blue-950/30 dark:border-blue-800",children:[e.jsx("span",{className:"material-icons text-blue-500 mr-2","aria-hidden":"true",children:"wifi_tethering"}),e.jsxs(de,{children:[e.jsx("strong",{children:"Welcome to Dune Weaver!"}),e.jsx("br",{}),"Connect to your home WiFi network below to get started."]})]}),e.jsx(y,{children:e.jsxs(b,{className:"pt-4 pb-3 px-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx("span",{className:"material-icons-outlined text-base text-muted-foreground","aria-hidden":"true",children:"info"}),e.jsx("span",{className:"font-semibold text-sm",children:"WiFi Status"})]}),n?e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-y-1 text-sm",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-x-5 gap-y-1",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"Mode"}),e.jsx(se,{variant:f?"secondary":"default",className:"text-xs px-1.5 py-0",children:n.mode==="hotspot"?"Hotspot":n.mode==="client"?"Connected":n.mode})]}),n.ssid&&e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"Network"}),e.jsx("span",{className:"font-medium text-xs",children:n.ssid})]}),n.ip&&e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"IP"}),e.jsx("span",{className:"font-mono text-xs",children:n.ip})]})]}),e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"Host"}),e.jsxs("span",{className:"font-mono text-xs",children:[n.hostname,".local"]})]})]}):e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading status..."}),!f&&e.jsx("p",{className:"text-xs text-muted-foreground mt-2",children:"WiFi management requires a Raspberry Pi."})]})}),W.length>0&&e.jsx(y,{children:e.jsxs(b,{className:"pt-4 pb-2 px-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx("span",{className:"material-icons-outlined text-base text-muted-foreground","aria-hidden":"true",children:"bookmark"}),e.jsx("span",{className:"font-semibold text-sm",children:"Saved Networks"})]}),e.jsx("div",{className:"space-y-0.5",children:W.map(s=>e.jsxs("div",{className:"flex items-center justify-between px-2.5 py-2 rounded-lg hover:bg-muted/50",children:[e.jsxs("div",{className:"flex items-center gap-2.5",children:[e.jsx("span",{className:"material-icons text-muted-foreground text-lg","aria-hidden":"true",children:"wifi"}),e.jsx("span",{className:"font-medium text-sm",children:s.ssid})]}),e.jsx(i,{variant:"ghost",size:"sm",className:"h-7 w-7 p-0",onClick:()=>P(s.ssid),"aria-label":`Forget network ${s.ssid}`,children:e.jsx("span",{className:"material-icons text-sm text-destructive","aria-hidden":"true",children:"delete"})})]},s.name))})]})}),e.jsx(y,{children:e.jsxs(b,{className:"pt-4 pb-3 px-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx("span",{className:"material-icons-outlined text-base text-muted-foreground","aria-hidden":"true",children:"wifi_tethering"}),e.jsx("span",{className:"font-semibold text-sm",children:"Hotspot Password"}),!H&&e.jsx(se,{variant:"secondary",className:"text-xs px-1.5 py-0",children:"Open"})]}),e.jsx("p",{className:"text-xs text-muted-foreground mb-3",children:"Set a password for the Dune Weaver hotspot. Leave empty for an open network."}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(z,{type:D?"text":"password",value:o,onChange:s=>q(s.target.value),placeholder:"No password (open)","aria-label":"Hotspot password",className:"pr-8 h-8 text-sm",onKeyDown:s=>{s.key==="Enter"&&o!==H&&Z()}}),e.jsx("button",{type:"button",onClick:()=>ue(!D),className:"absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground","aria-label":D?"Hide password":"Show password",children:e.jsx("span",{className:"material-icons text-sm","aria-hidden":"true",children:D?"visibility_off":"visibility"})})]}),e.jsx(i,{size:"sm",className:"h-8",onClick:Z,disabled:G||o===H||o.length>0&&o.length<8,children:G?e.jsx("span",{className:"material-icons text-sm animate-spin","aria-hidden":"true",children:"refresh"}):"Save"})]}),o&&o.length<8&&o.length>0&&e.jsx("p",{className:"text-xs text-destructive mt-1",children:"Password must be at least 8 characters"})]})}),f&&e.jsxs(e.Fragment,{children:[e.jsx(be,{}),e.jsxs("div",{className:"text-center text-sm text-muted-foreground space-y-1",children:[e.jsx("p",{children:"After connecting, access Dune Weaver at:"}),e.jsxs("code",{className:"text-xs bg-muted px-2 py-1 rounded",children:["http://",n?.hostname||"duneweaver",".local"]})]})]}),e.jsx(y,{children:e.jsxs(b,{className:"pt-4 pb-3 px-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx("span",{className:"material-icons-outlined text-base text-muted-foreground","aria-hidden":"true",children:"settings_power"}),e.jsx("span",{className:"font-semibold text-sm",children:"System"})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(i,{variant:"outline",size:"sm",className:"flex-1 h-8",onClick:()=>p("restart"),children:[e.jsx("span",{className:"material-icons-outlined text-sm mr-1.5","aria-hidden":"true",children:"restart_alt"}),"Restart"]}),e.jsxs(i,{variant:"outline",size:"sm",className:"flex-1 h-8 text-destructive hover:text-destructive",onClick:()=>p("shutdown"),children:[e.jsx("span",{className:"material-icons-outlined text-sm mr-1.5","aria-hidden":"true",children:"power_settings_new"}),"Shutdown"]})]})]})}),e.jsx(y,{children:e.jsxs(b,{className:"pt-4 pb-2 px-4",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"material-icons-outlined text-base text-muted-foreground","aria-hidden":"true",children:"wifi_find"}),e.jsx("span",{className:"font-semibold text-sm",children:"Networks"}),e.jsx("span",{className:"text-xs text-muted-foreground",children:d.length>0?`(${d.length})`:""})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(i,{variant:"ghost",size:"sm",className:"h-7 w-7 p-0",onClick:Ne,title:"Add network manually","aria-label":"Add network manually",children:e.jsx("span",{className:"material-icons text-base","aria-hidden":"true",children:"add"})}),e.jsx(i,{variant:"ghost",size:"sm",className:"h-7 w-7 p-0",onClick:N,disabled:F,"aria-label":"Scan for networks",children:e.jsx("span",{className:`material-icons text-base ${F?"animate-spin":""}`,"aria-hidden":"true",children:"refresh"})})]})]}),e.jsxs("div",{className:"space-y-0.5",children:[d.length===0&&F&&e.jsx("p",{className:"text-sm text-muted-foreground text-center py-3",children:"Scanning for networks..."}),d.length===0&&!F&&e.jsx("p",{className:"text-sm text-muted-foreground text-center py-3",children:"No networks found. Try scanning again."}),d.map(s=>e.jsxs("button",{onClick:()=>we(s),className:`w-full flex items-center gap-2.5 px-2.5 py-2 rounded-lg text-left transition-colors hover:bg-muted/50
- ${s.active?"bg-green-50 dark:bg-green-950/20":""}`,children:[e.jsx(me,{signal:s.signal}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"font-medium text-sm truncate",children:s.ssid}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[s.security,s.saved&&" · Saved",s.active&&" · Connected"]})]}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:[s.signal,"%"]}),s.security!=="Open"&&e.jsx("span",{className:"material-icons text-sm text-muted-foreground","aria-hidden":"true",children:"lock"})]},`${s.ssid}-${s.security}-${s.signal}`))]})]})}),e.jsx(te,{open:u!==null,onOpenChange:s=>{s||P(null)},children:e.jsxs(ae,{className:"sm:max-w-md",children:[e.jsxs(ne,{children:[e.jsxs(re,{children:["Forget '",u,"'?"]}),e.jsx(ie,{children:je?e.jsxs(e.Fragment,{children:["This is your only saved network. Forgetting it will start the"," ",e.jsx("strong",{children:"Dune Weaver"})," hotspot. Connect to the Dune Weaver WiFi to access this page again."]}):X?e.jsx(e.Fragment,{children:"You are currently connected to this network. The system will try the next saved network, or start the hotspot if none are in range."}):"The saved credentials for this network will be removed."})]}),e.jsxs(Se,{className:"flex-row gap-2 sm:justify-end",children:[e.jsx(i,{variant:"outline",onClick:()=>P(null),children:"Cancel"}),e.jsx(i,{variant:"destructive",onClick:fe,children:"Forget"})]})]})}),e.jsx(te,{open:l!==null,onOpenChange:s=>{s||R()},children:e.jsxs(ae,{className:"sm:max-w-md",children:[e.jsxs(ne,{children:[e.jsx(re,{className:"flex items-center gap-2",children:x?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"material-icons text-lg text-muted-foreground","aria-hidden":"true",children:"add_circle_outline"}),"Add Network"]}):e.jsxs(e.Fragment,{children:[l&&e.jsx(me,{signal:l.signal}),l?.ssid]})}),e.jsx(ie,{children:x?"Enter the network name and password":e.jsxs(e.Fragment,{children:[l?.security!=="Open"?"Secured network":"Open network",l?.saved&&" · Saved"]})})]}),e.jsxs("div",{className:"space-y-4",children:[f&&e.jsxs(ce,{children:[e.jsx("span",{className:"material-icons text-base","aria-hidden":"true",children:"wifi_off"}),e.jsxs(de,{children:["Connecting will turn off the table's hotspot. Rejoin your home WiFi, then open"," ","http://",n?.hostname||"<hostname>",".local"]})]}),x&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(oe,{htmlFor:"wifi-ssid",children:"Network Name (SSID)"}),e.jsx(z,{id:"wifi-ssid",type:"text",value:j,onChange:s=>T(s.target.value),placeholder:"Enter network name",autoFocus:!0})]}),v&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(oe,{htmlFor:"wifi-password",children:"Password"}),e.jsxs("div",{className:"relative",children:[e.jsx(z,{id:"wifi-password",type:k?"text":"password",value:m,onChange:s=>S(s.target.value),placeholder:"Enter WiFi password",autoFocus:!x,onKeyDown:s=>{s.key==="Enter"&&m&&$()}}),e.jsx("button",{type:"button",onClick:()=>C(!k),className:"absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground","aria-label":k?"Hide password":"Show password",children:e.jsx("span",{className:"material-icons text-sm","aria-hidden":"true",children:k?"visibility_off":"visibility"})})]})]}),x?e.jsxs("div",{className:"flex gap-2",children:[e.jsx(i,{variant:"outline",className:"flex-1",onClick:pe,disabled:_||h||!j.trim()||!!v&&!m,children:_?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"material-icons text-sm animate-spin mr-2","aria-hidden":"true",children:"refresh"}),"Saving..."]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"material-icons text-sm mr-2","aria-hidden":"true",children:"bookmark_add"}),"Save"]})}),e.jsx(i,{className:"flex-1",onClick:$,disabled:h||_||!j.trim()||!!v&&!m,children:h?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"material-icons text-sm animate-spin mr-2","aria-hidden":"true",children:"refresh"}),"Connecting..."]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"material-icons text-sm mr-2","aria-hidden":"true",children:"wifi"}),"Connect"]})})]}):e.jsx(i,{className:"w-full",onClick:$,disabled:h||!!v&&!m,children:h?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"material-icons text-sm animate-spin mr-2","aria-hidden":"true",children:"refresh"}),"Connecting..."]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"material-icons text-sm mr-2","aria-hidden":"true",children:"wifi"}),"Connect"]})})]})]})}),e.jsx(le,{open:Q==="restart",onOpenChange:s=>{s||p(null)},title:"Restart the system?",description:"The table will be unavailable for a minute or two while it reboots.",confirmLabel:"Restart",destructive:!0,onConfirm:ve}),e.jsx(le,{open:Q==="shutdown",onOpenChange:s=>{s||p(null)},title:"Shut down the system?",description:"The table will power off. You'll need to physically unplug and replug it (or use its power switch) to turn it back on.",confirmLabel:"Shut down",destructive:!0,onConfirm:ye}),A!=="idle"&&e.jsx("div",{className:"fixed inset-0 z-50 flex flex-col items-center justify-center gap-3 bg-background/95 px-6 text-center",role:"status",children:A==="restarting"?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"material-icons text-3xl text-muted-foreground animate-spin","aria-hidden":"true",children:"refresh"}),e.jsx("p",{className:"text-sm font-medium",children:"Restarting — waiting for the table to come back…"})]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"material-icons-outlined text-3xl text-muted-foreground","aria-hidden":"true",children:"power_settings_new"}),e.jsx("p",{className:"text-sm font-medium",children:"The system is shutting down. You can close this page."})]})})]})}export{Ee as WiFiSetupPage};
|