PageSourceSearch

https://nashobahub-prod.onrender.com/assets/admin-settings-CTBNzaPK.js

js nashobahub-prod.onrender.com collected 2026-10-03 11:43:45 UTC 16,951 bytes, 1 lines download raw bytes

1import{u as X,r as N,o as W,a as L,j as e,aA as le,C as w,a1 as F,a2 as T,a3 as A,a4 as U,I as r,K as de,B as j,a9 as S,T as R,b as ce,U as me,V as he,W as pe,Y as ue,Z as xe,a0 as je,A as ye,e as ge,f as fe,h as ve,i as be,k as Ne,l as ke,m as Ce,q as E,Q as D}from"./index-CU4TP-S4.js";import{u as B,F as $,a as d,b as c,c as n,d as m,e as I,f as h,t as V}from"./form-D-xzwno4.js";import{i as P}from"./authUtils-CcDzk6i0.js";import{T as Se,a as Le,b as O,c as H}from"./tabs-DGAvBb6E.js";import{n as we}from"./schema-CEA6AeVK.js";import{O as Fe}from"./ResyObjectUploader-D_UB-BW0.js";import{B as Te}from"./building-2-D6YIm3bs.js";import{I as G}from"./image-DVqlGyvi.js";import{L as _}from"./link-2-Dy6jIQ4y.js";import{E as Ae}from"./external-link-cnWKgyDk.js";import{P as Ue}from"./pencil-C0OXxJ_w.js";import{s as p,o as Ee,al as J}from"./types-BmAflJw1.js";import"./skeleton-CytUjfKO.js";const De=Ee({headerTitle:p().optional(),headerSubtitle:p().optional(),headerImageUrl:p().optional(),companyName:p().optional(),companyAddress:p().optional(),companyCity:p().optional(),companyState:p().optional(),companyZipCode:p().optional(),companyPhone:p().optional(),companyEmail:p().email().optional().or(J("")),companyWebsite:p().url().optional().or(J(""))});function Ie(){const{toast:a}=X(),[g,v]=N.useState(""),[C,f]=N.useState(""),{data:u}=W({queryKey:["/api/resy/floor-access"]}),k=L({mutationFn:async()=>D("PUT","/api/resy/floor-access",{hostCode:g,trackerCode:C}),onSuccess:()=>{v(""),f(""),E.invalidateQueries({queryKey:["/api/resy/floor-access"]}),a({title:"Access codes saved"})},onError:x=>a({title:"Access codes",description:x.message.replace(/^\d+:\s*/,""),variant:"destructive"})});return e.jsxs(w,{children:[e.jsxs(F,{children:[e.jsx(T,{children:"Host and tracker access codes"}),e.jsxs(A,{children:["Each page needs its own 4-digit code. The code is not shown again after it is saved. ",u!=null&&u.host?"Host code is set.":"Host code is not set."," ",u!=null&&u.tracker?"Tracker code is set.":"Tracker code is not set."]})]}),e.jsxs(U,{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(r,{inputMode:"numeric",maxLength:4,placeholder:"Host code",value:g,onChange:x=>v(x.target.value.replace(/\D/g,"").slice(0,4))}),e.jsx(r,{inputMode:"numeric",maxLength:4,placeholder:"Tracker code",value:C,onChange:x=>f(x.target.value.replace(/\D/g,"").slice(0,4))}),e.jsx(j,{className:"sm:col-span-2 w-fit",disabled:k.isPending||!g&&!C,onClick:()=>k.mutate(),children:"Save access codes"})]})]})}function $e(){const{toast:a}=X(),[g,v]=N.useState(null),[C,f]=N.useState(!1),[u,k]=N.useState(null),[x,q]=N.useState(null),{data:t,isLoading:ee}=W({queryKey:["/api/resy/site-settings"]}),{data:M=[],isLoading:se}=W({queryKey:["/api/resy/footer-links"]}),o=B({resolver:V(De),defaultValues:{headerTitle:"",headerSubtitle:"",headerImageUrl:"",companyName:"",companyAddress:"",companyCity:"",companyState:"",companyZipCode:"",companyPhone:"",companyEmail:"",companyWebsite:""}});N.useEffect(()=>{t&&o.reset({headerTitle:t.headerTitle||"",headerSubtitle:t.headerSubtitle||"",headerImageUrl:t.headerImageUrl||"",companyName:t.companyName||"",companyAddress:t.companyAddress||"",companyCity:t.companyCity||"",companyState:t.companyState||"",companyZipCode:t.companyZipCode||"",companyPhone:t.companyPhone||"",companyEmail:t.companyEmail||"",companyWebsite:t.companyWebsite||""})},[t,o]);const te=we.extend({name:p().min(1,"Link name is required"),url:p().url("Please enter a valid URL")}),y=B({resolver:V(te),defaultValues:{name:"",iconUrl:"",url:"",displayOrder:0}}),z=L({mutationFn:async({key:s,value:l})=>{await D("PUT",`/api/resy/site-settings/${s}`,{value:l})},onError:s=>{P(s)?a({title:"Unauthorized",description:"You must be logged in to update settings.",variant:"destructive"}):a({title:"Error",description:s.message||"Failed to update setting.",variant:"destructive"})}}),ae=async s=>{try{const l=Object.entries(s).map(([K,oe])=>z.mutateAsync({key:K,value:oe||""}));g!==null&&l.push(z.mutateAsync({key:"headerImageUrl",value:g})),await Promise.all(l),E.invalidateQueries({queryKey:["/api/resy/site-settings"]}),v(null),a({title:"Settings saved",description:"Your site settings have been updated successfully."})}catch(l){console.error("Failed to save settings:",l)}},Y=L({mutationFn:async s=>{await D("POST","/api/resy/footer-links",s)},onSuccess:()=>{E.invalidateQueries({queryKey:["/api/resy/footer-links"]}),f(!1),y.reset(),a({title:"Link created",description:"Footer link has been created successfully."})},onError:s=>{P(s)?a({title:"Unauthorized",description:"You must be logged in to create footer links.",variant:"destructive"}):a({title:"Error",description:s.message||"Failed to create footer link.",variant:"destructive"})}}),Q=L({mutationFn:async s=>{const{id:l,...K}=s;await D("PATCH",`/api/resy/footer-links/${l}`,K)},onSuccess:()=>{E.invalidateQueries({queryKey:["/api/resy/footer-links"]}),f(!1),k(null),y.reset(),a({title:"Link updated",description:"Footer link has been updated successfully."})},onError:s=>{P(s)?a({title:"Unauthorized",description:"You must be logged in to update footer links.",variant:"destructive"}):a({title:"Error",description:s.message||"Failed to update footer link.",variant:"destructive"})}}),Z=L({mutationFn:async s=>{await D("DELETE",`/api/resy/footer-links/${s}`)},onSuccess:()=>{E.invalidateQueries({queryKey:["/api/resy/footer-links"]}),q(null),a({title:"Link deleted",description:"Footer link has been deleted successfully."})},onError:s=>{P(s)?a({title:"Unauthorized",description:"You must be logged in to delete footer links.",variant:"destructive"}):a({title:"Error",description:s.message||"Failed to delete footer link.",variant:"destructive"})}}),ie=s=>{k(s),y.reset({name:s.name,iconUrl:s.iconUrl||"",url:s.url,displayOrder:s.displayOrder}),f(!0)},ne=()=>{k(null),y.reset({name:"",iconUrl:"",url:"",displayOrder:M.length}),f(!0)},re=s=>{u?Q.mutate({...s,id:u.id}):Y.mutate(s)},i=z.isPending,b=Y.isPending||Q.isPending;return ee?e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{children:[e.jsx("div",{className:"h-10 bg-muted rounded animate-pulse w-1/3 mb-2"}),e.jsx("div",{className:"h-6 bg-muted rounded animate-pulse w-1/2"})]}),e.jsx("div",{className:"h-96 bg-muted rounded animate-pulse"})]}):e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"font-serif text-3xl md:text-4xl font-semibold mb-2",children:"Settings"}),e.jsx("p",{className:"text-muted-foreground",children:"Configure your reservation site settings and footer links."})]}),e.jsx(Ie,{}),e.jsxs(Se,{defaultValue:"general",className:"space-y-6",children:[e.jsxs(Le,{"data-testid":"tabs-settings",children:[e.jsxs(O,{value:"general","data-testid":"tab-general",children:[e.jsx(le,{className:"w-4 h-4 mr-2"}),"General"]}),e.jsxs(O,{value:"company","data-testid":"tab-company",children:[e.jsx(Te,{className:"w-4 h-4 mr-2"}),"Company Info"]}),e.jsxs(O,{value:"header","data-testid":"tab-header",children:[e.jsx(G,{className:"w-4 h-4 mr-2"}),"Header"]}),e.jsxs(O,{value:"footer","data-testid":"tab-footer",children:[e.jsx(_,{className:"w-4 h-4 mr-2"}),"Footer Links"]})]}),e.jsx($,{...o,children:e.jsxs("form",{onSubmit:o.handleSubmit(ae),children:[e.jsx(H,{value:"general",children:e.jsxs(w,{children:[e.jsxs(F,{children:[e.jsx(T,{children:"General Settings"}),e.jsx(A,{children:"Basic configuration for your reservation site."})]}),e.jsxs(U,{className:"space-y-4",children:[e.jsx(d,{control:o.control,name:"headerTitle",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"Site Title"}),e.jsx(m,{children:e.jsx(r,{...s,placeholder:"Your Winery Name",disabled:i,"data-testid":"input-header-title"})}),e.jsx(I,{children:"The main title shown on your reservation page."}),e.jsx(h,{})]})}),e.jsx(d,{control:o.control,name:"headerSubtitle",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"Site Subtitle"}),e.jsx(m,{children:e.jsx(de,{...s,placeholder:"Welcome to our tasting room...",rows:3,disabled:i,"data-testid":"input-header-subtitle"})}),e.jsx(I,{children:"A brief description shown below the title."}),e.jsx(h,{})]})}),e.jsx("div",{className:"flex justify-end pt-4",children:e.jsxs(j,{type:"submit",disabled:i,"data-testid":"button-save-general",children:[i&&e.jsx(S,{className:"w-4 h-4 mr-2 animate-spin"}),"Save Settings"]})})]})]})}),e.jsx(H,{value:"company",children:e.jsxs(w,{children:[e.jsxs(F,{children:[e.jsx(T,{children:"Company Information"}),e.jsx(A,{children:"Your business contact details shown on the reservation site."})]}),e.jsxs(U,{className:"space-y-4",children:[e.jsx(d,{control:o.control,name:"companyName",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"Company Name"}
1),e.jsx(m,{children:e.jsx(r,{...s,placeholder:"Your Business Name",disabled:i,"data-testid":"input-company-name"})}),e.jsx(h,{})]})}),e.jsx(d,{control:o.control,name:"companyAddress",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"Address"}),e.jsx(m,{children:e.jsx(r,{...s,placeholder:"123 Main Street",disabled:i,"data-testid":"input-company-address"})}),e.jsx(h,{})]})}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4",children:[e.jsx(d,{control:o.control,name:"companyCity",render:({field:s})=>e.jsxs(c,{className:"col-span-2 md:col-span-1",children:[e.jsx(n,{children:"City"}),e.jsx(m,{children:e.jsx(r,{...s,placeholder:"City",disabled:i,"data-testid":"input-company-city"})}),e.jsx(h,{})]})}),e.jsx(d,{control:o.control,name:"companyState",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"State"}),e.jsx(m,{children:e.jsx(r,{...s,placeholder:"MA",disabled:i,"data-testid":"input-company-state"})}),e.jsx(h,{})]})}),e.jsx(d,{control:o.control,name:"companyZipCode",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"ZIP Code"}),e.jsx(m,{children:e.jsx(r,{...s,placeholder:"01234",disabled:i,"data-testid":"input-company-zip"})}),e.jsx(h,{})]})})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsx(d,{control:o.control,name:"companyPhone",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"Phone"}),e.jsx(m,{children:e.jsx(r,{...s,type:"tel",placeholder:"(555) 123-4567",disabled:i,"data-testid":"input-company-phone"})}),e.jsx(h,{})]})}),e.jsx(d,{control:o.control,name:"companyEmail",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"Email"}),e.jsx(m,{children:e.jsx(r,{...s,type:"email",placeholder:"[email protected]",disabled:i,"data-testid":"input-company-email"})}),e.jsx(h,{})]})})]}),e.jsx(d,{control:o.control,name:"companyWebsite",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"Website"}),e.jsx(m,{children:e.jsx(r,{...s,type:"url",placeholder:"https://www.example.com",disabled:i,"data-testid":"input-company-website"})}),e.jsx(h,{})]})}),e.jsx("div",{className:"flex justify-end pt-4",children:e.jsxs(j,{type:"submit",disabled:i,"data-testid":"button-save-company",children:[i&&e.jsx(S,{className:"w-4 h-4 mr-2 animate-spin"}),"Save Settings"]})})]})]})}),e.jsx(H,{value:"header",children:e.jsxs(w,{children:[e.jsxs(F,{children:[e.jsx(T,{children:"Header Image"}),e.jsx(A,{children:"The hero image displayed at the top of your reservation page."})]}),e.jsxs(U,{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx(n,{children:"Current Header Image"}),g!==null?e.jsx("div",{className:"mt-2",children:g?e.jsxs("div",{className:"relative inline-block",children:[e.jsx("img",{src:g,alt:"New header",className:"max-w-md rounded-lg border"}),e.jsx(j,{type:"button",variant:"destructive",size:"icon",className:"absolute top-2 right-2",onClick:()=>v(null),children:e.jsx(R,{className:"w-4 h-4"})})]}):e.jsx("p",{className:"text-sm text-muted-foreground",children:"Image will be removed when you save."})}):t!=null&&t.headerImageUrl?e.jsxs("div",{className:"mt-2 relative inline-block",children:[e.jsx("img",{src:t.headerImageUrl,alt:"Current header",className:"max-w-md rounded-lg border"}),e.jsx(j,{type:"button",variant:"destructive",size:"icon",className:"absolute top-2 right-2",onClick:()=>v(""),children:e.jsx(R,{className:"w-4 h-4"})})]}):e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:"No header image set."})]}),e.jsxs("div",{children:[e.jsx(n,{children:"Upload New Image"}),e.jsx("div",{className:"mt-2",children:e.jsxs(Fe,{onComplete:s=>{v(s),a({title:"Image selected",description:"Save settings to apply the new header image."})},variant:"outline",children:[e.jsx(G,{className:"w-4 h-4 mr-2"}),"Select from Media Library"]})})]})]}),e.jsx("div",{className:"flex justify-end pt-4",children:e.jsxs(j,{type:"submit",disabled:i,"data-testid":"button-save-header",children:[i&&e.jsx(S,{className:"w-4 h-4 mr-2 animate-spin"}),"Save Settings"]})})]})]})})]})}),e.jsx(H,{value:"footer",children:e.jsxs(w,{children:[e.jsx(F,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx(T,{children:"Footer Links"}),e.jsx(A,{children:"Links displayed in the footer of your reservation page."})]}),e.jsxs(j,{onClick:ne,"data-testid":"button-add-footer-link",children:[e.jsx(ce,{className:"w-4 h-4 mr-2"}),"Add Link"]})]})}),e.jsx(U,{children:se?e.jsx("div",{className:"space-y-3",children:[...Array(3)].map((s,l)=>e.jsx("div",{className:"h-16 bg-muted rounded animate-pulse"},l))}):M.length===0?e.jsxs("div",{className:"text-center py-8 text-muted-foreground",children:[e.jsx(_,{className:"w-12 h-12 mx-auto mb-4 opacity-50"}),e.jsx("p",{children:"No footer links yet"}),e.jsx("p",{className:"text-sm mt-1",children:"Add links to display in your site footer."})]}):e.jsx("div",{className:"space-y-3",children:M.sort((s,l)=>s.displayOrder-l.displayOrder).map(s=>e.jsxs("div",{className:"flex items-center justify-between p-4 border rounded-lg",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[s.iconUrl&&e.jsx("img",{src:s.iconUrl,alt:"",className:"w-6 h-6 object-contain"}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:s.name}),e.jsxs("a",{href:s.url,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-muted-foreground hover:text-primary flex items-center gap-1",children:[s.url,e.jsx(Ae,{className:"w-3 h-3"})]})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(j,{variant:"ghost",size:"icon",onClick:()=>ie(s),"data-testid":`button-edit-footer-link-${s.id}`,children:e.jsx(Ue,{className:"w-4 h-4"})}),e.jsx(j,{variant:"ghost",size:"icon",onClick:()=>q(s),"data-testid":`button-delete-footer-link-${s.id}`,children:e.jsx(R,{className:"w-4 h-4"})})]})]},s.id))})})]})})]}),e.jsx(me,{open:C,onOpenChange:f,children:e.jsxs(he,{children:[e.jsxs(pe,{children:[e.jsx(ue,{children:u?"Edit Footer Link":"Add Footer Link"}),e.jsx(xe,{children:u?"Update the footer link details.":"Add a new link to your site footer."})]}),e.jsx($,{...y,children:e.jsxs("form",{onSubmit:y.handleSubmit(re),className:"space-y-4",children:[e.jsx(d,{control:y.control,name:"name",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"Link Name"}),e.jsx(m,{children:e.jsx(r,{...s,placeholder:"Facebook",disabled:b,"data-testid":"input-footer-link-name"})}),e.jsx(h,{})]})}),e.jsx(d,{control:y.control,name:"url",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"URL"}),e.jsx(m,{children:e.jsx(r,{...s,type:"url",placeholder:"https://facebook.com/yourpage",disabled:b,"data-testid":"input-footer-link-url"})}),e.jsx(h,{})]})}),e.jsx(d,{control:y.control,name:"iconUrl",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"Icon URL (optional)"}),e.jsx(m,{children:e.jsx(r,{...s,value:s.value||"",placeholder:"https://example.com/icon.png",disabled:b,"data-testid":"input-footer-link-icon"})}),e.jsx(I,{children:"URL to an icon image for this link."}),e.jsx(h,{})]})}),e.jsx(d,{control:y.control,name:"displayOrder",render:({field:s})=>e.jsxs(c,{children:[e.jsx(n,{children:"Display Order"}),e.jsx(m,{children:e.jsx(r,{...s,type:"number",min:0,onChange:l=>s.onChange(parseInt(l.target.value)||0),disabled:b,"data-testid":"input-footer-link-order"})}),e.jsx(I,{children:"Lower numbers appear first."}),e.jsx(h,{})]})}),e.jsxs(je,{children:[e.jsx(j,{type:"button",variant:"outline",onClick:()=>f(!1),disabled:b,children:"Cancel"}),e.jsxs(j,{type:"submit",disabled:b,"data-testid":"button-save-footer-link",children:[b&&e.jsx(S,{className:"w-4 h-4 mr-2 animate-spin"}),u?"Update Link":"Add Link"]})]})]})})]})}),e.jsx(ye,{open:!!x,onOpenChange:()=>q(null),children:e.jsxs(ge,{children:[e.jsxs(fe,{children:[e.jsx(ve,{children:"Delete Footer Link"}),e.jsxs(be,{children:['Are you sure you want to delete "',x==null?void 0:x.name,'"? This action cannot be undone.']})]}),e.jsxs(Ne,{children:[e.jsx(ke,{children:"Cancel"}),e.jsxs(Ce,{onClick:()=>x&&Z.mutate(x.id),className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:[Z.isPending&&e.jsx(S,{className:"w-4 h-4 mr-2 animate-spin"}),"Delete"]})]})]})})]})}export{$e 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.