PageSourceSearch

https://hublnet.com/assets/HublSettingsApp-DnALjr-8.js

js hublnet.com collected 2026-10-09 22:01:47 UTC 25,848 bytes, 26 lines download raw bytes

1import{Z as R,u as I,r as c,c6 as W,j as e,g as p,B as z,t as _,ar as Y,cS as Z,X as N,cT as G,s as v,d as q,cA as A,cB as S,ba as Q,L as C,I as j,f as X,cm as J,P as ee,p as te,q as se,c9 as ae,cU as ne}from"./index-w4jqsJ3r.js";import{j as re,l as ie,q as le,e as L,p as oe,o as de,O as ce,A as me,D as ue,i as he,I as xe,v as pe,w as ge,x as ye,y as be,z as fe}from"./OnlineOrderPrintingSection-DpPCOsxi.js";import{C as je}from"./cake-BTBsFdml.js";import{C as B}from"./calendar-clock-DcMeJY7h.js";import{E as ve}from"./EmailConnectionsPanel-BD2CnvSA.js";import"./starWebPrnt-FtNrJo88.js";import"./cloud-upload-n1IueNFJ.js";import"./scan-line-CYew5XFG.js";import"./scale-oRshuo7V.js";import"./collapsible-CM4R5b-7.js";import"./wifi-CJyXM-uO.js";import"./InfoButton-qxLSLKxK.js";import"./file-pen-line-D9AYeXBW.js";import"./plug-CgTm648T.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 _e=R("ArrowDownAZ",[["path",{d:"m3 16 4 4 4-4",key:"1co6wj"}],["path",{d:"M7 20V4",key:"1yoxec"}],["path",{d:"M20 8h-5",key:"1vsyxs"}],["path",{d:"M15 10V6.5a2.5 2.5 0 0 1 5 0V10",key:"ag13bf"}],["path",{d:"M15 14h5l-5 6h5",key:"ur5jdg"}]]);/**
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 ke=R("Flame",[["path",{d:"M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z",key:"96xj49"}]]);/**
12 * @license lucide-react v0.462.0 - ISC
13 *
14 * This source code is licensed under the ISC license.
15 * See the LICENSE file in the root directory of this source tree.
16 */const we=R("Nfc",[["path",{d:"M6 8.32a7.43 7.43 0 0 1 0 7.36",key:"9iaqei"}],["path",{d:"M9.46 6.21a11.76 11.76 0 0 1 0 11.58",key:"1yha7l"}],["path",{d:"M12.91 4.1a15.91 15.91 0 0 1 .01 15.8",key:"4iu2gk"}],["path",{d:"M16.37 2a20.16 20.16 0 0 1 0 20",key:"sap9u2"}]]);/**
17 * @license lucide-react v0.462.0 - ISC
18 *
19 * This source code is licensed under the ISC license.
20 * See the LICENSE file in the root directory of this source tree.
21 */const Se=R("Settings2",[["path",{d:"M20 7h-9",key:"3s1dr2"}],["path",{d:"M14 17H5",key:"gfn3mx"}],["circle",{cx:"17",cy:"17",r:"3",key:"18b49y"}],["circle",{cx:"7",cy:"7",r:"3",key:"dfmy0x"}]]);/**
22 * @license lucide-react v0.462.0 - ISC
23 *
24 * This source code is licensed under the ISC license.
25 * See the LICENSE file in the root directory of this source tree.
26 */const Ne=R("Timer",[["line",{x1:"10",x2:"14",y1:"2",y2:"2",key:"14vaq8"}],["line",{x1:"12",x2:"15",y1:"14",y2:"11",key:"17fdiu"}],["circle",{cx:"12",cy:"14",r:"8",key:"1e1u0o"}]]),Ce=()=>{const{currentOrg:i}=I(),a=i==null?void 0:i.id,r=a?`pos:customerDisplayMode:${a}`:"pos:customerDisplayMode",[u,b]=c.useState({printer:"disconnected",scanner:"listening",terminal:"disconnected",cashDrawer:"closed"}),[h,s]=c.useState(()=>typeof window>"u"?"upright":localStorage.getItem(r)||"upright"),l=t=>{s(t);try{localStorage.setItem(r,t)}catch{}},[m,T]=c.useState(()=>W()),M=t=>{T(t),G(t)},[o,y]=c.useState(()=>re()),f=t=>{y(t),ge(t)},[k,w]=c.useState(()=>ie()),n=t=>{w(t),ye(t)},[d,x]=c.useState(()=>le()),[g,D]=c.useState(""),H=t=>{x(t),be(t)},O=async()=>{D("Checking this device…");const t=await fe();D(t.available?`Ready — ${t.readerName}`:t.reason||"Not available on this device.")},[V,$]=c.useState(()=>L(a));return c.useEffect(()=>{$(L(a))},[a]),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs(p,{title:"Scanner & Hardware",sectionKey:"hubl-settings-register-hardware",children:[e.jsx(oe,{hardware:u,onStatusChange:b}),e.jsxs("div",{className:"mt-3 flex flex-wrap items-center gap-2",children:[e.jsx(z,{variant:"outline",size:"sm",onClick:async()=>{const t=await de(a);t.ok?_.success(t.message):_.error(t.message)},children:"Reconnect USB devices"}),e.jsx("span",{className:"text-xs text-muted-foreground",children:"Use when the hub stops recognizing the printer, reader or drawer."})]})]}),e.jsx(p,{title:"Online Orders & Receipt Printing",sectionKey:"hubl-settings-register-online-orders",children:e.jsx(ce,{})}),e.jsx(p,{title:"Card Terminal Pairing (VP3350)",sectionKey:"hubl-settings-register-terminal",children:e.jsx(me,{})}),e.jsx(p,{title:"Donation Round-Up Siren",sectionKey:"hubl-settings-register-siren",children:e.jsx(ue,{})}),e.jsxs(p,{title:"Customer Checkout View",sectionKey:"hubl-settings-register-display",children:[e.jsx("p",{className:"text-sm text-muted-foreground mb-3",children:"Choose how the customer-facing checkout review appears during a sale."}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3",children:[{id:"upright",title:"Same Screen, Upright (Default)",desc:"Same screen, normal orientation — good for a shared monitor or kiosk facing both ways."},{id:"flipped",title:"Flip Screen",desc:"Same screen, rotated 180° for a counter setup where you flip the device toward the customer."},{id:"second_monitor",title:"Second Monitor",desc:"Opens the customer checkout in a separate window you can drag onto a second display."}].map(t=>e.jsxs("button",{type:"button",onClick:()=>l(t.id),className:`text-left rounded-xl border p-4 transition-colors ${h===t.id?"border-primary bg-primary/5":"border-border bg-card hover:bg-accent/40"}`,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(Y,{className:`h-4 w-4 ${h===t.id?"text-primary":"text-muted-foreground"}`}),e.jsx("span",{className:"font-semibold text-sm text-foreground",children:t.title})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:t.desc})]},t.id))}),e.jsx("p",{className:"text-sm text-muted-foreground mt-5 mb-3",children:"Card size — how large the customer-facing checkout card (phone number, tip, total) appears on screen."}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3",children:[{id:"small",title:"Small",desc:"Compact card for a small counter tablet."},{id:"medium",title:"Medium",desc:"A step down from the default."},{id:"large",title:"Large (Default)",desc:"Full-width card — current behavior."}].map(t=>e.jsxs("button",{type:"button",onClick:()=>M(t.id),className:`text-left rounded-xl border p-4 transition-colors ${m===t.id?"border-primary bg-primary/5":"border-border bg-card hover:bg-accent/40"}`,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(Z,{className:`h-4 w-4 ${m===t.id?"text-primary":"text-muted-foreground"}`}),e.jsx("span",{className:"font-semibold text-sm text-foreground",children:t.title})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:t.desc})]},t.id))})]}),e.jsxs(p,{title:"Product Tile Order",sectionKey:"hubl-settings-register-sort",children:[e.jsx("p",{className:"text-sm text-muted-foreground mb-3",children:"How products are ordered on the register grid. This is a per-device choice."}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[{id:"alphabetical",title:"Alphabetical",desc:"A–Z by register name.",Icon:_e},{id:"most_used",title:"Most Used First (Default)",desc:"Your most-rung items float to the top; ties stay alphabetical.",Icon:ke}].map(t=>e.jsxs("button",{type:"button",onClick:()=>f(t.id),className:`text-left rounded-xl border p-4 transition-colors ${o===t.id?"border-primary bg-primary/5":"border-border bg-card hover:bg-accent/40"}`,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(t.Icon,{className:`h-4 w-4 ${o===t.id?"text-primary":"text-muted-foreground"}`}),e.jsx("span",{className:"font-semibold text-sm text-foreground",children:t.title})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:t.desc})]},t.id))})]}),e.jsx(p,{title:"Idle Lock & Employee PIN",sectionKey:"hubl-settings-register-idle",children:he(a)?e.jsx("p",{className:"text-sm text-muted-foreground",children:"Idle lock is turned off for this business. Registers here run as unattended in-field kiosks and will never dim or ask for a PIN on idle."}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-sm text-muted-foreground mb-3",children:"How long the register can sit untouched before it dims and asks for an employee PIN. Per device. On kiosk-locked devices the PIN cannot be skipped."}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3",children:xe.map(t=>e.jsxs("button",{type:"button",onClick:()=>n(t.value),className:`text-left rounded-xl border p-4 transition-colors ${k===t.value?"border-primary bg-primary/5":"border-border bg-card hover:bg-accent/40"}`,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(Ne,{className:`h-4 w-4 ${k===t.value?"text-primary":"text-muted-foreground"}`}),e.jsx("span",{className:"font-semibold text-sm text-foreground",children:t.title})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:t.desc})]},t.value))})]})}),e.jsx(p,{title:"Price Rounding",sectionKey:"hubl-settings-register-rounding",children:e.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-xl border border-border bg-card p-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-foreground",children:"Round register prices to $0.25, $0.50 or $1"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Prices round up to the next quarter; prices already on a quarter stay the same. Tax is included in the shown price, so a $2.50 item totals exactly $2.50. Inventory prices are not changed."})]}),e.jsx(N,{checked:V,onCheckedChange:t=>{$(t),pe(a,t)}})]})}),e.jsxs(p,{title:"Tap to Pay on This Device",sectionKey:"hubl-settings-register-taptopay",children:[e.jsx("p",{className:"text-sm text-muted-foreground mb-3",children:"Take contactless cards and phones by tapping them against this device — no separate reader. Requires the HUBLNet Android app with NFC payments enabled; otherwise the register keeps using the paired VP3350."}),e.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-xl border border-border bg-card p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(we,{className:`h-4 w-4 ${d?"text-primary":"text-muted-foreground"}`}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-foreground",children:"Use this device as the card reader"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:g||"Not checked yet on this device."})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(z,{variant:"outline",size:"sm",onClick:O,children:"Check"}),e.jsx(N,{checked:d,onCheckedChange:H})]})]})]})]})},F={announcements_enabled:!1,frequency:"monthly",send_weekday:3,monthly_cap:2,birthday_enabled:!0,birthday_subject:"Happy birthday from all of us!",birthday_body:"Happy birthday! Stop in this week and let us celebrate with you.",birthday_offer:null,birthday_image_url:null},Te=()=>{const{currentOrg:i}=I(),a=i==null?void 0:i.id,[r,u]=c.useState(F),b=c.useCallback(async()=>
26{if(!a)return;const{data:s}=await v.from("email_marketing_settings").select("*").eq("organization_id",a).maybeSingle();s&&u({...F,...s})},[a]);c.useEffect(()=>{b()},[b]);const h=async s=>{if(!a)return;const l={...r,...s};u(l);const{error:m}=await v.from("email_marketing_settings").upsert({organization_id:a,announcements_enabled:l.announcements_enabled,frequency:l.frequency,send_weekday:l.send_weekday,monthly_cap:l.monthly_cap,birthday_enabled:l.birthday_enabled,birthday_subject:l.birthday_subject,birthday_body:l.birthday_body,birthday_offer:l.birthday_offer,birthday_image_url:l.birthday_image_url},{onConflict:"organization_id"});m&&_.error(m.message)};return e.jsxs("div",{className:"space-y-3",children:[e.jsx(p,{title:"Sending rules",icon:e.jsx(Se,{className:"h-5 w-5 text-primary"}),sectionKey:"hubl-settings-marketing-rules",badge:e.jsx(q,{variant:r.announcements_enabled?"default":"secondary",className:"ml-auto mr-2",children:r.announcements_enabled?"On":"Off"}),children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-md border border-border p-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium",children:"Send announcement emails"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Only members who opted in receive these. Every email carries a one-click unsubscribe."})]}),e.jsx(N,{checked:r.announcements_enabled,onCheckedChange:s=>h({announcements_enabled:s})})]}),e.jsxs(A,{children:[e.jsx(S,{label:"How often",icon:e.jsx(Q,{className:"h-4 w-4"}),value:r.frequency,onChange:s=>h({frequency:s}),options:[{value:"weekly",label:"Weekly",description:"One announcement every week"},{value:"biweekly",label:"Every other week",description:"Twice a month"},{value:"monthly",label:"Monthly",description:"First matching weekday of the month"},{value:"quarterly",label:"Quarterly",description:"Four times a year"}],wide:!0}),e.jsx(S,{label:"Day of week",value:String(r.send_weekday),onChange:s=>h({send_weekday:Number(s)}),options:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"].map((s,l)=>({value:String(l),label:s}))}),e.jsx(S,{label:"Max per month",value:String(r.monthly_cap),onChange:s=>h({monthly_cap:Number(s)}),options:[1,2,3,4].map(s=>({value:String(s),label:`${s} email${s>1?"s":""}`}))})]})]})}),e.jsx(p,{title:"Birthday emails",icon:e.jsx(je,{className:"h-5 w-5 text-primary"}),sectionKey:"hubl-settings-marketing-birthday",badge:e.jsx(q,{variant:r.birthday_enabled?"default":"secondary",className:"ml-auto mr-2",children:r.birthday_enabled?"On":"Off"}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-md border border-border p-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium",children:"Send a happy-birthday email"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Goes out on each rewards member's birthday, once a year."})]}),e.jsx(N,{checked:r.birthday_enabled,onCheckedChange:s=>h({birthday_enabled:s})})]}),e.jsxs("div",{children:[e.jsx(C,{className:"text-xs",children:"Subject line"}),e.jsx(j,{value:r.birthday_subject,onChange:s=>u(l=>({...l,birthday_subject:s.target.value})),onBlur:()=>h({})})]}),e.jsxs("div",{children:[e.jsx(C,{className:"text-xs",children:"Message"}),e.jsx(X,{rows:4,value:r.birthday_body,onChange:s=>u(l=>({...l,birthday_body:s.target.value})),onBlur:()=>h({})})]}),e.jsxs("div",{className:"grid gap-2 sm:grid-cols-2",children:[e.jsxs("div",{children:[e.jsx(C,{className:"text-xs",children:"Birthday offer (optional)"}),e.jsx(j,{value:r.birthday_offer||"",placeholder:"A free scoop on us — just mention this email.",onChange:s=>u(l=>({...l,birthday_offer:s.target.value})),onBlur:()=>h({})})]}),e.jsxs("div",{children:[e.jsx(C,{className:"text-xs",children:"Image URL (optional)"}),e.jsx(j,{value:r.birthday_image_url||"",placeholder:"https://…",onChange:s=>u(l=>({...l,birthday_image_url:s.target.value})),onBlur:()=>h({})})]})]})]})})]})},K={announcements_enabled:!1,frequency:"monthly",send_weekday:3,monthly_cap:2,birthday_enabled:!0},Me={enabled:!1,cadence:"weekly",recipients:[]},De=Array.from({length:48},(i,a)=>{const r=Math.floor(a/2),u=a%2*30;return{value:`${r}:${u}`,label:`${(r+11)%12+1}:${u?"30":"00"} ${r<12?"AM":"PM"}`}}),Ee=[{value:"summary",label:"Summary only"},{value:"standard",label:"Standard (payment mediums + totals)"},{value:"full",label:"Full (adds categories + top items)"}],Re={enabled:!1,send_hour:21,send_minute:30,detail_level:"full",recipients:[]};Array.from({length:24},(i,a)=>({value:String(a),label:`${(a+11)%12+1}:00 ${a<12?"AM":"PM"}`}));const Ie=["Sunday","Monday","Tuesday","Wednesday","Thursday","Frid
26ay","Saturday"],P=({title:i,desc:a,children:r})=>e.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-md border border-border p-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-sm font-medium",children:i}),e.jsx("p",{className:"text-xs text-muted-foreground",children:a})]}),e.jsx("div",{className:"shrink-0",children:r})]}),Pe=()=>{const{currentOrg:i}=I(),a=i==null?void 0:i.id,[r,u]=c.useState(K),[b,h]=c.useState(Me),[s,l]=c.useState(""),[m,T]=c.useState(Re),[M,o]=c.useState(""),y=c.useCallback(async()=>{if(!a)return;const[n,d,x]=await Promise.all([v.from("email_marketing_settings").select("*").eq("organization_id",a).maybeSingle(),v.from("tax_tip_digest_settings").select("*").eq("organization_id",a).maybeSingle(),v.from("daily_sales_report_settings").select("*").eq("organization_id",a).maybeSingle()]);if(x.data){const g=x.data;T({enabled:!!g.enabled,send_hour:Number(g.send_hour??21),send_minute:Number(g.send_minute??30),detail_level:g.detail_level||"full",recipients:g.recipients||[]}),o((g.recipients||[]).join(", "))}if(n.data&&u({...K,...n.data}),d.data){const g=d.data;h({enabled:!!g.enabled,cadence:g.cadence||"weekly",recipients:g.recipients||[]}),l((g.recipients||[]).join(", "))}},[a]);c.useEffect(()=>{y()},[y]);const f=async n=>{if(!a)return;const d={...r,...n};u(d);const{error:x}=await v.from("email_marketing_settings").upsert({organization_id:a,announcements_enabled:d.announcements_enabled,frequency:d.frequency,send_weekday:d.send_weekday,monthly_cap:d.monthly_cap,birthday_enabled:d.birthday_enabled},{onConflict:"organization_id"});x&&_.error(x.message)},k=async n=>{if(!a)return;const d={...b,...n};h(d);const{error:x}=await v.from("tax_tip_digest_settings").upsert({organization_id:a,enabled:d.enabled,cadence:d.cadence,recipients:d.recipients},{onConflict:"organization_id"});x&&_.error(x.message)},w=async n=>{if(!a)return;const d={...m,...n};T(d);const{error:x}=await v.from("daily_sales_report_settings").upsert({organization_id:a,enabled:d.enabled,send_hour:d.send_hour,send_minute:d.send_minute,detail_level:d.detail_level,recipients:d.recipients},{onConflict:"organization_id"});x&&_.error(x.message)};return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{className:"space-y-3",children:[e.jsx("p",{className:"text-sm font-medium",children:"Marketing email rules"}),e.jsx(P,{title:"Birthday emails",desc:"Send a happy-birthday email on each rewards member's birthday.",children:e.jsx(N,{checked:r.birthday_enabled,onCheckedChange:n=>f({birthday_enabled:n})})}),e.jsx(P,{title:"Rotating announcements",desc:"Automatically rotate through your announcements on a schedule.",children:e.jsx(N,{checked:r.announcements_enabled,onCheckedChange:n=>f({announcements_enabled:n})})}),e.jsxs(A,{children:[e.jsx(S,{label:"Frequency",icon:e.jsx(J,{className:"h-4 w-4"}),value:r.frequency,onChange:n=>f({frequency:n}),options:[{value:"weekly",label:"Weekly"},{value:"biweekly",label:"Every other week"},{value:"monthly",label:"Monthly"}]}),e.jsx(S,{label:"Send day",value:String(r.send_weekday),onChange:n=>f({send_weekday:Number(n)}),options:Ie.map((n,d)=>({value:String(d),label:n}))})]}),e.jsxs("div",{className:"max-w-xs",children:[e.jsx(C,{className:"text-xs",children:"Maximum marketing emails per member each month"}),e.jsx(j,{inputMode:"numeric",value:String(r.monthly_cap),onChange:n=>u(d=>({...d,monthly_cap:Number(n.target.value.replace(/[^0-9]/g,""))||0})),onBlur:()=>f({})})]})]}),e.jsxs("div",{className:"space-y-3 border-t border-border pt-5",children:[e.jsx("p",{className:"text-sm font-medium",children:"Tax & tip report email"}),e.jsx(P,{title:"Send a tax & tip summary",desc:"Emails how much sales tax and how much in tips you collected for the period. Skipped when there's no new data.",children:e.jsx(N,{checked:b.enabled,onCheckedChange:n=>k({enabled:n})})}),e.jsx(A,{children:e.jsx(S,{label:"Cadence",icon:e.jsx(B,{className:"h-4 w-4"}),value:b.cadence,onChange:n=>k({cadence:n}),options:[{value:"daily",label:"Daily"},{value:"weekly",label:"Weekly"},{value:"biweekly",label:"Every other week"},{value:"monthly",label:"Monthly"}]})}),e.jsxs("div",{children:[e.jsx(C,{className:"text-xs",children:"Recipients (comma separated — leave blank to use the organization email)"}),e.jsx(j,{value:s,placeholder:"[email protected], [email protected]",onChange:n=>l(n.target.value),onBlur:()=>k({recipients:s.split(",").map(n=>
26n.trim()).filter(Boolean)})})]})]}),e.jsxs("div",{className:"space-y-3 border-t border-border pt-5",children:[e.jsx("p",{className:"text-sm font-medium",children:"Daily sales report email"}),e.jsx(P,{title:"Send an end-of-day sales report",desc:"Nightly breakdown of the day's sales for businesses using HUBLPay: card, cash, online, tips, tax, categories and totals.",children:e.jsx(N,{checked:m.enabled,onCheckedChange:n=>w({enabled:n})})}),e.jsxs(A,{children:[e.jsx(S,{label:"Send time",icon:e.jsx(B,{className:"h-4 w-4"}),value:`${m.send_hour}:${m.send_minute}`,onChange:n=>{const[d,x]=n.split(":").map(Number);w({send_hour:d,send_minute:x})},options:De}),e.jsx(S,{label:"Detail",icon:e.jsx(B,{className:"h-4 w-4"}),value:m.detail_level,onChange:n=>w({detail_level:n}),options:Ee})]}),e.jsxs("div",{children:[e.jsx(C,{className:"text-xs",children:"Recipients (comma separated — leave blank to use the organization email)"}),e.jsx(j,{value:M,placeholder:"[email protected]",onChange:n=>o(n.target.value),onBlur:()=>w({recipients:M.split(",").map(n=>n.trim()).filter(Boolean)})})]})]})]})},E=v,Ae=i=>`${i.getFullYear()}-${String(i.getMonth()+1).padStart(2,"0")}-${String(i.getDate()).padStart(2,"0")}`,U=i=>new Date(i).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}),ze=()=>{const{currentOrg:i}=I(),a=i==null?void 0:i.id,[r,u]=c.useState(null),[b,h]=c.useState([]),[s,l]=c.useState({date:Ae(new Date),from:"17:00",to:"19:00",reason:""}),m=c.useCallback(async()=>{var f;if(!a)return;const[o,y]=await Promise.all([E.from("restaurant_settings").select("max_covers_per_slot").eq("organization_id",a).maybeSingle(),E.from("restaurant_blocks").select("*").eq("organization_id",a).gte("ends_at",new Date().toISOString()).order("starts_at")]);u(((f=o.data)==null?void 0:f.max_covers_per_slot)??null),h(y.data??[])},[a]);c.useEffect(()=>{m()},[m]);const T=async o=>{u(o);const{error:y}=await E.from("restaurant_settings").update({max_covers_per_slot:o}).eq("organization_id",a);y?_.error(y.message):_.success("Saved")},M=async()=>{const[o,y,f]=s.date.split("-").map(Number),[k,w]=s.from.split(":").map(Number),[n,d]=s.to.split(":").map(Number),x=new Date(o,y-1,f,k,w),g=new Date(o,y-1,f,n,d);if(!(g>x))return _.error("End time must be after start time");const{error:D}=await E.from("restaurant_blocks").insert({organization_id:a,starts_at:x.toISOString(),ends_at:g.toISOString(),reason:s.reason||null});if(D)return _.error(D.message);l({...s,reason:""}),m()};return e.jsxs("div",{className:"space-y-4 text-sm",children:[e.jsxs("label",{className:"flex flex-wrap items-center gap-2",children:["Most online guests per 15 minutes",e.jsx(j,{className:"h-8 w-20",inputMode:"numeric",placeholder:"No limit",defaultValue:r??"",onBlur:o=>{const y=o.target.value&&Number(o.target.value.replace(/\D/g,""))||null;y!==r&&T(y)}},String(r)),e.jsx("span",{className:"text-xs text-muted-foreground",children:"Keeps the kitchen from getting slammed. Staff can still book past it."})]}),e.jsxs("div",{children:[e.jsx("div",{className:"mb-2 font-semibold",children:"Blocked times & private events"}),e.jsxs("div",{className:"mb-2 flex flex-wrap gap-2",children:[e.jsx(j,{type:"date",className:"h-8 w-40",value:s.date,onChange:o=>l({...s,date:o.target.value})}),e.jsx(j,{type:"time",className:"h-8 w-32",value:s.from,onChange:o=>l({...s,from:o.target.value})}),e.jsx(j,{type:"time",className:"h-8 w-32",value:s.to,onChange:o=>l({...s,to:o.target.value})}),e.jsx(j,{className:"h-8 w-48",placeholder:"Reason (e.g. private party)",value:s.reason,onChange:o=>l({...s,reason:o.target.value})}),e.jsxs(z,{size:"sm",onClick:M,children:[e.jsx(ee,{className:"mr-1 h-4 w-4"}),"Block"]})]}),b.length===0?e.jsx("p",{className:"text-xs text-muted-foreground",children:"No upcoming blocks. The website won't offer blocked times."}):e.jsx("ul",{className:"divide-y divide-border",children:b.map(o=>e.jsxs("li",{className:"flex items-center gap-3 py-2",children:[e.jsxs("span",{className:"flex-1",children:[new Date(o.starts_at).toLocaleDateString([],{weekday:"short",month:"short",day:"numeric"})," · ",U(o.starts_at)," – ",U(o.ends_at),o.reason?` · ${o.reason}`:""]}),e.jsx(z,{size:"sm",variant:"ghost",onClick:async()=>
26{await E.from("restaurant_blocks").delete().eq("id",o.id),m()},children:"Remove"})]},o.id))})]})]})},Qe=()=>{const{currentOrg:i}=I(),{installedAppIds:a}=te(),r=a.some(m=>m.startsWith("hubl-pos")),u=a.includes("hubl-table"),[b,h]=c.useState(""),[s,l]=c.useState(0);return c.useEffect(()=>{i!=null&&i.id&&v.from("site_content").select("value").eq("organization_id",i.id).eq("section","email").eq("key","smtp_email").maybeSingle().then(({data:m})=>{m!=null&&m.value&&h(m.value)})},[i==null?void 0:i.id]),e.jsx(se,{title:"HUBLSettings",icon:ae,subtitle:"Every app-level setting for this business, in one place.",onRefresh:()=>l(m=>m+1),children:e.jsxs("div",{className:"space-y-3",children:[e.jsx(p,{title:"Marketing Emails",sectionKey:"hubl-settings-marketing",children:e.jsx(Te,{})}),r&&e.jsx(p,{title:"Register Settings",sectionKey:"hubl-settings-register",children:e.jsx(Ce,{})}),u&&e.jsx(p,{title:"HUBLTable Booking Rules",sectionKey:"hubl-settings-hubltable",children:e.jsx(ze,{})}),e.jsx(p,{title:"Business Settings",defaultOpen:!0,sectionKey:"hubl-settings-business",children:e.jsx(ne,{embedded:!0})}),e.jsx(p,{title:"HUBLSend Settings",sectionKey:"hubl-settings-hublsend",children:e.jsx(ve,{smtpEmail:b,embedded:!0})}),e.jsx(p,{title:"Automation & Email Rules",sectionKey:"hubl-settings-automation",children:e.jsx(Pe,{})})]},s)})};export{Qe 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.