1import{c as f,r as h,j as e,d as O,B as p,m as v,X as R,e as B,L as Z}from"./index-BPQdf4N5.js";import{M as Y,I as N,u as T,T as K}from"./textarea-CDOZsyr9.js";import{u as q,L as k}from"./loader-circle-BCH3CJJd.js";import{C as ee}from"./circle-alert-CPiFck_2.js";import{E as te}from"./external-link-DtZSob4M.js";import"./utils-km2FGkQ4.js";/** 2 * @license lucide-react v0.545.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 se=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],ae=f("check",se);/** 7 * @license lucide-react v0.545.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 re=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],ie=f("chevron-down",re);/** 12 * @license lucide-react v0.545.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 ne=[["path",{d:"m18 15-6-6-6 6",key:"153udz"}]],le=f("chevron-up",ne);/** 17 * @license lucide-react v0.545.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 oe=[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]],V=f("eye-off",oe);/** 22 * @license lucide-react v0.545.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 de=[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],J=f("eye",de);/** 27 * @license lucide-react v0.545.0 - ISC 28 * 29 * This source code is licensed under the ISC license. 30 * See the LICENSE file in the root directory of this source tree. 31 */const ce=[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]],G=f("file-text",ce);/** 32 * @license lucide-react v0.545.0 - ISC 33 * 34 * This source code is licensed under the ISC license. 35 * See the LICENSE file in the root directory of this source tree. 36 */const me=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]],ue=f("image",me);/** 37 * @license lucide-react v0.545.0 - ISC 38 * 39 * This source code is licensed under the ISC license. 40 * See the LICENSE file in the root directory of this source tree. 41 */const xe=[["polyline",{points:"22 12 16 12 14 15 10 15 8 12 2 12",key:"o97t9d"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"oot6mr"}]],he=f("inbox",xe);/** 42 * @license lucide-react v0.545.0 - ISC 43 * 44 * This source code is licensed under the ISC license. 45 * See the LICENSE file in the root directory of this source tree. 46 */const pe=[["rect",{width:"7",height:"9",x:"3",y:"3",rx:"1",key:"10lvy0"}],["rect",{width:"7",height:"5",x:"14",y:"3",rx:"1",key:"16une8"}],["rect",{width:"7",height:"9",x:"14",y:"12",rx:"1",key:"1hutg5"}],["rect",{width:"7",height:"5",x:"3",y:"16",rx:"1",key:"ldoo1y"}]],fe=f("layout-dashboard",pe);/** 47 * @license lucide-react v0.545.0 - ISC 48 * 49 * This source code is licensed under the ISC license. 50 * See the LICENSE file in the root directory of this source tree. 51 */const ye=[["path",{d:"m16 17 5-5-5-5",key:"1bji2h"}],["path",{d:"M21 12H9",key:"dn1m92"}],["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4",key:"1uf3rs"}]],be=f("log-out",ye);/** 52 * @license lucide-react v0.545.0 - ISC 53 * 54 * This source code is licensed under the ISC license. 55 * See the LICENSE file in the root directory of this source tree. 56 */const ge=[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]],je=f("lock",ge);/** 57 * @license lucide-react v0.545.0 - ISC 58 * 59 * This source code is licensed under the ISC license. 60 * See the LICENSE file in the root directory of this source tree. 61 */const Ne=[["path",{d:"M15 18h-5",key:"95g1m2"}],["path",{d:"M18 14h-8",key:"sponae"}],["path",{d:"M4 22h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v16a2 2 0 0 1-4 0v-9a2 2 0 0 1 2-2h2",key:"39pd36"}
61],["rect",{width:"8",height:"4",x:"10",y:"6",rx:"1",key:"aywv1n"}]],ve=f("newspaper",Ne);/** 62 * @license lucide-react v0.545.0 - ISC 63 * 64 * This source code is licensed under the ISC license. 65 * See the LICENSE file in the root directory of this source tree. 66 */const we=[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]],ke=f("pencil",we);/** 67 * @license lucide-react v0.545.0 - ISC 68 * 69 * This source code is licensed under the ISC license. 70 * See the LICENSE file in the root directory of this source tree. 71 */const Ce=[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]],_=f("plus",Ce);/** 72 * @license lucide-react v0.545.0 - ISC 73 * 74 * This source code is licensed under the ISC license. 75 * See the LICENSE file in the root directory of this source tree. 76 */const Se=[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]],W=f("save",Se);/** 77 * @license lucide-react v0.545.0 - ISC 78 * 79 * This source code is licensed under the ISC license. 80 * See the LICENSE file in the root directory of this source tree. 81 */const Me=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],$=f("trash-2",Me);/** 82 * @license lucide-react v0.545.0 - ISC 83 * 84 * This source code is licensed under the ISC license. 85 * See the LICENSE file in the root directory of this source tree. 86 */const Ee=[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m17 8-5-5-5 5",key:"7q97r8"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}]],ze=f("upload",Ee),I={title:"",type:"News",date:"",time:null,description:"",content:[],image:"",ctaText:null,ctaLink:null};function Le({message:s,type:m,onClose:l}){return e.jsxs(v.div,{initial:{opacity:0,y:50,scale:.9},animate:{opacity:1,y:0,scale:1},exit:{opacity:0,y:20,scale:.9},className:`fixed bottom-6 right-6 z-50 flex items-center gap-3 px-6 py-4 rounded-xl shadow-2xl text-white ${m==="success"?"bg-green-600":"bg-red-600"}`,children:[m==="success"?e.jsx(ae,{size:20}):e.jsx(ee,{size:20}),e.jsx("span",{className:"font-medium",children:s}),e.jsx("button",{onClick:l,className:"ml-2 hover:opacity-70",children:e.jsx(R,{size:16})})]})}function X({title:s,itemName:m,bodyPrefix:l,bodySuffix:i,confirmLabel:c,onConfirm:r,onCancel:x,isPending:a}){return e.jsx(v.div,{initial:{opacity:0}
86,animate:{opacity:1},exit:{opacity:0},className:"fixed inset-0 bg-black/70 backdrop-blur-sm z-50 flex items-center justify-center p-6",onClick:x,children:e.jsx(v.div,{initial:{scale:.9,opacity:0},animate:{scale:1,opacity:1},exit:{scale:.9,opacity:0},className:"bg-card border border-white/10 rounded-2xl p-8 max-w-md w-full",onClick:u=>u.stopPropagation(),children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-16 h-16 bg-red-500/10 rounded-full flex items-center justify-center mx-auto mb-4",children:e.jsx($,{className:"w-8 h-8 text-red-500"})}),e.jsx("h3",{className:"text-2xl font-serif mb-2",children:s}),e.jsxs("p",{className:"text-muted-foreground mb-6",children:[l,'"',e.jsx("span",{className:"text-white",children:m}),'"',i]}),e.jsxs("div",{className:"flex gap-3 justify-center",children:[e.jsx(p,{variant:"outline",onClick:x,className:"rounded-full px-6",disabled:a,children:"Cancel"}),e.jsxs(p,{onClick:r,disabled:a,className:"bg-red-600 hover:bg-red-700 text-white rounded-full px-6","data-testid":"button-confirm-delete",children:[a?e.jsx(k,{className:"h-4 w-4 animate-spin mr-2"}):e.jsx($,{size:16,className:"mr-2"}),c]})]})]})})})}function Pe({onLogin:s}){const[m,l]=h.useState(""),[i,c]=h.useState(""),[r,x]=h.useState(""),[a,u]=
86h.useState(!1),b=async o=>{o.preventDefault(),u(!0),x("");try{(await fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:m,password:i})})).ok?s():x("Invalid username or password")}catch{x("Login failed. Please try again.")}finally{u(!1)}};return e.jsx("div",{className:"min-h-screen pt-36 md:pt-56 bg-background",children:e.jsx("div",{className:"container mx-auto px-6 pb-24",children:e.jsx(v.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},className:"max-w-md mx-auto",children:e.jsxs("div",{className:"bg-card/30 border border-white/5 rounded-2xl p-8 backdrop-blur-sm",children:[e.jsxs("div",{className:"text-center mb-8",children:[e.jsx("div",{className:"w-16 h-16 bg-primary/10 rounded-full flex items-center justify-center mx-auto mb-4",children:e.jsx(je,{className:"w-8 h-8 text-primary"})}),e.jsx("h1",{className:"text-3xl font-serif mb-2",children:"Admin Login"}),e.jsx("p",{className:"text-muted-foreground text-sm",children:"Sign in to manage your content"})]}),e.jsxs("form",{onSubmit:b,className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-2",children:"Username"}),e.jsx(N,{value:m,onChange:o=>l(o.target.value),placeholder:"Enter username",required:!0,className:"bg-background/50 border-white/10","data-testid":"input-username"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-2",children:"Password"}),e.jsx(N,{type:"password",value:i,onChange:o=>c(o.target.value),placeholder:"Enter password",required:!0,className:"bg-background/50 border-white/10","data-testid":"input-password"})]}),r&&e.jsx("p",{className:"text-red-400 text-sm text-center",children:r}),e.jsx(p,{type:"submit",disabled:a,className:"w-full bg-primary text-primary-foreground hover:bg-primary/90 rounded-full h-12","data-testid":"button-login",children:a?e.jsx(k,{className:"h-4 w-4 animate-spin"}):"Sign In"})]})]})})})})}async function Q(s){const m=await fetch("/api/uploads/request-url",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:s.name,size:s.size,contentType:s.type})});if(!m.ok)throw new Error("Failed to get upload URL");const{uploadURL:l}=await m.json();if(!(await fetch(l,{method:"PUT",body:s,headers:{"Content-Type":"application/pdf"}})).ok)throw new Error("Failed to upload");return l}function $e({showToast:s}){const m=B(),[l,i]=h.useState(null),[c,r]=h.useState(null),[x,a]=h.useState(!1),[u,b]=h.useState(""),[o,y]=h.useState(null),[C,S]=h.useState(!1),{data:w,isLoading:z}=q({queryKey:["/api/admin/menu-pdfs"],queryFn:async()=>{const t=await fetch("/api/admin/menu-pdfs");if(!t.ok)throw new Error("Failed to fetch menu PDFs");return t.json()}}),g=()=>{m.invalidateQueries({queryKey:["/api/admin/menu-pdfs"]}),m.invalidateQueries({queryKey:["/api/menu-pdfs"]})},M=async(t,n)=>{const d=await fetch(`/api/menu-pdfs/${t}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(!d.ok)throw new Error("Update failed");return d.json()},F=async(t,n)=>{if(n.type!=="application/pdf"){s("Please select a PDF file","error");return}i(t);try{const d=await Q(n);await M(t,{pdfUrl:d,filename:n.name}),g(),s("Menu PDF updated","success")}catch(d){console.error(d),s("Upload failed. Please try again.","error")}finally{i(null)}},E=async t=>{i(t.slot);try{await M(t.slot,{isHidden:!t.isHidden}),g(),s(t.isHidden?"Menu shown on site":"Menu hidden from site","success")}catch{s("Could not update visibility","error")}finally{i(null)}},H=async(t,n)=>{if(!(!n.trim()||n.trim()===t.title)){i(t.slot);try{await M(t.slot,{title:n.trim()}),g(),s("Title updated","success")}catch{s("Could not update title","error")}finally{i(null)}}},L=async(t,n)=>{if(!w)return;const d=t+n;if(d<0||d>=w.length)return;const j=[...w];[j[t],j[d]]=[j[d],j[t]],m.setQueryData(["/api/admin/menu-pdfs"],j);try{if(!(await fetch("/api/menu-pdfs/reorder",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({slots:j.map(D=>D.slot)})})).ok)throw new Error;g()}catch{g(),s("Could not save order","error")}},U=async()=>
86{if(c){i(c.slot);try{if(!(await fetch(`/api/menu-pdfs/${c.slot}`,{method:"DELETE"})).ok)throw new Error;g(),s("Menu removed","success"),r(null)}catch{s("Could not delete menu","error")}finally{i(null)}}},A=async t=>{if(t.preventDefault(),!u.trim()||!o){s("Please enter a title and choose a PDF","error");return}if(o.type!=="application/pdf"){s("Please select a PDF file","error");return}S(!0);try{const n=await Q(o);if(!(await fetch("/api/menu-pdfs",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:u.trim(),pdfUrl:n,filename:o.name})})).ok)throw new Error;g(),s("Menu added","success"),b(""),y(null),a(!1)}catch{s("Could not add menu. Please try again.","error")}finally{S(!1)}};return e.jsxs("div",{children:[e.jsx(O,{children:c&&e.jsx(X,{title:"Delete menu",itemName:c.title,bodyPrefix:"Are you sure you want to delete ",bodySuffix:"? This will remove it from the website immediately.",confirmLabel:"Delete",isPending:l===c.slot,onConfirm:U,onCancel:()=>r(null)})}),e.jsxs("div",{className:"flex items-start md:items-center justify-between flex-col md:flex-row gap-4 mb-8",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl md:text-4xl font-serif mb-2",children:"Menu PDFs"}),e.jsx("p",{className:"text-muted-foreground text-sm",children:"Add, reorder, hide, and replace the menus shown on your site."})]}),!x&&e.jsxs(p,{onClick:()=>a(!0),className:"bg-primary text-primary-foreground hover:bg-primary/90 rounded-full px-5","data-testid":"button-add-menu",children:[e.jsx(_,{size:18,className:"mr-2"})," Add Menu"]})]}),x&&e.jsxs(v.form,{onSubmit:A,initial:{opacity:0,y:-10},animate:{opacity:1,y:0},className:"bg-card/30 border border-white/5 rounded-2xl p-6 mb-8 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"text-lg font-serif",children:"Add a new menu"}),e.jsx(p,{type:"button",variant:"ghost",size:"icon",onClick:()=>{a(!1),b(""),y(null)},children:e.jsx(R,{size:18})})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium mb-2",children:["Menu name ",e.jsx("span",{className:"text-red-400",children:"*"})]}),e.jsx(N,{value:u,onChange:t=>b(t.target.value),placeholder:"e.g., Christmas Menu",className:"bg-background/50 border-white/10",required:!0,"data-testid":"input-new-menu-title"})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium mb-2",children:["PDF file ",e.jsx("span",{className:"text-red-400",children:"*"})]}),e.jsx("input",{type:"file",accept:"application/pdf",onChange:t=>y(t.target.files?.[0]||null),className:"block w-full text-sm text-muted-foreground file:mr-4 file:rounded-full file:border-0 file:bg-primary/10 file:text-primary file:px-4 file:py-2 file:font-medium hover:file:bg-primary hover:file:text-white file:cursor-pointer","data-testid":"input-new-menu-file"}),o&&e.jsx("p",{className:"text-xs text-muted-foreground mt-2",children:o.name})]}),e.jsxs("div",{className:"flex gap-3 pt-2",children:[e.jsxs(p,{type:"submit",disabled:C,className:"bg-primary text-primary-foreground hover:bg-primary/90 rounded-full px-6","data-testid":"button-save-new-menu",children:[C?e.jsx(k,{size:16,className:"animate-spin mr-2"}):e.jsx(W,{size:16,className:"mr-2"}),"Add menu"]}),e.jsx(p,{type:"button",variant:"outline",onClick:()=>{a(!1),b(""),y(null)},className:"rounded-full px-6 border-white/10",children:"Cancel"})]})]}),z?e.jsx("div",{className:"flex justify-center py-20",children:e.jsx(k,{className:"h-8 w-8 animate-spin text-primary"})}):w&&w.length===0?e.jsxs("div",{className:"text-center py-16 bg-card/30 border border-white/5 rounded-2xl",children:[e.jsx(G,{className:"w-12 h-12 text-primary mx-auto mb-3 opacity-50"}),e.jsx("p",{className:"text-muted-foreground",children:'No menus yet. Click "Add Menu" to upload your first PDF.'})]}):e.jsx("div",{className:"space-y-3",children:w?.map((t,n)=>{const d=l===t.slot,j=new Date(t.updatedAt).toLocaleDateString("en-GB",{day:"numeric",month:"short",year:"numeric"});return e.jsxs(v.div,{layout:!0,initial:{opacity:0}
86,animate:{opacity:1},className:`bg-card/30 border rounded-xl p-4 md:p-5 flex flex-col md:flex-row md:items-center gap-4 transition-colors ${t.isHidden?"border-white/5 opacity-60":"border-white/5 hover:border-white/10"}`,"data-testid":`row-menu-pdf-${t.slot}`,children:[e.jsxs("div",{className:"flex flex-col gap-1 flex-shrink-0",children:[e.jsx("button",{type:"button",onClick:()=>L(n,-1),disabled:n===0||d,className:"w-7 h-7 rounded-md flex items-center justify-center border border-white/10 hover:bg-white/5 disabled:opacity-30 disabled:hover:bg-transparent",title:"Move up","data-testid":`button-move-up-${t.slot}`,children:e.jsx(le,{size:14})}),e.jsx("button",{type:"button",onClick:()=>L(n,1),disabled:n===(w?.length||0)-1||d,className:"w-7 h-7 rounded-md flex items-center justify-center border border-white/10 hover:bg-white/5 disabled:opacity-30 disabled:hover:bg-transparent",title:"Move down","data-testid":`button-move-down-${t.slot}`,children:e.jsx(ie,{size:14})})]}),e.jsxs("div",{className:"flex-grow min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2 flex-wrap",children:[e.jsx(Fe,{value:t.title,onSave:P=>H(t,P),testId:`input-menu-title-${t.slot}`}),t.isHidden&&e.jsxs("span",{className:"text-xs px-2 py-0.5 rounded-full bg-white/10 text-white/60 flex items-center gap-1",children:[e.jsx(V,{size:10})," Hidden"]})]}),e.jsx("p",{className:"text-xs text-muted-foreground truncate",title:t.filename,children:t.filename}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-0.5",children:["Updated ",j]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2 flex-shrink-0",children:[e.jsxs("a",{href:t.pdfUrl,target:"_blank",rel:"noopener noreferrer",className:"px-3 h-9 inline-flex items-center gap-1.5 rounded-full text-xs font-medium border border-white/10 hover:bg-white/5 transition-colors","data-testid":`link-view-pdf-${t.slot}`,children:[e.jsx(te,{size:13})," View"]}),e.jsxs("label",{className:`px-3 h-9 inline-flex items-center gap-1.5 rounded-full text-xs font-medium border border-white/10 cursor-pointer transition-colors ${d?"opacity-50 cursor-wait":"hover:bg-primary hover:text-white hover:border-primary"}`,children:[e.jsx("input",{type:"file",accept:"application/pdf",className:"hidden",disabled:d,onChange:P=>{const D=P.target.files?.[0];D&&F(t.slot,D),P.target.value=""},"data-testid":`input-pdf-${t.slot}`}),d?e.jsx(k,{size:13,className:"animate-spin"}):e.jsx(ze,{size:13}),"Replace"]}),e.jsx("button",{type:"button",onClick:()=>E(t),disabled:d,className:"px-3 h-9 inline-flex items-center gap-1.5 rounded-full text-xs font-medium border border-white/10 hover:bg-white/5 transition-colors disabled:opacity-50","data-testid":`button-toggle-hidden-${t.slot}`,children:t.isHidden?e.jsxs(e.Fragment,{children:[e.jsx(J,{size:13})," Show"]}):e.jsxs(e.Fragment,{children:[e.jsx(V,{size:13})," Hide"]})}),e.jsx("button",{type:"button",onClick:()=>r(t),disabled:d,className:"w-9 h-9 inline-flex items-center justify-center rounded-full border border-white/10 hover:bg-red-500 hover:text-white hover:border-red-500 transition-colors disabled:opacity-50",title:"Delete menu","data-testid":`button-delete-menu-${t.slot}`,children:e.jsx($,{size:14})})]})]},t.slot)})})]})}function Fe({value:s,onSave:m,testId:l}){const[i,c]=h.useState(!1),[r,x]=h.useState(s);return i?e.jsx("form",{onSubmit:a=>{a.preventDefault(),c(!1),m(r)},className:"flex items-center gap-2",children:e.jsx(N,{autoFocus:!0,value:r,onChange:a=>x(a.target.value),onBlur:()=>{c(!1),m(r)},className:"h-8 bg-background/50 border-white/10 text-base"})}):e.jsx("button",{type:"button",onClick:()=>{x(s),c(!0)},className:"font-serif text-lg text-left hover:text-primary transition-colors",title:"Click to rename","data-testid":l,children:s})}function Ae({showToast:s,onSessionExpired:m}){const l=B(),[i,c]=h.useState(null),[r,x]=h.useState(!1),[a,u]=h.useState(I),[b,o]=h.useState(""),[y,C]=h.useState(null),{data:S,isLoading:w}=q({queryKey:["/api/articles"],queryFn:async()=>{const t=await fetch("/api/articles");if(!t.ok)throw new Error("Failed to fetch articles");return t.json()}}),z=t=>{if(t.status===401)throw m(),new Error("Session expired")},g=T({mutationFn:async t=>{const n=await fetch("/api/articles",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok)throw z(n),new Error("Failed to create article");return n.json()},onSuccess:()=>
86{l.invalidateQueries({queryKey:["/api/articles"]}),E(),s("Article created successfully!","success")},onError:()=>s("Failed to create article. Please try again.","error")}),M=T({mutationFn:async({id:t,article:n})=>{const d=await fetch(`/api/articles/${t}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(!d.ok)throw z(d),new Error("Failed to update article");return d.json()},onSuccess:()=>{l.invalidateQueries({queryKey:["/api/articles"]}),E(),s("Article updated successfully!","success")},onError:()=>s("Failed to update article. Please try again.","error")}),F=T({mutationFn:async t=>{const n=await fetch(`/api/articles/${t}`,{method:"DELETE"});if(!n.ok)throw z(n),new Error("Failed to delete article")},onSuccess:()=>{l.invalidateQueries({queryKey:["/api/articles"]}),C(null),s("Article deleted successfully!","success")},onError:()=>s("Failed to delete article. Please try again.","error")}),E=()=>{c(null),x(!1),u(I),o("")},H=t=>{c(t),x(!1),u({title:t.title,type:t.type,date:t.date,time:t.time,description:t.description,content:t.content,image:t.image,ctaText:t.ctaText,ctaLink:t.ctaLink}),o(t.content.join(` 87 88`)),window.scrollTo({top:0,behavior:"smooth"})},L=()=>{x(!0),c(null),u(I),o(""),window.scrollTo({top:0,behavior:"smooth"})},U=t=>{t.preventDefault();const n=b.split(` 89 90`).filter(j=>j.trim()),d={...a,content:n};i?M.mutate({id:i.id,article:d}):g.mutate(d)},A=g.isPending||M.isPending;return e.jsxs("div",{children:[e.jsx(O,{children:y&&e.jsx(X,{title:"Delete article",itemName:y.title,bodyPrefix:"Are you sure you want to delete ",bodySuffix:"? This action cannot be undone.",confirmLabel:"Delete",isPending:F.isPending,onConfirm:()=>F.mutate(y.id),onCancel:()=>C(null)})}),e.jsxs("div",{className:"flex items-start md:items-center justify-between flex-col md:flex-row gap-4 mb-8",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl md:text-4xl font-serif mb-2",children:"Events & News"}),e.jsx("p",{className:"text-muted-foreground text-sm",children:"Manage articles shown on your events page."})]}),!r&&!i&&e.jsxs(p,{onClick:L,className:"bg-primary text-primary-foreground hover:bg-primary/90 rounded-full px-6","data-testid":"button-create-article",children:[e.jsx(_,{size:18,className:"mr-2"})," New Article"]})]}),(r||i)&&e.jsxs(v.div,{initial:{opacity:0,y:-10},animate:{opacity:1,y:0},className:"bg-card/30 border border-white/5 rounded-2xl p-6 md:p-8 mb-8",children:[e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsx("h2",{className:"text-2xl font-serif",children:i?"Edit Article":"New Article"}),e.jsx(p,{variant:"ghost",size:"icon",onClick:E,"data-testid":"button-cancel",children:e.jsx(R,{size:20})})]}),e.jsxs("form",{onSubmit:U,className:"space-y-6",children:[e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium mb-2",children:["Title ",e.jsx("span",{className:"text-red-400",children:"*"})]}),e.jsx(N,{value:a.title,onChange:t=>u({...a,title:t.target.value}),placeholder:"Article title",required:!0,className:"bg-background/50 border-white/10","data-testid":"input-title"})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium mb-2",children:["Type ",e.jsx("span",{className:"text-red-400",children:"*"})]}),e.jsxs("select",{value:a.type,onChange:t=>u({...a,type:t.target.value}),className:"w-full h-10 px-3 rounded-md bg-background/50 border border-white/10 text-sm","data-testid":"select-type",children:[e.jsx("option",{value:"News",children:"News"}),e.jsx("option",{value:"Event",children:"Event"})]})]})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium mb-2",children:["Date ",e.jsx("span",{className:"text-red-400",children:"*"})]}),e.jsx(N,{value:a.date,onChange:t=>u({...a,date:t.target.value}),placeholder:"e.g., February 15, 2026",required:!0,className:"bg-background/50 border-white/10","data-testid":"input-date"})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium mb-2",children:["Time ",e.jsx("span",{className:"text-muted-foreground text-xs",children:"(optional)"})]}),e.jsx(N,{value:a.time||"",onChange:t=>u({...a,time:t.target.value||null}),placeholder:"e.g., 7:00 PM",className:"bg-background/50 border-white/10","data-testid":"input-time"})]})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium mb-2",children:["Description ",e.jsx("span",{className:"text-red-400",children:"*"})," ",e.jsx("span",{className:"text-muted-foreground text-xs",children:"(shown on card)"})]}),e.jsx(K,{value:a.description,onChange:t=>u({...a,description:t.target.value}),placeholder:"Brief description for the article card",required:!0,className:"bg-background/50 border-white/10",rows:2,"data-testid":"input-description"}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:[a.description.length," characters"]})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium mb-2",children:["Image URL ",e.jsx("span",{className:"text-red-400",children:"*"})]}),e.jsx(N,{value:a.image,onChange:t=>u({...a,image:t.target.value}),placeholder:"https://images.unsplash.com/...",required:!0,className:"bg-background/50 border-white/10","data-testid":"input-image"}),a.image&&e.jsxs("div",{className:"mt-3",children:[e.jsx("p",{className:"text-xs text-muted-foreground mb-2",children:"Image Preview:"}),e.jsxs("div",{className:"relative aspect-video max-w-md rounded-lg overflow-hidden bg-background/30 border border-white/5",children:[e.jsx("img",{src:a.image,alt:"Preview",className:"w-full h-full object-cover",onError:t=>{t.target.style.display="none",t.target.nextElementSibling?.classList.remove("hidden")},onLoad:t=>{t.target.style.display="block",t.target.nextElementSibling?.classList.add("hidden")}}),e.jsx("div",{className:"hidden absolute inset-0 flex items-center justify-center text-muted-foreground",children:e.jsxs("div",{className:"text-center",children:[e.jsx(ue,{size:32,className:"mx-auto mb-2 opacity-50"}),e.jsx("p",{className:"text-sm",children:"Unable to load image"})]})})]})]})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium mb-2",children:["Full Content ",e.jsx("span",{className:"text-red-400",children:"*"})]}),e.jsx(K,{value:b,onChange:t=>o(t.target.value),placeholder:"Write your article content here. Separate paragraphs with blank lines.",required:!0,className:"bg-background/50 border-white/10 font-mono text-sm",rows:10,"data-testid":"input-content"}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:[b.split(` 91 92`).filter(t=>t.trim()).length," paragraphs ⢠Separate paragraphs with blank lines"]})]}),e.jsxs("div",{className:"border-t border-white/5 pt-6",children:[e.jsxs("h3",{className:"text-lg font-medium mb-4",children:["Call to Action Button ",e.jsx("span",{className:"text-muted-foreground text-sm font-normal",children:"(optional)"})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-6",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-2",children:"Button Text"}),e.jsx(N,{value:a.ctaText||"",onChange:t=>u({...a,ctaText:t.target.value||null}),placeholder:"e.g., Book Now",className:"bg-background/50 border-white/10","data-testid":"input-cta-text"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-2",children:"Button Link"}),e.jsx(N,{value:a.ctaLink||"",onChange:t=>u({...a,ctaLink:t.target.value||null}),placeholder:"https://...",className:"bg-background/50 border-white/10","data-testid":"input-cta-link"})]})]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-2",children:"Leave empty to use default reservation link."})]}),e.jsxs("div",{className:"flex gap-4 pt-4 border-t border-white/5",children:[e.jsxs(p,{type:"submit",disabled:A,className:"bg-primary text-primary-foreground hover:bg-primary/90 rounded-full px-8","data-testid":"button-save",children:[A?e.jsx(k,{className:"h-4 w-4 animate-spin mr-2"}):e.jsx(W,{size:18,className:"mr-2"}),i?"Update Article":"Create Article"]}),e.jsx(p,{type:"button",variant:"outline",onClick:E,className:"rounded-full px-8 border-white/10",children:"Cancel"})]})]})]}),w?e.jsx("div",{className:"flex justify-center py-20",children:e.jsx(k,{className:"h-8 w-8 animate-spin text-primary"})}):S&&S.length===0?e.jsxs("div",{className:"text-center py-20 bg-card/30 border border-white/5 rounded-2xl",children:[e.jsx("div",{className:"w-16 h-16 bg-primary/10 rounded-full flex items-center justify-center mx-auto mb-4",children:e.jsx(_,{className:"w-8 h-8 text-primary"})}),e.jsx("h3",{className:"text-xl font-serif mb-2",children:"No articles yet"}),e.jsx("p",{className:"text-muted-foreground mb-6",children:"Create your first article to get started"}),e.jsxs(p,{onClick:L,className:"bg-primary text-primary-foreground hover:bg-primary/90 rounded-full px-6",children:[e.jsx(_,{size:18,className:"mr-2"})," Create Article"]})]}):e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-sm text-muted-foreground mb-4",children:[S?.length," article",S?.length!==1?"s":""]}),S?.map(t=>e.jsxs(v.div,{initial:{opacity:0}
92,animate:{opacity:1},layout:!0,className:"bg-card/30 border border-white/5 rounded-xl p-4 md:p-6 flex items-center gap-4 md:gap-6 hover:border-white/10 transition-colors","data-testid":`row-article-${t.id}`,children:[e.jsx("img",{src:t.image,alt:t.title,className:"w-20 h-14 md:w-28 md:h-20 object-cover rounded-lg flex-shrink-0"}),e.jsxs("div",{className:"flex-grow min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 md:gap-3 mb-1 flex-wrap",children:[e.jsx("span",{className:`text-xs px-2 py-0.5 rounded-full ${t.type==="Event"?"bg-primary/20 text-primary":"bg-white/10 text-white/70"}`,children:t.type}),e.jsx("span",{className:"text-xs text-muted-foreground",children:t.date}),t.time&&e.jsxs("span",{className:"text-xs text-muted-foreground hidden md:inline",children:["⢠",t.time]})]}),e.jsx("h3",{className:"font-serif text-base md:text-lg truncate",children:t.title}),e.jsx("p",{className:"text-xs text-muted-foreground truncate hidden md:block mt-1",children:t.description})]}),e.jsxs("div",{className:"flex gap-2 flex-shrink-0",children:[e.jsx(Z,{href:`/article/${t.id}`,children:e.jsx(p,{variant:"outline",size:"icon",className:"rounded-full border-white/10 hover:bg-white/5","data-testid":`button-view-${t.id}`,title:"View article",children:e.jsx(J,{size:16})})}),e.jsx(p,{variant:"outline",size:"icon",onClick:()=>H(t),className:"rounded-full border-white/10 hover:bg-primary hover:text-white hover:border-primary","data-testid":`button-edit-${t.id}`,title:"Edit article",children:e.jsx(ke,{size:16})}),e.jsx(p,{variant:"outline",size:"icon",onClick:()=>C(t),className:"rounded-full border-white/10 hover:bg-red-500 hover:text-white hover:border-red-500","data-testid":`button-delete-${t.id}`,title:"Delete article",children:e.jsx($,{size:16})})]})]},t.id))]})]})}function De({showToast:s}){const m=B(),{data:l,isLoading:i}=q({queryKey:["/api/contact-submissions"],queryFn:async()=>{const r=await fetch("/api/contact-submissions");if(!r.ok)throw new Error("Failed to fetch submissions");return r.json()}}),c=T({mutationFn:async r=>{if(!(await fetch(`/api/contact-submissions/${r}`,{method:"DELETE"})).ok)throw new Error("Failed to delete")},onSuccess:()=>{m.invalidateQueries({queryKey:["/api/contact-submissions"]}),s("Submission deleted","success")},onError:()=>s("Failed to delete submission","error")});return e.jsxs("div",{children:[e.jsxs("div",{className:"mb-8",children:[e.jsx("h1",{className:"text-3xl md:text-4xl font-serif mb-2",children:"Contact Submissions"}),e.jsx("p",{className:"text-muted-foreground text-sm",children:"Messages sent through your contact form."})]}),i?e.jsx("div",{className:"flex justify-center py-20",children:e.jsx(k,{className:"h-8 w-8 animate-spin text-primary"})}):!l||l.length===0?e.jsxs("div",{className:"text-center py-20 bg-card/30 border border-white/5 rounded-2xl",children:[e.jsx(he,{className:"w-12 h-12 text-primary mx-auto mb-3 opacity-50"}),e.jsx("p",{className:"text-muted-foreground",children:"No contact submissions yet."})]}):e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-sm text-muted-foreground mb-4",children:[l.length," message",l.length!==1?"s":""]}),l.map(r=>e.jsx(v.div,{initial:{opacity:0}
92,animate:{opacity:1},className:"bg-card/30 border border-white/5 rounded-xl p-6 hover:border-white/10 transition-colors","data-testid":`row-contact-${r.id}`,children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"flex-grow min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-2 flex-wrap",children:[e.jsxs("h3",{className:"font-semibold",children:[r.firstName," ",r.lastName]}),e.jsx("a",{href:`mailto:${r.email}`,className:"text-xs text-muted-foreground hover:text-primary",children:r.email}),e.jsx("span",{className:"text-xs text-muted-foreground",children:new Date(r.createdAt).toLocaleDateString("en-GB",{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"})})]}),e.jsx("p",{className:"text-sm text-primary mb-1 font-medium",children:r.subject}),e.jsx("p",{className:"text-sm text-muted-foreground whitespace-pre-wrap",children:r.message})]}),e.jsx(p,{variant:"outline",size:"icon",onClick:()=>c.mutate(r.id),className:"rounded-full border-white/10 hover:bg-red-500 hover:text-white hover:border-red-500 flex-shrink-0","data-testid":`button-delete-contact-${r.id}`,title:"Delete submission",children:e.jsx($,{size:16})})]})},r.id))]})]})}function Oe(){const[s,m]=h.useState("menus"),[l,i]=h.useState(null),c=(o,y)=>{i({message:o,type:y}),setTimeout(()=>i(null),4e3)},{data:r,isLoading:x,refetch:a}=q({queryKey:["/api/auth/status"],queryFn:async()=>(await fetch("/api/auth/status")).json()}),u=async()=>{await fetch("/api/auth/logout",{method:"POST"}),a()};if(x)return e.jsx("div",{className:"min-h-screen bg-background flex justify-center items-center",children:e.jsx(k,{className:"h-8 w-8 animate-spin text-primary"})});if(!r?.isAuthenticated)return e.jsx(Pe,{onLogin:()=>a()});const b=[{key:"menus",label:"Menu PDFs",icon:G},{key:"articles",label:"Events & News",icon:ve},{key:"contact",label:"Contact Form",icon:Y}];return e.jsxs("div",{className:"min-h-screen bg-background pt-32 md:pt-44",children:[e.jsx(O,{children:l&&e.jsx(Le,{message:l.message,type:l.type,onClose:()=>i(null)})}),e.jsx("div",{className:"border-b border-white/5 bg-card/20 backdrop-blur-sm",children:e.jsxs("div",{className:"max-w-7xl mx-auto px-4 md:px-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-2 py-3",children:[e.jsx(fe,{className:"w-4 h-4 text-primary"}),e.jsx("span",{className:"text-xs uppercase tracking-[0.25em] text-muted-foreground font-semibold",children:"Admin Portal"})]}),e.jsxs(p,{onClick:u,variant:"outline",size:"sm",className:"rounded-full border-white/10 text-xs","data-testid":"button-logout",children:[e.jsx(be,{size:14,className:"mr-2"})," Logout"]})]}),e.jsx("nav",{className:"flex gap-1 overflow-x-auto -mb-px scrollbar-none",children:b.map(o=>{const y=o.icon,C=s===o.key;return e.jsxs("button",{onClick:()=>m(o.key),className:`flex items-center gap-2 px-4 py-3 text-sm font-medium whitespace-nowrap transition-colors border-b-2 ${C?"border-primary text-primary":"border-transparent text-muted-foreground hover:text-white"}`,"data-testid":`nav-${o.key}`,children:[e.jsx(y,{size:15}),o.label]},o.key)})})]})}),e.jsx("main",{className:"max-w-7xl mx-auto px-4 md:px-6 pt-8 md:pt-10 pb-16",children:e.jsxs(v.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},transition:{duration:.2},children:[s==="menus"&&e.jsx($e,{showToast:c}),s==="articles"&&e.jsx(Ae,{showToast:c,onSessionExpired:()=>a()}),s==="contact"&&e.jsx(De,{showToast:c})]},s)})]})}export{Oe 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.