PageSourceSearch

https://nashobahub-prod.onrender.com/assets/admin-locations-DWudJtzg.js

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

1import{u as U,av as V,r as P,o as k,a as y,j as e,B as r,ax as Y,b as W,C as D,a1 as M,a4 as T,a2 as B,a3 as _,an as G,aq as J,aA as Z,a9 as A,A as X,cs as ee,T as se,e as ae,f as te,h as ie,i as ne,k as oe,l as re,m as le,U as de,V as ce,W as ue,Y as me,Z as he,I as q,c as O,K as $,Q as v,q as j}from"./index-CU4TP-S4.js";import{u as xe,t as ge,F as pe,a as u,b as m,c,d as h,f as b,e as p}from"./form-D-xzwno4.js";import{i as E}from"./authUtils-CcDzk6i0.js";import{r as R}from"./reservationLink-byin_0o3.js";import{c as je}from"./schema-CEA6AeVK.js";import{E as ve}from"./external-link-cnWKgyDk.js";import{E as fe}from"./eye-off-DT88Dd3V.js";import{A as be}from"./arrow-right-q8WDM_DR.js";import{C as ye}from"./copy-5gJh_YQI.js";import"./types-BmAflJw1.js";function Pe(){const{toast:t}=U(),[,f]=V(),[x,i]=P.useState(!1),[l,g]=P.useState(null),{data:a,isLoading:o}=k({queryKey:["/api/resy/locations"]}),{data:F}=k({queryKey:["/api/resy/experiences"]}),{data:w,isLoading:I}=k({queryKey:["/api/resy/location-tables"]}),S=y({mutationFn:async({id:s,showOnMasterPage:n})=>await(await v("PATCH",`/api/resy/locations/${s}`,{showOnMasterPage:n})).json(),onSuccess:()=>{j.invalidateQueries({queryKey:["/api/resy/locations"]})},onError:s=>{t({title:"Update failed",description:s.message,variant:"destructive"})}}),N=y({mutationFn:async s=>await(await v("POST",`/api/resy/locations/${s}/clone`,{})).json(),onSuccess:()=>{j.invalidateQueries({queryKey:["/api/resy/locations"]}),t({title:"Location Cloned",description:"A copy of the location has been created"})},onError:s=>{if(E(s)){t({title:"Unauthorized",description:"You are logged out. Logging in again...",variant:"destructive"}),setTimeout(()=>{window.location.href="/api/login"},500);return}t({title:"Clone Failed",description:s.message,variant:"destructive"})}}),L=y({mutationFn:async s=>await v("DELETE",`/api/resy/locations/${s}`),onSuccess:()=>{j.invalidateQueries({queryKey:["/api/resy/locations"]}),j.invalidateQueries({queryKey:["/api/resy/location-tables"]}),t({title:"Location Deleted",description:"The location has been permanently deleted"})},onError:s=>{if(E(s)){t({title:"Unauthorized",description:"You are logged out. Logging in again...",variant:"destructive"}),setTimeout(()=>{window.location.href="/api/login"},500);return}t({title:"Delete Failed",description:s.message,variant:"destructive"})}}),K=s=>{g(s),i(!0)},z=()=>{g(null),i(!0)},H=s=>{f(`/reservations/admin/locations/${s}`)},Q=(w==null?void 0:w.reduce((s,n)=>(s[n.locationId]||(s[n.locationId]=[]),s[n.locationId].push(n),s),{}))||{};return e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs(r,{variant:"outline",size:"sm",onClick:()=>f("/"),"data-testid":"button-return-hub",children:[e.jsx(Y,{className:"h-4 w-4 mr-2"}),"Return to Hub"]}),e.jsxs("div",{children:[e.jsx("h1",{className:"font-serif text-3xl md:text-4xl font-semibold mb-2",children:"Locations & Tables"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage dining locations and their table inventory"})]})]}),e.jsxs(r,{onClick:z,"data-testid":"button-create-location",children:[e.jsx(W,{className:"w-4 h-4 mr-2"}),"Create Location"]})]}),o||I?e.jsx("div",{className:"grid gap-6 md:grid-cols-2 lg:grid-cols-3",children:[...Array(3)].map((s,n)=>e.jsxs(D,{children:[e.jsx(M,{children:e.jsx("div",{className:"h-6 bg-muted rounded animate-pulse w-2/3"})}),e.jsx(T,{children:e.jsx("div",{className:"h-16 bg-muted rounded animate-pulse"})})]},n))}):a&&a.length>0?e.jsx("div",{className:"grid gap-6 md:grid-cols-2 lg:grid-cols-3",children:a.map(s=>{var C;const n=((C=Q[s.id])==null?void 0:C.length)||0;return e.jsxs(D,{className:"hover-elevate",children:[e.jsxs(M,{children:[e.jsx(B,{className:"text-xl",children:s.name}),s.description&&e.jsx(_,{children:s.description})]}),e.jsxs(T,{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(G,{className:"w-4 h-4"}),e.jsxs("span",{children:[n," ",n===1?"table":"tables"]})]}),e.jsx("div",{className:"space-y-1",children:(F||[]).filter(d=>d.locationId===s.id&&!d.isExternal).map(d=>e.jsxs("a",{href:R(d),target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1 text-sm font-medium text-primary hover:underline break-all","data-testid":`link-booking-page-${d.id}`,children:[e.jsx(ve,{className:"w-3.5 h-3.5 shrink-0"}),window.location.origin,R(d)]},d.id))}),e.jsxs(r,{variant:s.showOnMasterPage===!1?"outline":"secondary",className:"w-full",disabled:S.isPending,onClick:()=>S.mutate({id:s.id,showOnMasterPage:s.showOnMasterPage===!1}),"data-testid":`button-master-location-${s.id}`,children:[s.showOnMasterPage===!1?e.jsx(fe,{className:"w-4 h-4 mr-2"}):e.jsx(J,{className:"w-4 h-4 mr-2"}),s.showOnMasterPage===!1?"Excluded from master page":"Included on master page"]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(r,{onClick:()=>H(s.id),className:"flex-1","data-testid":`button-manage-location-${s.id}`,children:["Manage",e.jsx(be,{className:"w-3 h-3 ml-2"})]}),e.jsx(r,{onClick:()=>K(s),size:"icon",variant:"outline","data-testid":`button-edit-location-${s.id}`,children:e.jsx(Z,{className:"w-4 h-4"})}),e.jsx(r,{onClick:()=>N.mutate(s.id),size:"icon",variant:"outline",disabled:N.isPending,"data-testid":`button-clone-location-${s.id}`,children:N.isPending?e.jsx(A,{className:"w-4 h-4 animate-spin"}):e.jsx(ye,{className:"w-4 h-4"})}),e.jsxs(X,{children:[e.jsx(ee,{asChild:!0,children:e.jsx(r,{size:"icon",variant:"outline",disabled:L.isPending,"data-testid":`button-delete-location-${s.id}`,children:L.isPending?e.jsx(A,{className:"w-4 h-4 animate-spin"}):e.jsx(se,{className:"w-4 h-4"})})}),e.jsxs(ae,{children:[e.jsxs(te,{children:[e.jsx(ie,{children:"Delete Location"}),e.jsxs(ne,{children:['Are you sure you want to delete "',s.name,'"? This will also delete all tables, operating hours, and other settings associated with this location. This action cannot be undone.']})]}),e.jsxs(oe,{children:[e.jsx(re,{"data-testid":"button-cancel-delete",children:"Cancel"}),e.jsx(le,{onClick:()=>L.mutate(s.id),className:"bg-destructive text-destructive-foreground hover:bg-destructive/90","data-testid":"button-confirm-delete",children:"Delete"})]})]})]})]})]})]},s.id)})}):e.jsx(D,{children:e.jsx(T,{className:"text-center py-12",children:e.jsx("p",{className:"text-muted-foreground",children:"No locations foun
1d"})})}),e.jsx(de,{open:x,onOpenChange:i,children:e.jsxs(ce,{className:"max-w-2xl",children:[e.jsxs(ue,{children:[e.jsx(me,{children:l?"Edit Location Settings":"Create New Location"}),e.jsx(he,{children:l?"Update location configuration":"Add a new dining location to the system"})]}),e.jsx(we,{location:l,onSuccess:()=>{i(!1),g(null)}})]})})]})}function we({location:t,onSuccess:f}){const{toast:x}=U(),i=xe({resolver:ge(je),defaultValues:t?{name:t.name,description:t.description||"",headline:t.headline||"",bookingDetails:t.bookingDetails||"",address:t.address||"",isActive:t.isActive,isTicketedEventLocation:t.isTicketedEventLocation??!1,isReservationLocation:t.isReservationLocation??!1}:{name:"",description:"",headline:"",bookingDetails:"",address:"",isActive:!0,isTicketedEventLocation:!1,isReservationLocation:!1}}),l=y({mutationFn:async a=>t?(await v("PATCH",`/api/resy/locations/${t.id}`,a)).json():(await v("POST","/api/resy/locations",a)).json(),onSuccess:()=>{j.invalidateQueries({queryKey:["/api/resy/locations"]}),x({title:t?"Location Updated":"Location Created",description:`Location has been ${t?"updated":"created"} successfully`}),f()},onError:a=>{if(E(a)){x({title:"Unauthorized",description:"You are logged out. Logging in again...",variant:"destructive"}),setTimeout(()=>{window.location.href="/api/login"},500);return}x({title:"Save Failed",description:a.message,variant:"destructive"})}}),g=a=>{l.mutate(a)};return e.jsx(pe,{...i,children:e.jsxs("form",{onSubmit:i.handleSubmit(g),className:"space-y-6",children:[e.jsx(u,{control:i.control,name:"name",render:({field:a})=>e.jsxs(m,{children:[e.jsx(c,{children:"Location Name *"}),e.jsx(h,{children:e.jsx(q,{placeholder:"J's Restaurant",...a,"data-testid":"input-location-name"})}),e.jsx(b,{})]})}),e.jsxs("div",{className:"space-y-4 p-4 border rounded-lg bg-muted/30",children:[e.jsx(c,{className:"text-base font-medium",children:"Location Type"}),e.jsx(p,{className:"mt-0 mb-3",children:"Select the type of experience this location supports"}),e.jsx(u,{control:i.control,name:"isReservationLocation",render:({field:a})=>e.jsxs(m,{className:"flex flex-row items-start space-x-3 space-y-0",children:[e.jsx(h,{children:e.jsx(O,{checked:a.value,onCheckedChange:o=>{a.onChange(o),o&&i.setValue("isTicketedEventLocation",!1)},"data-testid":"checkbox-reservation-location"})}),e.jsxs("div",{className:"space-y-1 leading-none",children:[e.jsx(c,{className:"font-normal",children:"Table Reservation"}),e.jsx(p,{children:"For dining with table management, service periods, and turn times"})]})]})}),e.jsx(u,{control:i.control,name:"isTicketedEventLocation",render:({field:a})=>e.jsxs(m,{className:"flex flex-row items-start space-x-3 space-y-0",children:[e.jsx(h,{children:e.jsx(O,{checked:a.value,onCheckedChange:o=>{a.onChange(o),o&&i.setValue("isReservationLocation",!1)},"data-testid":"checkbox-ticketed-location"})}),e.jsxs("div",{className:"space-y-1 leading-none",children:[e.jsx(c,{className:"font-normal",children:"Ticketed Event"}),e.jsx(p,{children:"For tours, tastings, and events with capacity limits (no table management)"})]})]})})]}),e.jsx(u,{control:i.control,name:"headline",render:({field:a})=>e.jsxs(m,{children:[e.jsx(c,{children:"Guest headline"}),e.jsx(h,{children:e.jsx(q,{placeholder:"Outdoor seating above the vineyard",...a,value:a.value||"","data-testid":"input-location-headline"})}),e.jsx(p,{children:"Shown at the top of this location's booking page."}),e.jsx(b,{})]})}),e.jsx(u,{control:i.control,name:"description",render:({field:a})=>e.jsxs(m,{children:[e.jsx(c,{children:"About this location"}),e.jsx(h,{children:e.jsx($,{placeholder:"What guests should know about this place",...a,value:a.value||"","data-testid":"input-location-description"})}),e.jsx(b,{})]})}),e.jsx(u,{control:i.control,name:"bookingDetails",render:({field:a})=>e.jsxs(m,{children:[e.jsx(c,{children:"What guests are booking"}),e.jsx(h,{children:e.jsx($,{placeholder:"A table for casual outdoor dining",...a,value:a.value||"","data-testid":"input-location-booking-details"})}),e.jsx(p,{children:"Shown beside the photo on the public booking page."}),e.jsx(b,{})]})}),e.jsx("div",{className:"flex justify-end gap-3",children:e.jsx(r,{type:"submit",disabled:l.isPending,"data-testid":"button-save-location",children:l.isPending?e.jsxs(e.Fragment,{children:[e.jsx(A,{className:"w-3 h-3 mr-2 animate-spin"}),"Saving..."]}):"Update Location"})})]})})}export{Pe 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.