@zenith-open/zenithcms-admin 1.0.0-beta.4 → 1.0.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/assets/{ApiExplorerPage-UJpoKRI0.js → ApiExplorerPage-CLsHG-Ke.js} +1 -1
  2. package/dist/assets/{ApiExplorerPage-UJpoKRI0.js.map → ApiExplorerPage-CLsHG-Ke.js.map} +1 -1
  3. package/dist/assets/{AuditLogPage-8xYlRl1I.js → AuditLogPage-Bp2Nvabr.js} +1 -1
  4. package/dist/assets/{AuditLogPage-8xYlRl1I.js.map → AuditLogPage-Bp2Nvabr.js.map} +1 -1
  5. package/dist/assets/{BlockBuilderPage-DcOo3Vnt.js → BlockBuilderPage-CeVMk5Ns.js} +1 -1
  6. package/dist/assets/{BlockBuilderPage-DcOo3Vnt.js.map → BlockBuilderPage-CeVMk5Ns.js.map} +1 -1
  7. package/dist/assets/{CollectionHooksPage-Dn_ujtlp.js → CollectionHooksPage-EFkVZNrc.js} +1 -1
  8. package/dist/assets/{CollectionHooksPage-Dn_ujtlp.js.map → CollectionHooksPage-EFkVZNrc.js.map} +1 -1
  9. package/dist/assets/{CollectionsPage-BSPHf7H2.js → CollectionsPage-D-N_ykJz.js} +1 -1
  10. package/dist/assets/{CollectionsPage-BSPHf7H2.js.map → CollectionsPage-D-N_ykJz.js.map} +1 -1
  11. package/dist/assets/{ComponentBuilderPage-CT6S12LA.js → ComponentBuilderPage-C3mhOLPs.js} +1 -1
  12. package/dist/assets/{ComponentBuilderPage-CT6S12LA.js.map → ComponentBuilderPage-C3mhOLPs.js.map} +1 -1
  13. package/dist/assets/{DashboardBuilder-Cbi9Ddiu.js → DashboardBuilder-Beiurp0v.js} +1 -1
  14. package/dist/assets/{DashboardBuilder-Cbi9Ddiu.js.map → DashboardBuilder-Beiurp0v.js.map} +1 -1
  15. package/dist/assets/{PluginsPage-5YRpbP-N.js → PluginsPage-BjPoOvBl.js} +1 -1
  16. package/dist/assets/{PluginsPage-5YRpbP-N.js.map → PluginsPage-BjPoOvBl.js.map} +1 -1
  17. package/dist/assets/{RedirectsPage-D_4jAdaI.js → RedirectsPage-GIZCbEll.js} +1 -1
  18. package/dist/assets/{RedirectsPage-D_4jAdaI.js.map → RedirectsPage-GIZCbEll.js.map} +1 -1
  19. package/dist/assets/{SchemaBuilderPage-EFA5XIAa.js → SchemaBuilderPage-3CDbJi28.js} +1 -1
  20. package/dist/assets/{SchemaBuilderPage-EFA5XIAa.js.map → SchemaBuilderPage-3CDbJi28.js.map} +1 -1
  21. package/dist/assets/{SettingsPage-BRpcMw48.js → SettingsPage-DYYNnxkV.js} +1 -1
  22. package/dist/assets/{SettingsPage-BRpcMw48.js.map → SettingsPage-DYYNnxkV.js.map} +1 -1
  23. package/dist/assets/{SpatialEditor-CPgS7Zrd.js → SpatialEditor-DlyP5PPa.js} +1 -1
  24. package/dist/assets/{SpatialEditor-CPgS7Zrd.js.map → SpatialEditor-DlyP5PPa.js.map} +1 -1
  25. package/dist/assets/{TemplatesPage-B-nNYv3o.js → TemplatesPage-DfeCDCe_.js} +1 -1
  26. package/dist/assets/{TemplatesPage-B-nNYv3o.js.map → TemplatesPage-DfeCDCe_.js.map} +1 -1
  27. package/dist/assets/{TrashPage-Ccusal1w.js → TrashPage-DGi-7RPl.js} +1 -1
  28. package/dist/assets/{TrashPage-Ccusal1w.js.map → TrashPage-DGi-7RPl.js.map} +1 -1
  29. package/dist/assets/{index-ChcKY5Xe.js → index-C4J6QNLn.js} +3 -3
  30. package/dist/assets/index-C4J6QNLn.js.map +1 -0
  31. package/dist/assets/index-Umj4hIVD.css +1 -0
  32. package/dist/index.html +45 -3
  33. package/dist/sw.js +1 -1
  34. package/dist/sw.js.map +1 -1
  35. package/package.json +2 -2
  36. package/dist/assets/index-ChcKY5Xe.js.map +0 -1
  37. package/dist/assets/index-CxhwdV2K.css +0 -1
@@ -1 +1 @@
1
- import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{C as t,En as n,H as r,Ht as i,Ln as a,Q as o,_n as s,ir as c,l,rr as u,rt as d,vn as f,vr as p,xr as m}from"./vendor-react-DQVTOTFO.js";import{a as h,o as g,t as _}from"./utils-fgvbH6CB.js";import{d as v,f as y,p as b}from"./index-ChcKY5Xe.js";var x=e(m(),1),S=p(),C=[`301`,`302`,`307`,`308`],w=()=>{let{theme:e}=h(),p=e===`dark`,[m,w]=(0,x.useState)([]),[T,E]=(0,x.useState)(!0),[D,O]=(0,x.useState)(``),[k,A]=(0,x.useState)(1),[j,M]=(0,x.useState)(1),[ee,N]=(0,x.useState)(0),[P,F]=(0,x.useState)(!1),[I,L]=(0,x.useState)(null),[R,z]=(0,x.useState)(null),[B,V]=(0,x.useState)(``),[H,U]=(0,x.useState)(``),[W,G]=(0,x.useState)(`301`),[K,q]=(0,x.useState)(!1),J=(0,x.useCallback)(async()=>{E(!0);try{let e=(await g.get(`/redirects`,{params:{page:k,limit:20,search:D||void 0}})).data;w(e.data||[]),M(e.meta?.pagination?.totalPages||1),N(e.meta?.pagination?.total||0)}catch{l.error(`Failed to load redirects`)}finally{E(!1)}},[k,D]);(0,x.useEffect)(()=>{J()},[J]);let Y=()=>{L(null),V(``),U(``),G(`301`),F(!0)},X=e=>{L(e),V(e.from),U(e.to),G(e.type),F(!0)},Z=async()=>{if(!B||!H){l.error(`Both "From" and "To" paths are required`);return}q(!0);try{I?(await g.patch(`/redirects/${I._id}`,{from:B,to:H,type:W}),l.success(`Redirect updated`)):(await g.post(`/redirects`,{from:B,to:H,type:W}),l.success(`Redirect created`)),F(!1),J()}catch(e){let t=e.response?.data?.error?.message||(e instanceof Error?e.message:String(e))||`Failed to save redirect`;l.error(t)}finally{q(!1)}},Q=async e=>{try{await g.delete(`/redirects/${e}`),l.success(`Redirect deleted`),z(null),J()}catch{l.error(`Failed to delete redirect`)}},$=e=>{switch(e){case`301`:return`text-amber-500 border-amber-500/30`;case`302`:return`text-z-active-text border-z-active-border`;case`307`:return`text-z-secondary border-z-border/30`;case`308`:return`text-z-secondary border-z-border/30`;default:return`text-z-secondary border-z-border/30`}};return(0,S.jsxs)(`div`,{className:`flex flex-col h-[calc(100vh-64px)] overflow-hidden`,children:[(0,S.jsx)(b,{title:`URL Redirects`,description:`Manage 301 and 302 traffic routing.`,icon:(0,S.jsx)(f,{size:24}),backLink:{to:`/`,label:`Dashboard`},actions:(0,S.jsxs)(`button`,{onClick:Y,className:`flex items-center gap-2 px-6 py-2.5 bg-z-accent hover:opacity-90 shadow-sm text-z-primary text-sm font-semibold transition-all rounded-none`,children:[(0,S.jsx)(o,{size:14}),`Add Redirect`]})}),(0,S.jsxs)(`div`,{className:`flex-1 overflow-auto p-6 md:p-8 space-y-6`,children:[(0,S.jsxs)(`div`,{className:`max-w-md relative`,children:[(0,S.jsx)(r,{size:14,className:_(`absolute left-4 top-1/2 -translate-y-1/2`,p?`text-z-secondary`:`text-z-muted`)}),(0,S.jsx)(`input`,{type:`text`,value:D,onChange:e=>{O(e.target.value),A(1)},placeholder:`Search redirect paths...`,className:_(`w-full pl-10 pr-4 py-2.5 text-sm font-semibold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none shadow-sm`,`z-input`)})]}),(0,S.jsxs)(v,{children:[T?(0,S.jsx)(`div`,{className:`flex items-center justify-center py-20 gap-3`,children:(0,S.jsx)(a,{size:20,className:`animate-spin text-z-secondary`})}):m.length===0?(0,S.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-20 gap-4 opacity-50`,children:[(0,S.jsx)(f,{size:32,className:`text-z-secondary`}),(0,S.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary`,children:D?`No matching redirects`:`No redirects configured`})]}):(0,S.jsx)(`div`,{className:`overflow-x-auto min-w-full`,children:(0,S.jsxs)(`table`,{className:`w-full text-left border-collapse`,children:[(0,S.jsx)(`thead`,{children:(0,S.jsxs)(`tr`,{className:_(`text-sm font-semibold border-b`,`text-z-secondary border-z-border`),children:[(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal`,children:`From`}),(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal hidden md:table-cell`,children:`To`}),(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal w-20`,children:`Type`}),(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal w-24 hidden sm:table-cell`,children:`Hits`}),(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal w-24 hidden lg:table-cell`,children:`Last Hit`}),(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal w-24`})]})}),(0,S.jsx)(`tbody`,{children:m.map(e=>(0,S.jsxs)(`tr`,{onClick:()=>X(e),className:_(`text-xs border-b transition-colors cursor-pointer`,p?`border-z-border hover:bg-z-panel`:`border-z-border hover:bg-[var(--z-bg-input)]`),children:[(0,S.jsx)(`td`,{className:`px-5 py-4`,children:(0,S.jsx)(`code`,{className:_(`px-2 py-1 text-xs font-mono font-bold`,p?`bg-z-hover text-z-muted`:`bg-[var(--z-bg-hover)] text-z-secondary`),children:e.from})}),(0,S.jsx)(`td`,{className:`px-5 py-4 hidden md:table-cell`,children:(0,S.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,S.jsx)(s,{size:12,className:`text-z-secondary shrink-0`}),(0,S.jsx)(`span`,{className:_(`font-mono font-bold truncate max-w-[300px]`,`text-z-secondary`),children:e.to})]})}),(0,S.jsx)(`td`,{className:`px-5 py-4`,children:(0,S.jsx)(`span`,{className:_(`inline-block px-2 py-0.5 text-sm font-semibold font-mono border`,$(e.type)),children:e.type})}),(0,S.jsx)(`td`,{className:`px-5 py-4 hidden sm:table-cell`,children:(0,S.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,S.jsx)(d,{size:11,className:p?`text-z-secondary`:`text-z-muted`}),(0,S.jsx)(`span`,{className:_(`font-bold tabular-nums`,`text-z-secondary`),children:e.hits?.toLocaleString()||0})]})}),(0,S.jsx)(`td`,{className:`px-5 py-4 hidden lg:table-cell`,children:(0,S.jsx)(`span`,{className:_(`text-sm font-mono`,p?`text-z-secondary`:`text-z-muted`),children:e.lastHitAt?new Date(e.lastHitAt).toLocaleString():`—`})}),(0,S.jsx)(`td`,{className:`px-5 py-4`,children:(0,S.jsxs)(`div`,{className:`flex items-center gap-2 justify-end`,children:[(0,S.jsx)(`button`,{onClick:t=>{t.stopPropagation(),window.open(e.from,`_blank`)},className:_(`p-1.5 border transition-all`,`border-z-border text-z-secondary hover:text-z-primary`),title:`Test redirect`,children:(0,S.jsx)(i,{size:12})}),(0,S.jsx)(`button`,{onClick:t=>{t.stopPropagation(),z(e._id)},className:`p-1.5 border rounded-none border-red-500/20 text-red-500 hover:bg-red-500/10 transition-all`,title:`Delete`,children:(0,S.jsx)(t,{size:12})})]})})]},e._id))})]})}),j>1&&(0,S.jsxs)(`div`,{className:_(`flex items-center justify-between px-5 py-4 border-t`,`border-z-border`),children:[(0,S.jsxs)(`span`,{className:_(`text-sm font-bold`,`text-z-secondary`),children:[`Page `,k,` of `,j]}),(0,S.jsxs)(`div`,{className:`flex gap-2`,children:[(0,S.jsx)(`button`,{onClick:()=>A(e=>Math.max(1,e-1)),disabled:k<=1,className:_(`px-4 py-2 text-sm font-semibold border rounded-none transition-all`,`border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30`),children:`Prev`}),(0,S.jsx)(`button`,{onClick:()=>A(e=>Math.min(j,e+1)),disabled:k>=j,className:_(`px-4 py-2 text-sm font-semibold border rounded-none transition-all`,`border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30`),children:`Next`})]})]})]}),(0,S.jsx)(c,{children:P&&(0,S.jsx)(u.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:`fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4`,children:(0,S.jsx)(u.div,{initial:{opacity:0,scale:.95},animate:{opacity:1,scale:1},exit:{opacity:0,scale:.95},className:`w-full max-w-md`,children:(0,S.jsxs)(v,{children:[(0,S.jsxs)(`div`,{className:_(`px-6 py-4 border-b flex items-center justify-between`,`border-z-border`),children:[(0,S.jsx)(`h2`,{className:`text-sm font-semibold text-z-secondary`,children:I?`Edit Redirect`:`New Redirect`}),(0,S.jsx)(`button`,{onClick:()=>F(!1),className:`text-z-secondary hover:text-z-primary dark:hover:text-z-primary`,children:(0,S.jsx)(`svg`,{width:`14`,height:`14`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,children:(0,S.jsx)(`path`,{d:`M18 6L6 18M6 6l12 12`})})})]}),(0,S.jsxs)(y,{className:`p-6 space-y-4`,children:[(0,S.jsxs)(`div`,{children:[(0,S.jsx)(`label`,{className:`block text-sm font-semibold mb-1.5 text-z-secondary`,children:`From Path`}),(0,S.jsx)(`input`,{type:`text`,value:B,onChange:e=>V(e.target.value),placeholder:`/old-path`,className:_(`w-full px-4 py-2.5 text-xs font-mono font-bold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none`,p?`bg-z-panel backdrop-blur-md border-z-border text-z-primary focus:border-z-active-border`:`bg-z-input border-z-border text-z-primary focus:border-z-accent`)})]}),(0,S.jsxs)(`div`,{children:[(0,S.jsx)(`label`,{className:`block text-sm font-semibold mb-1.5 text-z-secondary`,children:`To URL`}),(0,S.jsx)(`input`,{type:`text`,value:H,onChange:e=>U(e.target.value),placeholder:`https://example.com/new-path`,className:_(`w-full px-4 py-2.5 text-xs font-mono font-bold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none`,p?`bg-z-panel backdrop-blur-md border-z-border text-z-primary focus:border-z-active-border`:`bg-z-input border-z-border text-z-primary focus:border-z-accent`)})]}),(0,S.jsxs)(`div`,{children:[(0,S.jsx)(`label`,{className:`block text-sm font-semibold mb-1.5 text-z-secondary`,children:`Redirect Type`}),(0,S.jsx)(`div`,{className:`flex gap-2`,children:C.map(e=>(0,S.jsx)(`button`,{onClick:()=>G(e),className:_(`flex-1 py-2.5 text-sm font-semibold font-mono border rounded-none transition-all`,W===e?p?`border-z-accent text-z-active-text bg-z-active-bg shadow-sm`:`border-z-accent text-z-accent bg-z-active-bg shadow-sm`:p?`border-z-border text-z-secondary hover:text-z-primary hover:bg-z-hover`:`border-z-border text-z-muted hover:text-z-primary hover:bg-[var(--z-bg-input)]`),children:e},e))})]})]}),(0,S.jsxs)(`div`,{className:_(`px-6 py-4 border-t flex justify-end gap-3`,`border-z-border`),children:[(0,S.jsx)(`button`,{onClick:()=>F(!1),className:_(`px-5 py-2.5 text-sm font-semibold transition-colors rounded-none`,p?`text-z-secondary hover:text-z-primary hover:bg-z-hover`:`text-z-secondary hover:text-z-primary hover:bg-[var(--z-bg-input)]`),children:`Cancel`}),(0,S.jsxs)(`button`,{onClick:Z,disabled:K||!B||!H,className:`px-6 py-2.5 bg-z-accent hover:opacity-90 disabled:opacity-50 text-z-primary text-sm font-semibold transition-all shadow-sm rounded-none flex items-center gap-2`,children:[K&&(0,S.jsx)(a,{size:12,className:`animate-spin`}),I?`Update`:`Create`]})]})]})})})}),(0,S.jsx)(c,{children:R&&(0,S.jsx)(u.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:`fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4`,children:(0,S.jsx)(u.div,{initial:{opacity:0,scale:.95},animate:{opacity:1,scale:1},exit:{opacity:0,scale:.95},className:`w-full max-w-sm`,children:(0,S.jsx)(v,{children:(0,S.jsxs)(y,{className:`p-8 text-center`,children:[(0,S.jsx)(n,{size:32,className:`mx-auto mb-4 text-red-500`}),(0,S.jsx)(`h3`,{className:`text-sm font-semibold mb-2 text-z-primary`,children:`Delete Redirect?`}),(0,S.jsx)(`p`,{className:`text-sm font-bold text-z-secondary mb-6`,children:`This action cannot be undone.`}),(0,S.jsxs)(`div`,{className:`flex gap-3 justify-center`,children:[(0,S.jsx)(`button`,{onClick:()=>z(null),className:_(`px-5 py-2.5 text-sm font-semibold border rounded-none transition-all`,`border-z-border text-z-secondary hover:text-z-primary`),children:`Cancel`}),(0,S.jsx)(`button`,{onClick:()=>Q(R),className:`px-5 py-2.5 bg-red-600 hover:bg-red-500 text-z-primary text-sm font-semibold transition-all rounded-none shadow-sm`,children:`Delete`})]})]})})})})})]})]})};export{w as default};
1
+ import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{C as t,En as n,H as r,Ht as i,Ln as a,Q as o,_n as s,ir as c,l,rr as u,rt as d,vn as f,vr as p,xr as m}from"./vendor-react-DQVTOTFO.js";import{a as h,o as g,t as _}from"./utils-fgvbH6CB.js";import{d as v,f as y,p as b}from"./index-C4J6QNLn.js";var x=e(m(),1),S=p(),C=[`301`,`302`,`307`,`308`],w=()=>{let{theme:e}=h(),p=e===`dark`,[m,w]=(0,x.useState)([]),[T,E]=(0,x.useState)(!0),[D,O]=(0,x.useState)(``),[k,A]=(0,x.useState)(1),[j,M]=(0,x.useState)(1),[ee,N]=(0,x.useState)(0),[P,F]=(0,x.useState)(!1),[I,L]=(0,x.useState)(null),[R,z]=(0,x.useState)(null),[B,V]=(0,x.useState)(``),[H,U]=(0,x.useState)(``),[W,G]=(0,x.useState)(`301`),[K,q]=(0,x.useState)(!1),J=(0,x.useCallback)(async()=>{E(!0);try{let e=(await g.get(`/redirects`,{params:{page:k,limit:20,search:D||void 0}})).data;w(e.data||[]),M(e.meta?.pagination?.totalPages||1),N(e.meta?.pagination?.total||0)}catch{l.error(`Failed to load redirects`)}finally{E(!1)}},[k,D]);(0,x.useEffect)(()=>{J()},[J]);let Y=()=>{L(null),V(``),U(``),G(`301`),F(!0)},X=e=>{L(e),V(e.from),U(e.to),G(e.type),F(!0)},Z=async()=>{if(!B||!H){l.error(`Both "From" and "To" paths are required`);return}q(!0);try{I?(await g.patch(`/redirects/${I._id}`,{from:B,to:H,type:W}),l.success(`Redirect updated`)):(await g.post(`/redirects`,{from:B,to:H,type:W}),l.success(`Redirect created`)),F(!1),J()}catch(e){let t=e.response?.data?.error?.message||(e instanceof Error?e.message:String(e))||`Failed to save redirect`;l.error(t)}finally{q(!1)}},Q=async e=>{try{await g.delete(`/redirects/${e}`),l.success(`Redirect deleted`),z(null),J()}catch{l.error(`Failed to delete redirect`)}},$=e=>{switch(e){case`301`:return`text-amber-500 border-amber-500/30`;case`302`:return`text-z-active-text border-z-active-border`;case`307`:return`text-z-secondary border-z-border/30`;case`308`:return`text-z-secondary border-z-border/30`;default:return`text-z-secondary border-z-border/30`}};return(0,S.jsxs)(`div`,{className:`flex flex-col h-[calc(100vh-64px)] overflow-hidden`,children:[(0,S.jsx)(b,{title:`URL Redirects`,description:`Manage 301 and 302 traffic routing.`,icon:(0,S.jsx)(f,{size:24}),backLink:{to:`/`,label:`Dashboard`},actions:(0,S.jsxs)(`button`,{onClick:Y,className:`flex items-center gap-2 px-6 py-2.5 bg-z-accent hover:opacity-90 shadow-sm text-z-primary text-sm font-semibold transition-all rounded-none`,children:[(0,S.jsx)(o,{size:14}),`Add Redirect`]})}),(0,S.jsxs)(`div`,{className:`flex-1 overflow-auto p-6 md:p-8 space-y-6`,children:[(0,S.jsxs)(`div`,{className:`max-w-md relative`,children:[(0,S.jsx)(r,{size:14,className:_(`absolute left-4 top-1/2 -translate-y-1/2`,p?`text-z-secondary`:`text-z-muted`)}),(0,S.jsx)(`input`,{type:`text`,value:D,onChange:e=>{O(e.target.value),A(1)},placeholder:`Search redirect paths...`,className:_(`w-full pl-10 pr-4 py-2.5 text-sm font-semibold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none shadow-sm`,`z-input`)})]}),(0,S.jsxs)(v,{children:[T?(0,S.jsx)(`div`,{className:`flex items-center justify-center py-20 gap-3`,children:(0,S.jsx)(a,{size:20,className:`animate-spin text-z-secondary`})}):m.length===0?(0,S.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-20 gap-4 opacity-50`,children:[(0,S.jsx)(f,{size:32,className:`text-z-secondary`}),(0,S.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary`,children:D?`No matching redirects`:`No redirects configured`})]}):(0,S.jsx)(`div`,{className:`overflow-x-auto min-w-full`,children:(0,S.jsxs)(`table`,{className:`w-full text-left border-collapse`,children:[(0,S.jsx)(`thead`,{children:(0,S.jsxs)(`tr`,{className:_(`text-sm font-semibold border-b`,`text-z-secondary border-z-border`),children:[(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal`,children:`From`}),(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal hidden md:table-cell`,children:`To`}),(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal w-20`,children:`Type`}),(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal w-24 hidden sm:table-cell`,children:`Hits`}),(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal w-24 hidden lg:table-cell`,children:`Last Hit`}),(0,S.jsx)(`th`,{className:`px-5 py-4 font-normal w-24`})]})}),(0,S.jsx)(`tbody`,{children:m.map(e=>(0,S.jsxs)(`tr`,{onClick:()=>X(e),className:_(`text-xs border-b transition-colors cursor-pointer`,p?`border-z-border hover:bg-z-panel`:`border-z-border hover:bg-[var(--z-bg-input)]`),children:[(0,S.jsx)(`td`,{className:`px-5 py-4`,children:(0,S.jsx)(`code`,{className:_(`px-2 py-1 text-xs font-mono font-bold`,p?`bg-z-hover text-z-muted`:`bg-[var(--z-bg-hover)] text-z-secondary`),children:e.from})}),(0,S.jsx)(`td`,{className:`px-5 py-4 hidden md:table-cell`,children:(0,S.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,S.jsx)(s,{size:12,className:`text-z-secondary shrink-0`}),(0,S.jsx)(`span`,{className:_(`font-mono font-bold truncate max-w-[300px]`,`text-z-secondary`),children:e.to})]})}),(0,S.jsx)(`td`,{className:`px-5 py-4`,children:(0,S.jsx)(`span`,{className:_(`inline-block px-2 py-0.5 text-sm font-semibold font-mono border`,$(e.type)),children:e.type})}),(0,S.jsx)(`td`,{className:`px-5 py-4 hidden sm:table-cell`,children:(0,S.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,S.jsx)(d,{size:11,className:p?`text-z-secondary`:`text-z-muted`}),(0,S.jsx)(`span`,{className:_(`font-bold tabular-nums`,`text-z-secondary`),children:e.hits?.toLocaleString()||0})]})}),(0,S.jsx)(`td`,{className:`px-5 py-4 hidden lg:table-cell`,children:(0,S.jsx)(`span`,{className:_(`text-sm font-mono`,p?`text-z-secondary`:`text-z-muted`),children:e.lastHitAt?new Date(e.lastHitAt).toLocaleString():`—`})}),(0,S.jsx)(`td`,{className:`px-5 py-4`,children:(0,S.jsxs)(`div`,{className:`flex items-center gap-2 justify-end`,children:[(0,S.jsx)(`button`,{onClick:t=>{t.stopPropagation(),window.open(e.from,`_blank`)},className:_(`p-1.5 border transition-all`,`border-z-border text-z-secondary hover:text-z-primary`),title:`Test redirect`,children:(0,S.jsx)(i,{size:12})}),(0,S.jsx)(`button`,{onClick:t=>{t.stopPropagation(),z(e._id)},className:`p-1.5 border rounded-none border-red-500/20 text-red-500 hover:bg-red-500/10 transition-all`,title:`Delete`,children:(0,S.jsx)(t,{size:12})})]})})]},e._id))})]})}),j>1&&(0,S.jsxs)(`div`,{className:_(`flex items-center justify-between px-5 py-4 border-t`,`border-z-border`),children:[(0,S.jsxs)(`span`,{className:_(`text-sm font-bold`,`text-z-secondary`),children:[`Page `,k,` of `,j]}),(0,S.jsxs)(`div`,{className:`flex gap-2`,children:[(0,S.jsx)(`button`,{onClick:()=>A(e=>Math.max(1,e-1)),disabled:k<=1,className:_(`px-4 py-2 text-sm font-semibold border rounded-none transition-all`,`border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30`),children:`Prev`}),(0,S.jsx)(`button`,{onClick:()=>A(e=>Math.min(j,e+1)),disabled:k>=j,className:_(`px-4 py-2 text-sm font-semibold border rounded-none transition-all`,`border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30`),children:`Next`})]})]})]}),(0,S.jsx)(c,{children:P&&(0,S.jsx)(u.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:`fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4`,children:(0,S.jsx)(u.div,{initial:{opacity:0,scale:.95},animate:{opacity:1,scale:1},exit:{opacity:0,scale:.95},className:`w-full max-w-md`,children:(0,S.jsxs)(v,{children:[(0,S.jsxs)(`div`,{className:_(`px-6 py-4 border-b flex items-center justify-between`,`border-z-border`),children:[(0,S.jsx)(`h2`,{className:`text-sm font-semibold text-z-secondary`,children:I?`Edit Redirect`:`New Redirect`}),(0,S.jsx)(`button`,{onClick:()=>F(!1),className:`text-z-secondary hover:text-z-primary dark:hover:text-z-primary`,children:(0,S.jsx)(`svg`,{width:`14`,height:`14`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,children:(0,S.jsx)(`path`,{d:`M18 6L6 18M6 6l12 12`})})})]}),(0,S.jsxs)(y,{className:`p-6 space-y-4`,children:[(0,S.jsxs)(`div`,{children:[(0,S.jsx)(`label`,{className:`block text-sm font-semibold mb-1.5 text-z-secondary`,children:`From Path`}),(0,S.jsx)(`input`,{type:`text`,value:B,onChange:e=>V(e.target.value),placeholder:`/old-path`,className:_(`w-full px-4 py-2.5 text-xs font-mono font-bold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none`,p?`bg-z-panel backdrop-blur-md border-z-border text-z-primary focus:border-z-active-border`:`bg-z-input border-z-border text-z-primary focus:border-z-accent`)})]}),(0,S.jsxs)(`div`,{children:[(0,S.jsx)(`label`,{className:`block text-sm font-semibold mb-1.5 text-z-secondary`,children:`To URL`}),(0,S.jsx)(`input`,{type:`text`,value:H,onChange:e=>U(e.target.value),placeholder:`https://example.com/new-path`,className:_(`w-full px-4 py-2.5 text-xs font-mono font-bold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none`,p?`bg-z-panel backdrop-blur-md border-z-border text-z-primary focus:border-z-active-border`:`bg-z-input border-z-border text-z-primary focus:border-z-accent`)})]}),(0,S.jsxs)(`div`,{children:[(0,S.jsx)(`label`,{className:`block text-sm font-semibold mb-1.5 text-z-secondary`,children:`Redirect Type`}),(0,S.jsx)(`div`,{className:`flex gap-2`,children:C.map(e=>(0,S.jsx)(`button`,{onClick:()=>G(e),className:_(`flex-1 py-2.5 text-sm font-semibold font-mono border rounded-none transition-all`,W===e?p?`border-z-accent text-z-active-text bg-z-active-bg shadow-sm`:`border-z-accent text-z-accent bg-z-active-bg shadow-sm`:p?`border-z-border text-z-secondary hover:text-z-primary hover:bg-z-hover`:`border-z-border text-z-muted hover:text-z-primary hover:bg-[var(--z-bg-input)]`),children:e},e))})]})]}),(0,S.jsxs)(`div`,{className:_(`px-6 py-4 border-t flex justify-end gap-3`,`border-z-border`),children:[(0,S.jsx)(`button`,{onClick:()=>F(!1),className:_(`px-5 py-2.5 text-sm font-semibold transition-colors rounded-none`,p?`text-z-secondary hover:text-z-primary hover:bg-z-hover`:`text-z-secondary hover:text-z-primary hover:bg-[var(--z-bg-input)]`),children:`Cancel`}),(0,S.jsxs)(`button`,{onClick:Z,disabled:K||!B||!H,className:`px-6 py-2.5 bg-z-accent hover:opacity-90 disabled:opacity-50 text-z-primary text-sm font-semibold transition-all shadow-sm rounded-none flex items-center gap-2`,children:[K&&(0,S.jsx)(a,{size:12,className:`animate-spin`}),I?`Update`:`Create`]})]})]})})})}),(0,S.jsx)(c,{children:R&&(0,S.jsx)(u.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:`fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4`,children:(0,S.jsx)(u.div,{initial:{opacity:0,scale:.95},animate:{opacity:1,scale:1},exit:{opacity:0,scale:.95},className:`w-full max-w-sm`,children:(0,S.jsx)(v,{children:(0,S.jsxs)(y,{className:`p-8 text-center`,children:[(0,S.jsx)(n,{size:32,className:`mx-auto mb-4 text-red-500`}),(0,S.jsx)(`h3`,{className:`text-sm font-semibold mb-2 text-z-primary`,children:`Delete Redirect?`}),(0,S.jsx)(`p`,{className:`text-sm font-bold text-z-secondary mb-6`,children:`This action cannot be undone.`}),(0,S.jsxs)(`div`,{className:`flex gap-3 justify-center`,children:[(0,S.jsx)(`button`,{onClick:()=>z(null),className:_(`px-5 py-2.5 text-sm font-semibold border rounded-none transition-all`,`border-z-border text-z-secondary hover:text-z-primary`),children:`Cancel`}),(0,S.jsx)(`button`,{onClick:()=>Q(R),className:`px-5 py-2.5 bg-red-600 hover:bg-red-500 text-z-primary text-sm font-semibold transition-all rounded-none shadow-sm`,children:`Delete`})]})]})})})})})]})]})};export{w as default};
@@ -1 +1 @@
1
- {"version":3,"file":"RedirectsPage-D_4jAdaI.js","names":[],"sources":["../../src/pages/RedirectsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react'\nimport {\n ArrowRightLeft,\n Plus,\n Search,\n Trash2,\n ExternalLink,\n Loader2,\n ArrowRight,\n MousePointerClick,\n AlertTriangle,\n} from 'lucide-react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { cn } from '../lib/utils'\nimport { useTheme } from '../context/ThemeContext'\nimport toast from 'react-hot-toast'\nimport api from '../lib/api'\nimport { PageHeader } from '../components/ui/PageHeader'\nimport { Card, CardContent } from '../components/ui/Card'\n\ninterface RedirectRule {\n _id: string\n from: string\n to: string\n type: string\n hits: number\n lastHitAt?: string\n createdAt: string\n siteId?: string\n}\n\nconst REDIRECT_TYPES = ['301', '302', '307', '308'] as const\n\nconst RedirectsPage = () => {\n const { theme } = useTheme()\n const dark = theme === 'dark'\n\n const [rules, setRules] = useState<RedirectRule[]>([])\n const [loading, setLoading] = useState(true)\n const [search, setSearch] = useState('')\n const [page, setPage] = useState(1)\n const [totalPages, setTotalPages] = useState(1)\n const [total, setTotal] = useState(0)\n const [showEditor, setShowEditor] = useState(false)\n const [editing, setEditing] = useState<RedirectRule | null>(null)\n const [deleteConfirm, setDeleteConfirm] = useState<string | null>(null)\n\n const [formFrom, setFormFrom] = useState('')\n const [formTo, setFormTo] = useState('')\n const [formType, setFormType] = useState('301')\n const [saving, setSaving] = useState(false)\n\n const fetchRules = useCallback(async () => {\n setLoading(true)\n try {\n const res = await api.get('/redirects', {\n params: { page, limit: 20, search: search || undefined },\n })\n const data = res.data\n setRules(data.data || [])\n setTotalPages(data.meta?.pagination?.totalPages || 1)\n setTotal(data.meta?.pagination?.total || 0)\n } catch {\n toast.error('Failed to load redirects')\n } finally {\n setLoading(false)\n }\n }, [page, search])\n\n useEffect(() => {\n fetchRules()\n }, [fetchRules])\n\n const openCreate = () => {\n setEditing(null)\n setFormFrom('')\n setFormTo('')\n setFormType('301')\n setShowEditor(true)\n }\n\n const openEdit = (rule: RedirectRule) => {\n setEditing(rule)\n setFormFrom(rule.from)\n setFormTo(rule.to)\n setFormType(rule.type)\n setShowEditor(true)\n }\n\n const handleSave = async () => {\n if (!formFrom || !formTo) {\n toast.error('Both \"From\" and \"To\" paths are required')\n return\n }\n setSaving(true)\n try {\n if (editing) {\n await api.patch(`/redirects/${editing._id}`, {\n from: formFrom,\n to: formTo,\n type: formType,\n })\n toast.success('Redirect updated')\n } else {\n await api.post('/redirects', {\n from: formFrom,\n to: formTo,\n type: formType,\n })\n toast.success('Redirect created')\n }\n setShowEditor(false)\n fetchRules()\n } catch (err: any) {\n const msg = err.response?.data?.error?.message || (err instanceof Error ? err.message : String(err)) || 'Failed to save redirect'\n toast.error(msg)\n } finally {\n setSaving(false)\n }\n }\n\n const handleDelete = async (id: string) => {\n try {\n await api.delete(`/redirects/${id}`)\n toast.success('Redirect deleted')\n setDeleteConfirm(null)\n fetchRules()\n } catch {\n toast.error('Failed to delete redirect')\n }\n }\n\n const typeColor = (t: string) => {\n switch (t) {\n case '301': return 'text-amber-500 border-amber-500/30'\n case '302': return 'text-z-active-text border-z-active-border'\n case '307': return 'text-z-secondary border-z-border/30'\n case '308': return 'text-z-secondary border-z-border/30'\n default: return 'text-z-secondary border-z-border/30'\n }\n }\n\n return (\n <div className=\"flex flex-col h-[calc(100vh-64px)] overflow-hidden\">\n <PageHeader\n title=\"URL Redirects\"\n description=\"Manage 301 and 302 traffic routing.\"\n icon={<ArrowRightLeft size={24} />}\n backLink={{ to: '/', label: 'Dashboard' }}\n actions={\n <button\n onClick={openCreate}\n className=\"flex items-center gap-2 px-6 py-2.5 bg-z-accent hover:opacity-90 shadow-sm text-z-primary text-sm font-semibold transition-all rounded-none\"\n >\n <Plus size={14} />\n Add Redirect\n </button>\n }\n />\n\n <div className=\"flex-1 overflow-auto p-6 md:p-8 space-y-6\">\n <div className=\"max-w-md relative\">\n <Search size={14} className={cn('absolute left-4 top-1/2 -translate-y-1/2', dark ? 'text-z-secondary' : 'text-z-muted')} />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => { setSearch(e.target.value); setPage(1) }}\n placeholder=\"Search redirect paths...\"\n className={cn(\n 'w-full pl-10 pr-4 py-2.5 text-sm font-semibold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none shadow-sm',\n 'z-input'\n )}\n />\n </div>\n\n <Card>\n {loading ? (\n <div className=\"flex items-center justify-center py-20 gap-3\">\n <Loader2 size={20} className=\"animate-spin text-z-secondary\" />\n </div>\n ) : rules.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-20 gap-4 opacity-50\">\n <ArrowRightLeft size={32} className=\"text-z-secondary\" />\n <p className=\"text-sm font-semibold text-z-secondary\">\n {search ? 'No matching redirects' : 'No redirects configured'}\n </p>\n </div>\n ) : (\n <div className=\"overflow-x-auto min-w-full\">\n <table className=\"w-full text-left border-collapse\">\n <thead>\n <tr className={cn(\n 'text-sm font-semibold border-b',\n 'text-z-secondary border-z-border'\n )}>\n <th className=\"px-5 py-4 font-normal\">From</th>\n <th className=\"px-5 py-4 font-normal hidden md:table-cell\">To</th>\n <th className=\"px-5 py-4 font-normal w-20\">Type</th>\n <th className=\"px-5 py-4 font-normal w-24 hidden sm:table-cell\">Hits</th>\n <th className=\"px-5 py-4 font-normal w-24 hidden lg:table-cell\">Last Hit</th>\n <th className=\"px-5 py-4 font-normal w-24\" />\n </tr>\n </thead>\n <tbody>\n {rules.map((rule) => (\n <tr\n key={rule._id}\n onClick={() => openEdit(rule)}\n className={cn(\n 'text-xs border-b transition-colors cursor-pointer',\n dark ? 'border-z-border hover:bg-z-panel' : 'border-z-border hover:bg-[var(--z-bg-input)]'\n )}\n >\n <td className=\"px-5 py-4\">\n <code className={cn('px-2 py-1 text-xs font-mono font-bold', dark ? 'bg-z-hover text-z-muted' : 'bg-[var(--z-bg-hover)] text-z-secondary')}>\n {rule.from}\n </code>\n </td>\n <td className=\"px-5 py-4 hidden md:table-cell\">\n <div className=\"flex items-center gap-2\">\n <ArrowRight size={12} className=\"text-z-secondary shrink-0\" />\n <span className={cn('font-mono font-bold truncate max-w-[300px]', dark ? 'text-z-secondary' : 'text-z-secondary')}>\n {rule.to}\n </span>\n </div>\n </td>\n <td className=\"px-5 py-4\">\n <span className={cn('inline-block px-2 py-0.5 text-sm font-semibold font-mono border', typeColor(rule.type))}>\n {rule.type}\n </span>\n </td>\n <td className=\"px-5 py-4 hidden sm:table-cell\">\n <div className=\"flex items-center gap-1.5\">\n <MousePointerClick size={11} className={dark ? 'text-z-secondary' : 'text-z-muted'} />\n <span className={cn('font-bold tabular-nums', dark ? 'text-z-secondary' : 'text-z-secondary')}>\n {rule.hits?.toLocaleString() || 0}\n </span>\n </div>\n </td>\n <td className=\"px-5 py-4 hidden lg:table-cell\">\n <span className={cn('text-sm font-mono', dark ? 'text-z-secondary' : 'text-z-muted')}>\n {rule.lastHitAt ? new Date(rule.lastHitAt).toLocaleString() : '—'}\n </span>\n </td>\n <td className=\"px-5 py-4\">\n <div className=\"flex items-center gap-2 justify-end\">\n <button\n onClick={(e) => { e.stopPropagation(); window.open(rule.from, '_blank') }}\n className={cn('p-1.5 border transition-all', dark ? 'border-z-border text-z-secondary hover:text-z-primary' : 'border-z-border text-z-secondary hover:text-z-primary')}\n title=\"Test redirect\"\n >\n <ExternalLink size={12} />\n </button>\n <button\n onClick={(e) => { e.stopPropagation(); setDeleteConfirm(rule._id) }}\n className=\"p-1.5 border rounded-none border-red-500/20 text-red-500 hover:bg-red-500/10 transition-all\"\n title=\"Delete\"\n >\n <Trash2 size={12} />\n </button>\n </div>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {totalPages > 1 && (\n <div className={cn('flex items-center justify-between px-5 py-4 border-t', 'border-z-border')}>\n <span className={cn('text-sm font-bold', 'text-z-secondary')}>\n Page {page} of {totalPages}\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n disabled={page <= 1}\n className={cn('px-4 py-2 text-sm font-semibold border rounded-none transition-all', dark ? 'border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30' : 'border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30')}\n >\n Prev\n </button>\n <button\n onClick={() => setPage((p) => Math.min(totalPages, p + 1))}\n disabled={page >= totalPages}\n className={cn('px-4 py-2 text-sm font-semibold border rounded-none transition-all', dark ? 'border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30' : 'border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30')}\n >\n Next\n </button>\n </div>\n </div>\n )}\n </Card>\n\n {/* Create/Edit Modal */}\n <AnimatePresence>\n {showEditor && (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4\"\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n className=\"w-full max-w-md\"\n >\n <Card>\n <div className={cn('px-6 py-4 border-b flex items-center justify-between', 'border-z-border')}>\n <h2 className=\"text-sm font-semibold text-z-secondary\">\n {editing ? 'Edit Redirect' : 'New Redirect'}\n </h2>\n <button onClick={() => setShowEditor(false)} className=\"text-z-secondary hover:text-z-primary dark:hover:text-z-primary\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>\n </button>\n </div>\n\n <CardContent className=\"p-6 space-y-4\">\n <div>\n <label className=\"block text-sm font-semibold mb-1.5 text-z-secondary\">From Path</label>\n <input\n type=\"text\"\n value={formFrom}\n onChange={(e) => setFormFrom(e.target.value)}\n placeholder=\"/old-path\"\n className={cn('w-full px-4 py-2.5 text-xs font-mono font-bold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none', dark ? 'bg-z-panel backdrop-blur-md border-z-border text-z-primary focus:border-z-active-border' : 'bg-z-input border-z-border text-z-primary focus:border-z-accent')}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-semibold mb-1.5 text-z-secondary\">To URL</label>\n <input\n type=\"text\"\n value={formTo}\n onChange={(e) => setFormTo(e.target.value)}\n placeholder=\"https://example.com/new-path\"\n className={cn('w-full px-4 py-2.5 text-xs font-mono font-bold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none', dark ? 'bg-z-panel backdrop-blur-md border-z-border text-z-primary focus:border-z-active-border' : 'bg-z-input border-z-border text-z-primary focus:border-z-accent')}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-semibold mb-1.5 text-z-secondary\">Redirect Type</label>\n <div className=\"flex gap-2\">\n {REDIRECT_TYPES.map((t) => (\n <button\n key={t}\n onClick={() => setFormType(t)}\n className={cn(\n 'flex-1 py-2.5 text-sm font-semibold font-mono border rounded-none transition-all',\n formType === t ? (dark ? 'border-z-accent text-z-active-text bg-z-active-bg shadow-sm' : 'border-z-accent text-z-accent bg-z-active-bg shadow-sm') : (dark ? 'border-z-border text-z-secondary hover:text-z-primary hover:bg-z-hover' : 'border-z-border text-z-muted hover:text-z-primary hover:bg-[var(--z-bg-input)]')\n )}\n >\n {t}\n </button>\n ))}\n </div>\n </div>\n </CardContent>\n\n <div className={cn('px-6 py-4 border-t flex justify-end gap-3', 'border-z-border')}>\n <button\n onClick={() => setShowEditor(false)}\n className={cn('px-5 py-2.5 text-sm font-semibold transition-colors rounded-none', dark ? 'text-z-secondary hover:text-z-primary hover:bg-z-hover' : 'text-z-secondary hover:text-z-primary hover:bg-[var(--z-bg-input)]')}\n >\n Cancel\n </button>\n <button\n onClick={handleSave}\n disabled={saving || !formFrom || !formTo}\n className=\"px-6 py-2.5 bg-z-accent hover:opacity-90 disabled:opacity-50 text-z-primary text-sm font-semibold transition-all shadow-sm rounded-none flex items-center gap-2\"\n >\n {saving && <Loader2 size={12} className=\"animate-spin\" />}\n {editing ? 'Update' : 'Create'}\n </button>\n </div>\n </Card>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Delete Confirmation */}\n <AnimatePresence>\n {deleteConfirm && (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4\"\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n className=\"w-full max-w-sm\"\n >\n <Card>\n <CardContent className=\"p-8 text-center\">\n <AlertTriangle size={32} className=\"mx-auto mb-4 text-red-500\" />\n <h3 className=\"text-sm font-semibold mb-2 text-z-primary\">Delete Redirect?</h3>\n <p className=\"text-sm font-bold text-z-secondary mb-6\">\n This action cannot be undone.\n </p>\n <div className=\"flex gap-3 justify-center\">\n <button\n onClick={() => setDeleteConfirm(null)}\n className={cn('px-5 py-2.5 text-sm font-semibold border rounded-none transition-all', dark ? 'border-z-border text-z-secondary hover:text-z-primary' : 'border-z-border text-z-secondary hover:text-z-primary')}\n >\n Cancel\n </button>\n <button\n onClick={() => handleDelete(deleteConfirm)}\n className=\"px-5 py-2.5 bg-red-600 hover:bg-red-500 text-z-primary text-sm font-semibold transition-all rounded-none shadow-sm\"\n >\n Delete\n </button>\n </div>\n </CardContent>\n </Card>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n </div>\n )\n}\n\nexport default RedirectsPage\n"],"mappings":"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"}
1
+ {"version":3,"file":"RedirectsPage-GIZCbEll.js","names":[],"sources":["../../src/pages/RedirectsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react'\nimport {\n ArrowRightLeft,\n Plus,\n Search,\n Trash2,\n ExternalLink,\n Loader2,\n ArrowRight,\n MousePointerClick,\n AlertTriangle,\n} from 'lucide-react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { cn } from '../lib/utils'\nimport { useTheme } from '../context/ThemeContext'\nimport toast from 'react-hot-toast'\nimport api from '../lib/api'\nimport { PageHeader } from '../components/ui/PageHeader'\nimport { Card, CardContent } from '../components/ui/Card'\n\ninterface RedirectRule {\n _id: string\n from: string\n to: string\n type: string\n hits: number\n lastHitAt?: string\n createdAt: string\n siteId?: string\n}\n\nconst REDIRECT_TYPES = ['301', '302', '307', '308'] as const\n\nconst RedirectsPage = () => {\n const { theme } = useTheme()\n const dark = theme === 'dark'\n\n const [rules, setRules] = useState<RedirectRule[]>([])\n const [loading, setLoading] = useState(true)\n const [search, setSearch] = useState('')\n const [page, setPage] = useState(1)\n const [totalPages, setTotalPages] = useState(1)\n const [total, setTotal] = useState(0)\n const [showEditor, setShowEditor] = useState(false)\n const [editing, setEditing] = useState<RedirectRule | null>(null)\n const [deleteConfirm, setDeleteConfirm] = useState<string | null>(null)\n\n const [formFrom, setFormFrom] = useState('')\n const [formTo, setFormTo] = useState('')\n const [formType, setFormType] = useState('301')\n const [saving, setSaving] = useState(false)\n\n const fetchRules = useCallback(async () => {\n setLoading(true)\n try {\n const res = await api.get('/redirects', {\n params: { page, limit: 20, search: search || undefined },\n })\n const data = res.data\n setRules(data.data || [])\n setTotalPages(data.meta?.pagination?.totalPages || 1)\n setTotal(data.meta?.pagination?.total || 0)\n } catch {\n toast.error('Failed to load redirects')\n } finally {\n setLoading(false)\n }\n }, [page, search])\n\n useEffect(() => {\n fetchRules()\n }, [fetchRules])\n\n const openCreate = () => {\n setEditing(null)\n setFormFrom('')\n setFormTo('')\n setFormType('301')\n setShowEditor(true)\n }\n\n const openEdit = (rule: RedirectRule) => {\n setEditing(rule)\n setFormFrom(rule.from)\n setFormTo(rule.to)\n setFormType(rule.type)\n setShowEditor(true)\n }\n\n const handleSave = async () => {\n if (!formFrom || !formTo) {\n toast.error('Both \"From\" and \"To\" paths are required')\n return\n }\n setSaving(true)\n try {\n if (editing) {\n await api.patch(`/redirects/${editing._id}`, {\n from: formFrom,\n to: formTo,\n type: formType,\n })\n toast.success('Redirect updated')\n } else {\n await api.post('/redirects', {\n from: formFrom,\n to: formTo,\n type: formType,\n })\n toast.success('Redirect created')\n }\n setShowEditor(false)\n fetchRules()\n } catch (err: any) {\n const msg = err.response?.data?.error?.message || (err instanceof Error ? err.message : String(err)) || 'Failed to save redirect'\n toast.error(msg)\n } finally {\n setSaving(false)\n }\n }\n\n const handleDelete = async (id: string) => {\n try {\n await api.delete(`/redirects/${id}`)\n toast.success('Redirect deleted')\n setDeleteConfirm(null)\n fetchRules()\n } catch {\n toast.error('Failed to delete redirect')\n }\n }\n\n const typeColor = (t: string) => {\n switch (t) {\n case '301': return 'text-amber-500 border-amber-500/30'\n case '302': return 'text-z-active-text border-z-active-border'\n case '307': return 'text-z-secondary border-z-border/30'\n case '308': return 'text-z-secondary border-z-border/30'\n default: return 'text-z-secondary border-z-border/30'\n }\n }\n\n return (\n <div className=\"flex flex-col h-[calc(100vh-64px)] overflow-hidden\">\n <PageHeader\n title=\"URL Redirects\"\n description=\"Manage 301 and 302 traffic routing.\"\n icon={<ArrowRightLeft size={24} />}\n backLink={{ to: '/', label: 'Dashboard' }}\n actions={\n <button\n onClick={openCreate}\n className=\"flex items-center gap-2 px-6 py-2.5 bg-z-accent hover:opacity-90 shadow-sm text-z-primary text-sm font-semibold transition-all rounded-none\"\n >\n <Plus size={14} />\n Add Redirect\n </button>\n }\n />\n\n <div className=\"flex-1 overflow-auto p-6 md:p-8 space-y-6\">\n <div className=\"max-w-md relative\">\n <Search size={14} className={cn('absolute left-4 top-1/2 -translate-y-1/2', dark ? 'text-z-secondary' : 'text-z-muted')} />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => { setSearch(e.target.value); setPage(1) }}\n placeholder=\"Search redirect paths...\"\n className={cn(\n 'w-full pl-10 pr-4 py-2.5 text-sm font-semibold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none shadow-sm',\n 'z-input'\n )}\n />\n </div>\n\n <Card>\n {loading ? (\n <div className=\"flex items-center justify-center py-20 gap-3\">\n <Loader2 size={20} className=\"animate-spin text-z-secondary\" />\n </div>\n ) : rules.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-20 gap-4 opacity-50\">\n <ArrowRightLeft size={32} className=\"text-z-secondary\" />\n <p className=\"text-sm font-semibold text-z-secondary\">\n {search ? 'No matching redirects' : 'No redirects configured'}\n </p>\n </div>\n ) : (\n <div className=\"overflow-x-auto min-w-full\">\n <table className=\"w-full text-left border-collapse\">\n <thead>\n <tr className={cn(\n 'text-sm font-semibold border-b',\n 'text-z-secondary border-z-border'\n )}>\n <th className=\"px-5 py-4 font-normal\">From</th>\n <th className=\"px-5 py-4 font-normal hidden md:table-cell\">To</th>\n <th className=\"px-5 py-4 font-normal w-20\">Type</th>\n <th className=\"px-5 py-4 font-normal w-24 hidden sm:table-cell\">Hits</th>\n <th className=\"px-5 py-4 font-normal w-24 hidden lg:table-cell\">Last Hit</th>\n <th className=\"px-5 py-4 font-normal w-24\" />\n </tr>\n </thead>\n <tbody>\n {rules.map((rule) => (\n <tr\n key={rule._id}\n onClick={() => openEdit(rule)}\n className={cn(\n 'text-xs border-b transition-colors cursor-pointer',\n dark ? 'border-z-border hover:bg-z-panel' : 'border-z-border hover:bg-[var(--z-bg-input)]'\n )}\n >\n <td className=\"px-5 py-4\">\n <code className={cn('px-2 py-1 text-xs font-mono font-bold', dark ? 'bg-z-hover text-z-muted' : 'bg-[var(--z-bg-hover)] text-z-secondary')}>\n {rule.from}\n </code>\n </td>\n <td className=\"px-5 py-4 hidden md:table-cell\">\n <div className=\"flex items-center gap-2\">\n <ArrowRight size={12} className=\"text-z-secondary shrink-0\" />\n <span className={cn('font-mono font-bold truncate max-w-[300px]', dark ? 'text-z-secondary' : 'text-z-secondary')}>\n {rule.to}\n </span>\n </div>\n </td>\n <td className=\"px-5 py-4\">\n <span className={cn('inline-block px-2 py-0.5 text-sm font-semibold font-mono border', typeColor(rule.type))}>\n {rule.type}\n </span>\n </td>\n <td className=\"px-5 py-4 hidden sm:table-cell\">\n <div className=\"flex items-center gap-1.5\">\n <MousePointerClick size={11} className={dark ? 'text-z-secondary' : 'text-z-muted'} />\n <span className={cn('font-bold tabular-nums', dark ? 'text-z-secondary' : 'text-z-secondary')}>\n {rule.hits?.toLocaleString() || 0}\n </span>\n </div>\n </td>\n <td className=\"px-5 py-4 hidden lg:table-cell\">\n <span className={cn('text-sm font-mono', dark ? 'text-z-secondary' : 'text-z-muted')}>\n {rule.lastHitAt ? new Date(rule.lastHitAt).toLocaleString() : '—'}\n </span>\n </td>\n <td className=\"px-5 py-4\">\n <div className=\"flex items-center gap-2 justify-end\">\n <button\n onClick={(e) => { e.stopPropagation(); window.open(rule.from, '_blank') }}\n className={cn('p-1.5 border transition-all', dark ? 'border-z-border text-z-secondary hover:text-z-primary' : 'border-z-border text-z-secondary hover:text-z-primary')}\n title=\"Test redirect\"\n >\n <ExternalLink size={12} />\n </button>\n <button\n onClick={(e) => { e.stopPropagation(); setDeleteConfirm(rule._id) }}\n className=\"p-1.5 border rounded-none border-red-500/20 text-red-500 hover:bg-red-500/10 transition-all\"\n title=\"Delete\"\n >\n <Trash2 size={12} />\n </button>\n </div>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {totalPages > 1 && (\n <div className={cn('flex items-center justify-between px-5 py-4 border-t', 'border-z-border')}>\n <span className={cn('text-sm font-bold', 'text-z-secondary')}>\n Page {page} of {totalPages}\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n disabled={page <= 1}\n className={cn('px-4 py-2 text-sm font-semibold border rounded-none transition-all', dark ? 'border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30' : 'border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30')}\n >\n Prev\n </button>\n <button\n onClick={() => setPage((p) => Math.min(totalPages, p + 1))}\n disabled={page >= totalPages}\n className={cn('px-4 py-2 text-sm font-semibold border rounded-none transition-all', dark ? 'border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30' : 'border-z-border text-z-secondary hover:text-z-primary disabled:opacity-30')}\n >\n Next\n </button>\n </div>\n </div>\n )}\n </Card>\n\n {/* Create/Edit Modal */}\n <AnimatePresence>\n {showEditor && (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4\"\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n className=\"w-full max-w-md\"\n >\n <Card>\n <div className={cn('px-6 py-4 border-b flex items-center justify-between', 'border-z-border')}>\n <h2 className=\"text-sm font-semibold text-z-secondary\">\n {editing ? 'Edit Redirect' : 'New Redirect'}\n </h2>\n <button onClick={() => setShowEditor(false)} className=\"text-z-secondary hover:text-z-primary dark:hover:text-z-primary\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>\n </button>\n </div>\n\n <CardContent className=\"p-6 space-y-4\">\n <div>\n <label className=\"block text-sm font-semibold mb-1.5 text-z-secondary\">From Path</label>\n <input\n type=\"text\"\n value={formFrom}\n onChange={(e) => setFormFrom(e.target.value)}\n placeholder=\"/old-path\"\n className={cn('w-full px-4 py-2.5 text-xs font-mono font-bold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none', dark ? 'bg-z-panel backdrop-blur-md border-z-border text-z-primary focus:border-z-active-border' : 'bg-z-input border-z-border text-z-primary focus:border-z-accent')}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-semibold mb-1.5 text-z-secondary\">To URL</label>\n <input\n type=\"text\"\n value={formTo}\n onChange={(e) => setFormTo(e.target.value)}\n placeholder=\"https://example.com/new-path\"\n className={cn('w-full px-4 py-2.5 text-xs font-mono font-bold border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border transition-colors rounded-none', dark ? 'bg-z-panel backdrop-blur-md border-z-border text-z-primary focus:border-z-active-border' : 'bg-z-input border-z-border text-z-primary focus:border-z-accent')}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-semibold mb-1.5 text-z-secondary\">Redirect Type</label>\n <div className=\"flex gap-2\">\n {REDIRECT_TYPES.map((t) => (\n <button\n key={t}\n onClick={() => setFormType(t)}\n className={cn(\n 'flex-1 py-2.5 text-sm font-semibold font-mono border rounded-none transition-all',\n formType === t ? (dark ? 'border-z-accent text-z-active-text bg-z-active-bg shadow-sm' : 'border-z-accent text-z-accent bg-z-active-bg shadow-sm') : (dark ? 'border-z-border text-z-secondary hover:text-z-primary hover:bg-z-hover' : 'border-z-border text-z-muted hover:text-z-primary hover:bg-[var(--z-bg-input)]')\n )}\n >\n {t}\n </button>\n ))}\n </div>\n </div>\n </CardContent>\n\n <div className={cn('px-6 py-4 border-t flex justify-end gap-3', 'border-z-border')}>\n <button\n onClick={() => setShowEditor(false)}\n className={cn('px-5 py-2.5 text-sm font-semibold transition-colors rounded-none', dark ? 'text-z-secondary hover:text-z-primary hover:bg-z-hover' : 'text-z-secondary hover:text-z-primary hover:bg-[var(--z-bg-input)]')}\n >\n Cancel\n </button>\n <button\n onClick={handleSave}\n disabled={saving || !formFrom || !formTo}\n className=\"px-6 py-2.5 bg-z-accent hover:opacity-90 disabled:opacity-50 text-z-primary text-sm font-semibold transition-all shadow-sm rounded-none flex items-center gap-2\"\n >\n {saving && <Loader2 size={12} className=\"animate-spin\" />}\n {editing ? 'Update' : 'Create'}\n </button>\n </div>\n </Card>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Delete Confirmation */}\n <AnimatePresence>\n {deleteConfirm && (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4\"\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n className=\"w-full max-w-sm\"\n >\n <Card>\n <CardContent className=\"p-8 text-center\">\n <AlertTriangle size={32} className=\"mx-auto mb-4 text-red-500\" />\n <h3 className=\"text-sm font-semibold mb-2 text-z-primary\">Delete Redirect?</h3>\n <p className=\"text-sm font-bold text-z-secondary mb-6\">\n This action cannot be undone.\n </p>\n <div className=\"flex gap-3 justify-center\">\n <button\n onClick={() => setDeleteConfirm(null)}\n className={cn('px-5 py-2.5 text-sm font-semibold border rounded-none transition-all', dark ? 'border-z-border text-z-secondary hover:text-z-primary' : 'border-z-border text-z-secondary hover:text-z-primary')}\n >\n Cancel\n </button>\n <button\n onClick={() => handleDelete(deleteConfirm)}\n className=\"px-5 py-2.5 bg-red-600 hover:bg-red-500 text-z-primary text-sm font-semibold transition-all rounded-none shadow-sm\"\n >\n Delete\n </button>\n </div>\n </CardContent>\n </Card>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n </div>\n )\n}\n\nexport default RedirectsPage\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{$n as t,Bt as n,C as r,Dn as i,Et as a,J as o,Jt as s,Ln as c,Lt as l,Mn as u,Mt as d,O as f,Ot as p,Q as m,R as h,Rn as g,T as _,Wt as ee,Zt as v,an as y,cn as te,d as b,fn as x,gt as ne,ir as S,l as C,mt as w,pt as T,rr as E,sn as D,un as O,vr as k,xr as A}from"./vendor-react-DQVTOTFO.js";import{a as re,o as j,t as M}from"./utils-fgvbH6CB.js";import{p as ie}from"./index-ChcKY5Xe.js";import{t as ae}from"./useUnsavedGuard-CMMKQT9a.js";var N=e(A(),1),P=k(),F=[{value:`text`,label:`Text`,icon:l,color:`#6b7280`},{value:`textarea`,label:`Textarea`,icon:i,color:`#6b7280`},{value:`number`,label:`Number`,icon:p,color:`#3b82f6`},{value:`email`,label:`Email`,icon:d,color:`var(--z-accent)`},{value:`password`,label:`Password`,icon:T,color:`#ef4444`},{value:`checkbox`,label:`Checkbox / Boolean`,icon:_,color:`var(--z-accent)`},{value:`date`,label:`Date`,icon:O,color:`#f59e0b`},{value:`select`,label:`Select / Enum`,icon:w,color:`#f97316`},{value:`media`,label:`Media / Image`,icon:a,color:`#06b6d4`},{value:`richtext`,label:`Rich Text`,icon:l,color:`#84cc16`},{value:`relation`,label:`Relation`,icon:ne,color:`#ec4899`},{value:`json`,label:`JSON Object`,icon:t,color:`#6366f1`},{value:`slug`,label:`Slug`,icon:f,color:`var(--z-accent)`},{value:`array`,label:`Array / Repeater`,icon:g,color:`#f59e0b`},{value:`blocks`,label:`Dynamic Blocks`,icon:x,color:`var(--z-accent)`},{value:`group`,label:`Field Group`,icon:h,color:`#3b82f6`},{value:`code`,label:`Code Editor`,icon:v,color:`#6b7280`},{value:`color`,label:`Color Picker`,icon:n,color:`#f97316`}],I={drafts:!0,timestamps:!0,versions:!1,publicRead:!1,singleton:!1,auth:!1,softDelete:!1};function L(e){return e.toLowerCase().replace(/\s+/g,`-`).replace(/[^a-z0-9-]/g,``)}function R({value:e,onChange:t,theme:n}){let[r,i]=(0,N.useState)(!1),a=F.find(t=>t.value===e),o=a?.icon||l;return(0,P.jsxs)(`div`,{className:`relative`,children:[(0,P.jsxs)(`button`,{type:`button`,onClick:()=>i(!r),className:M(`flex items-center gap-2 px-3 py-2 border text-sm font-semibold transition-all w-full shadow-sm rounded-none`,`z-card-interactive`),children:[(0,P.jsx)(o,{size:12,style:{color:a?.color}}),(0,P.jsx)(`span`,{className:`flex-1 text-left`,children:a?.label||`Select type`}),(0,P.jsx)(D,{size:10,className:`text-z-secondary`})]}),(0,P.jsx)(S,{children:r&&(0,P.jsx)(E.div,{initial:{opacity:0,y:4},animate:{opacity:1,y:0},exit:{opacity:0,y:4},className:M(`absolute z-50 top-full left-0 mt-1 w-64 border shadow-sm max-h-72 overflow-y-auto rounded-none`,n===`dark`?`bg-z-popover backdrop-blur-xl border-z-border`:`bg-z-panel border-z-border`),children:F.map(r=>{let a=r.icon;return(0,P.jsxs)(`button`,{type:`button`,onClick:()=>{t(r.value),i(!1)},className:M(`w-full flex items-center gap-3 px-4 py-2.5 text-sm font-semibold transition-all rounded-none`,e===r.value?`bg-z-accent text-z-logo-text`:n===`dark`?`text-z-muted hover:bg-z-hover hover:text-z-primary`:`text-z-secondary hover:bg-[var(--z-bg-input)]`),children:[(0,P.jsx)(a,{size:12,style:{color:e===r.value?`white`:r.color}}),r.label]},r.value)})})})]})}function z({fields:e,onUpdate:t,theme:n,availableCollections:i}){let a=()=>{t([...e,{name:`nestedField${e.length+1}`,type:`text`,label:`Nested Field ${e.length+1}`}])},o=n=>{t(e.filter((e,t)=>t!==n))},s=(n,r,i)=>{let a=[...e];a[n]={...a[n],[r]:i},t(a)},c=M(`border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black text-sm font-bold transition-colors py-2 px-3 rounded-none shadow-sm`,`z-input`);return(0,P.jsxs)(`div`,{className:`mt-4 border-l-2 border-z-accent/50 pl-4 space-y-4`,children:[(0,P.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,P.jsxs)(`h4`,{className:`text-sm font-bold text-z-primary`,children:[`Nested Fields (`,e.length,`)`]}),(0,P.jsxs)(`button`,{onClick:a,type:`button`,className:`flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border border-z-border text-z-secondary text-sm font-semibold rounded-none transition-all`,children:[(0,P.jsx)(m,{size:12}),` Add Field`]})]}),e.length===0?(0,P.jsx)(`div`,{className:`p-4 border border-dashed border-z-border text-center text-z-secondary text-sm`,children:`No nested fields added yet.`}):(0,P.jsx)(`div`,{className:`space-y-4`,children:e.map((e,t)=>(0,P.jsxs)(`div`,{className:`p-4 relative group border border-z-border bg-z-panel`,children:[(0,P.jsx)(`button`,{type:`button`,onClick:()=>o(t),className:`absolute top-2 right-2 opacity-0 group-hover:opacity-100 p-1 text-red-500/50 hover:text-red-500 transition-all rounded-none hover:bg-red-500/10 z-10`,children:(0,P.jsx)(r,{size:12})}),(0,P.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 pr-6`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-xs font-semibold text-z-secondary block mb-1`,children:`Field Name (key)`}),(0,P.jsx)(`input`,{type:`text`,value:e.name,onChange:e=>s(t,`name`,e.target.value.replace(/\s+/g,`_`).replace(/[^a-zA-Z0-9_]/g,``)),className:M(c,`w-full rounded-none font-mono text-xs`),placeholder:`fieldName`})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-xs font-semibold text-z-secondary block mb-1`,children:`Field Type`}),(0,P.jsx)(R,{value:e.type,onChange:e=>s(t,`type`,e),theme:n})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-xs font-semibold text-z-secondary block mb-1`,children:`Display Label`}),(0,P.jsx)(`input`,{type:`text`,value:e.label||``,onChange:e=>s(t,`label`,e.target.value),className:M(c,`w-full rounded-none text-xs`),placeholder:`Human readable label`})]})]}),(0,P.jsx)(B,{field:e,onUpdate:(e,n)=>s(t,e,n),theme:n,availableCollections:i})]},t))})]})}function B({field:e,onUpdate:t,theme:n,availableCollections:r}){let[i,a]=(0,N.useState)(!1),o=M(`w-full border p-2 text-sm font-mono outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors rounded-none shadow-sm`,`z-input`),s=`accent-gray-500 w-3.5 h-3.5`,c=`text-sm font-semibold text-z-secondary`;return(0,P.jsxs)(`div`,{className:`mt-2`,children:[(0,P.jsxs)(`button`,{type:`button`,onClick:()=>a(!i),className:`flex items-center gap-1.5 text-sm font-semibold text-z-secondary hover:text-z-secondary transition-colors`,children:[i?(0,P.jsx)(D,{size:10}):(0,P.jsx)(y,{size:10}),`Advanced Options`]}),(0,P.jsx)(S,{children:i&&(0,P.jsx)(E.div,{initial:{height:0,opacity:0},animate:{height:`auto`,opacity:1},exit:{height:0,opacity:0},className:`overflow-hidden`,children:(0,P.jsxs)(`div`,{className:M(`mt-3 p-4 border space-y-4 rounded-none shadow-sm`,`z-panel shadow-sm`),children:[(0,P.jsx)(`div`,{className:`flex flex-wrap gap-x-6 gap-y-2`,children:[[`required`,`Required`],[`unique`,`Unique`],[`index`,`Index`],[`hidden`,`Hidden`],[`readOnly`,`Read Only`]].map(([n,r])=>(0,P.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,P.jsx)(`input`,{type:`checkbox`,checked:!!e[n],onChange:e=>t(n,e.target.checked),className:s}),(0,P.jsx)(`span`,{className:c,children:r})]},n))}),(0,P.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-3`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Placeholder`}),(0,P.jsx)(`input`,{type:`text`,value:e.placeholder||``,onChange:e=>t(`placeholder`,e.target.value),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Default Value`}),(0,P.jsx)(`input`,{type:`text`,value:e.defaultValue??``,onChange:e=>t(`defaultValue`,e.target.value),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Description`}),(0,P.jsx)(`input`,{type:`text`,value:e.description||``,onChange:e=>t(`description`,e.target.value),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Width (e.g. 50%)`}),(0,P.jsx)(`input`,{type:`text`,value:e.width||``,onChange:e=>t(`width`,e.target.value),className:o})]}),(e.type===`text`||e.type===`textarea`)&&(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Min Length`}),(0,P.jsx)(`input`,{type:`number`,value:e.min??``,onChange:e=>t(`min`,Number(e.target.value)),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Max Length`}),(0,P.jsx)(`input`,{type:`number`,value:e.max??``,onChange:e=>t(`max`,Number(e.target.value)),className:o})]}),(0,P.jsxs)(`div`,{className:`col-span-2`,children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Regex Pattern`}),(0,P.jsx)(`input`,{type:`text`,value:e.regex||``,onChange:e=>t(`regex`,e.target.value),className:o,placeholder:`^[a-z]+$`})]})]}),e.type===`number`&&(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Min`}),(0,P.jsx)(`input`,{type:`number`,value:e.min??``,onChange:e=>t(`min`,Number(e.target.value)),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Max`}),(0,P.jsx)(`input`,{type:`number`,value:e.max??``,onChange:e=>t(`max`,Number(e.target.value)),className:o})]})]})]}),e.type===`relation`&&(0,P.jsxs)(`div`,{className:`space-y-3`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Relates To Collection`}),(0,P.jsxs)(`select`,{value:e.relationTo||``,onChange:e=>t(`relationTo`,e.target.value),className:M(o,`cursor-pointer`),children:[(0,P.jsx)(`option`,{value:``,children:`-- Select Collection --`}),r.map(e=>(0,P.jsx)(`option`,{value:e,children:e},e))]})]}),(0,P.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,P.jsx)(`input`,{type:`checkbox`,checked:!!e.hasMany,onChange:e=>t(`hasMany`,e.target.checked),className:s}),(0,P.jsx)(`span`,{className:c,children:`Has Many (array of references)`})]})]}),(e.type===`array`||e.type===`group`)&&(0,P.jsx)(z,{fields:e.fields||[],onUpdate:e=>t(`fields`,e),theme:n,availableCollections:r}),e.type===`select`&&(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-2`),children:`Options`}),(0,P.jsxs)(`div`,{className:`space-y-2`,children:[(e.options||[]).map((n,r)=>(0,P.jsxs)(`div`,{className:`flex gap-2`,children:[(0,P.jsx)(`input`,{type:`text`,value:n.label,onChange:n=>{let i=[...e.options||[]];i[r]={...i[r],label:n.target.value},t(`options`,i)},placeholder:`Label`,className:M(o,`flex-1`)}),(0,P.jsx)(`input`,{type:`text`,value:n.value,onChange:n=>{let i=[...e.options||[]];i[r]={...i[r],value:n.target.value},t(`options`,i)},placeholder:`value`,className:M(o,`flex-1 font-mono`)}),(0,P.jsx)(`button`,{type:`button`,onClick:()=>t(`options`,(e.options||[]).filter((e,t)=>t!==r)),className:`p-2 text-red-500/60 hover:text-red-500 transition-colors`,children:(0,P.jsx)(b,{size:12})})]},r)),(0,P.jsxs)(`button`,{type:`button`,onClick:()=>t(`options`,[...e.options||[],{label:``,value:``}]),className:`flex items-center gap-1 text-sm font-semibold text-z-secondary hover:text-z-secondary`,children:[(0,P.jsx)(m,{size:10}),` Add Option`]})]})]})]})})})]})}function V(){let{theme:e}=re(),t=e===`dark`,[n,i]=(0,N.useState)(`New Collection`),[a,l]=(0,N.useState)(`new-collection`),[d,f]=(0,N.useState)([]),[p,h]=(0,N.useState)(I),[_,y]=(0,N.useState)([]),[x,ne]=(0,N.useState)(!0),[w,D]=(0,N.useState)(null),O=_.find(e=>(e._id||e.id)===w),k=O?.isCodeFirst,[A,F]=(0,N.useState)(!1),[z,V]=(0,N.useState)(!1),[oe,H]=(0,N.useState)(!1),[se,U]=(0,N.useState)(!1),[W,ce]=(0,N.useState)(``),[G,K]=(0,N.useState)(!1),[q,le]=(0,N.useState)(``),[J,ue]=(0,N.useState)(!1),[de,Y]=(0,N.useState)(!1),[fe,pe]=(0,N.useState)([]),[me,he]=(0,N.useState)(!1);(0,N.useEffect)(()=>{let e=JSON.stringify({slug:a,collectionName:n,fields:d,settings:p});he(O?e!==JSON.stringify({slug:O.slug,collectionName:O.plural||O.slug,fields:O.fields||[],settings:{...I,...O.settings||{}}}):e!==JSON.stringify({slug:`new-collection`,collectionName:`New Collection`,fields:[],settings:I}))},[a,n,d,p,O]),ae({hasUnsavedChanges:me});let X=(0,N.useCallback)(async()=>{try{let[e,t]=await Promise.all([j.get(`/schemas`).catch(()=>({data:{data:[]}})),j.get(`/system/schemas`).catch(()=>({data:{data:{collections:[]}}}))]),n=e.data?.data,r=Array.isArray(n)?n:Array.isArray(n?.schemas)?n.schemas:[],i=t.data?.data?.collections||[],a=Array.isArray(i)?i.map(e=>({...e,id:e.slug,isCodeFirst:!0})):[],o=new Map;for(let e of[...r,...a])o.set(e.slug,e);y(Array.from(o.values()).sort((e,t)=>e.slug.localeCompare(t.slug)))}catch{y([])}finally{ne(!1)}},[]);(0,N.useEffect)(()=>{X(),j.get(`/schemas`).then(e=>{let t=e.data?.data;pe((Array.isArray(t?.collections)?t.collections:Array.isArray(t)?t:[]).map(e=>e.slug).filter(Boolean))}).catch(()=>{})},[X]);let ge=e=>{D(e._id||e.id||null),i(e.plural||e.slug),l(e.slug),f(e.fields||[]),h({...I,...e.settings||{}}),C.success(`Loaded schema: ${e.slug}`)},Z=()=>{D(null),i(`New Collection`),l(`new-collection`),f([]),h(I)},_e=()=>{f(e=>[...e,{name:`field${e.length+1}`,type:`text`,label:`Field ${e.length+1}`}])},ve=e=>{f(t=>t.filter((t,n)=>n!==e))},Q=(e,t,n)=>{f(r=>{let i=[...r];return i[e]={...i[e],[t]:n},i})},ye=async()=>{if(!a||!n)return C.error(`Name and slug required`);F(!0);try{let e={slug:a,singular:n,plural:n,fields:d,settings:p};if(w)await j.put(`/schemas/${w}`,e),C.success(`Schema updated!`);else{let t=await j.post(`/schemas`,e),n=t.data?.data?._id||t.data?.data?.id;n&&D(n),C.success(`Schema created!`)}await X(),await j.post(`/system/schema/reload`).catch(()=>{})}catch(e){C.error(e.response?.data?.error?.message||`Failed to save schema`)}finally{F(!1)}},be=async(e,t)=>{try{await j.delete(`/schemas/${e}`),C.success(`Schema "${t}" deleted`),w===e&&Z(),await X()}catch{C.error(`Failed to delete schema`)}},xe=async()=>{if(!W)return C.error(`Please provide a connection string`);K(!0);try{let e=(await j.post(`/system/introspect`,{connectionString:W})).data.data;if(e?.length>0){let t=e[0];i(t.name),l(L(t.name)),f(t.fields||[]),C.success(`Introspected: ${t.name}`),U(!1)}else C.error(`No tables found`)}catch(e){C.error(e.response?.data?.error||`Introspection failed`)}finally{K(!1)}},Se=async()=>{if(!q)return C.error(`Enter a prompt first`);ue(!0);try{let e=(await j.post(`/system/ai-architect`,{prompt:q})).data?.data;e&&(i(e.name||e.slug||`AI Collection`),l(e.slug||L(e.name||`ai-collection`)),f(e.fields||[]),C.success(`AI schema generated!`),Y(!1))}catch(e){C.error(e.response?.data?.error?.message||`AI generation failed`)}finally{ue(!1)}},Ce=()=>{let e=d.map(e=>{let t=` name: '${e.name}',\n type: '${e.type}',`;return e.label&&(t+=`\n label: '${e.label}',`),e.required&&(t+=`
1
+ import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{$n as t,Bt as n,C as r,Dn as i,Et as a,J as o,Jt as s,Ln as c,Lt as l,Mn as u,Mt as d,O as f,Ot as p,Q as m,R as h,Rn as g,T as _,Wt as ee,Zt as v,an as y,cn as te,d as b,fn as x,gt as ne,ir as S,l as C,mt as w,pt as T,rr as E,sn as D,un as O,vr as k,xr as A}from"./vendor-react-DQVTOTFO.js";import{a as re,o as j,t as M}from"./utils-fgvbH6CB.js";import{p as ie}from"./index-C4J6QNLn.js";import{t as ae}from"./useUnsavedGuard-CMMKQT9a.js";var N=e(A(),1),P=k(),F=[{value:`text`,label:`Text`,icon:l,color:`#6b7280`},{value:`textarea`,label:`Textarea`,icon:i,color:`#6b7280`},{value:`number`,label:`Number`,icon:p,color:`#3b82f6`},{value:`email`,label:`Email`,icon:d,color:`var(--z-accent)`},{value:`password`,label:`Password`,icon:T,color:`#ef4444`},{value:`checkbox`,label:`Checkbox / Boolean`,icon:_,color:`var(--z-accent)`},{value:`date`,label:`Date`,icon:O,color:`#f59e0b`},{value:`select`,label:`Select / Enum`,icon:w,color:`#f97316`},{value:`media`,label:`Media / Image`,icon:a,color:`#06b6d4`},{value:`richtext`,label:`Rich Text`,icon:l,color:`#84cc16`},{value:`relation`,label:`Relation`,icon:ne,color:`#ec4899`},{value:`json`,label:`JSON Object`,icon:t,color:`#6366f1`},{value:`slug`,label:`Slug`,icon:f,color:`var(--z-accent)`},{value:`array`,label:`Array / Repeater`,icon:g,color:`#f59e0b`},{value:`blocks`,label:`Dynamic Blocks`,icon:x,color:`var(--z-accent)`},{value:`group`,label:`Field Group`,icon:h,color:`#3b82f6`},{value:`code`,label:`Code Editor`,icon:v,color:`#6b7280`},{value:`color`,label:`Color Picker`,icon:n,color:`#f97316`}],I={drafts:!0,timestamps:!0,versions:!1,publicRead:!1,singleton:!1,auth:!1,softDelete:!1};function L(e){return e.toLowerCase().replace(/\s+/g,`-`).replace(/[^a-z0-9-]/g,``)}function R({value:e,onChange:t,theme:n}){let[r,i]=(0,N.useState)(!1),a=F.find(t=>t.value===e),o=a?.icon||l;return(0,P.jsxs)(`div`,{className:`relative`,children:[(0,P.jsxs)(`button`,{type:`button`,onClick:()=>i(!r),className:M(`flex items-center gap-2 px-3 py-2 border text-sm font-semibold transition-all w-full shadow-sm rounded-none`,`z-card-interactive`),children:[(0,P.jsx)(o,{size:12,style:{color:a?.color}}),(0,P.jsx)(`span`,{className:`flex-1 text-left`,children:a?.label||`Select type`}),(0,P.jsx)(D,{size:10,className:`text-z-secondary`})]}),(0,P.jsx)(S,{children:r&&(0,P.jsx)(E.div,{initial:{opacity:0,y:4},animate:{opacity:1,y:0},exit:{opacity:0,y:4},className:M(`absolute z-50 top-full left-0 mt-1 w-64 border shadow-sm max-h-72 overflow-y-auto rounded-none`,n===`dark`?`bg-z-popover backdrop-blur-xl border-z-border`:`bg-z-panel border-z-border`),children:F.map(r=>{let a=r.icon;return(0,P.jsxs)(`button`,{type:`button`,onClick:()=>{t(r.value),i(!1)},className:M(`w-full flex items-center gap-3 px-4 py-2.5 text-sm font-semibold transition-all rounded-none`,e===r.value?`bg-z-accent text-z-logo-text`:n===`dark`?`text-z-muted hover:bg-z-hover hover:text-z-primary`:`text-z-secondary hover:bg-[var(--z-bg-input)]`),children:[(0,P.jsx)(a,{size:12,style:{color:e===r.value?`white`:r.color}}),r.label]},r.value)})})})]})}function z({fields:e,onUpdate:t,theme:n,availableCollections:i}){let a=()=>{t([...e,{name:`nestedField${e.length+1}`,type:`text`,label:`Nested Field ${e.length+1}`}])},o=n=>{t(e.filter((e,t)=>t!==n))},s=(n,r,i)=>{let a=[...e];a[n]={...a[n],[r]:i},t(a)},c=M(`border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black text-sm font-bold transition-colors py-2 px-3 rounded-none shadow-sm`,`z-input`);return(0,P.jsxs)(`div`,{className:`mt-4 border-l-2 border-z-accent/50 pl-4 space-y-4`,children:[(0,P.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,P.jsxs)(`h4`,{className:`text-sm font-bold text-z-primary`,children:[`Nested Fields (`,e.length,`)`]}),(0,P.jsxs)(`button`,{onClick:a,type:`button`,className:`flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border border-z-border text-z-secondary text-sm font-semibold rounded-none transition-all`,children:[(0,P.jsx)(m,{size:12}),` Add Field`]})]}),e.length===0?(0,P.jsx)(`div`,{className:`p-4 border border-dashed border-z-border text-center text-z-secondary text-sm`,children:`No nested fields added yet.`}):(0,P.jsx)(`div`,{className:`space-y-4`,children:e.map((e,t)=>(0,P.jsxs)(`div`,{className:`p-4 relative group border border-z-border bg-z-panel`,children:[(0,P.jsx)(`button`,{type:`button`,onClick:()=>o(t),className:`absolute top-2 right-2 opacity-0 group-hover:opacity-100 p-1 text-red-500/50 hover:text-red-500 transition-all rounded-none hover:bg-red-500/10 z-10`,children:(0,P.jsx)(r,{size:12})}),(0,P.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 pr-6`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-xs font-semibold text-z-secondary block mb-1`,children:`Field Name (key)`}),(0,P.jsx)(`input`,{type:`text`,value:e.name,onChange:e=>s(t,`name`,e.target.value.replace(/\s+/g,`_`).replace(/[^a-zA-Z0-9_]/g,``)),className:M(c,`w-full rounded-none font-mono text-xs`),placeholder:`fieldName`})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-xs font-semibold text-z-secondary block mb-1`,children:`Field Type`}),(0,P.jsx)(R,{value:e.type,onChange:e=>s(t,`type`,e),theme:n})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:`text-xs font-semibold text-z-secondary block mb-1`,children:`Display Label`}),(0,P.jsx)(`input`,{type:`text`,value:e.label||``,onChange:e=>s(t,`label`,e.target.value),className:M(c,`w-full rounded-none text-xs`),placeholder:`Human readable label`})]})]}),(0,P.jsx)(B,{field:e,onUpdate:(e,n)=>s(t,e,n),theme:n,availableCollections:i})]},t))})]})}function B({field:e,onUpdate:t,theme:n,availableCollections:r}){let[i,a]=(0,N.useState)(!1),o=M(`w-full border p-2 text-sm font-mono outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors rounded-none shadow-sm`,`z-input`),s=`accent-gray-500 w-3.5 h-3.5`,c=`text-sm font-semibold text-z-secondary`;return(0,P.jsxs)(`div`,{className:`mt-2`,children:[(0,P.jsxs)(`button`,{type:`button`,onClick:()=>a(!i),className:`flex items-center gap-1.5 text-sm font-semibold text-z-secondary hover:text-z-secondary transition-colors`,children:[i?(0,P.jsx)(D,{size:10}):(0,P.jsx)(y,{size:10}),`Advanced Options`]}),(0,P.jsx)(S,{children:i&&(0,P.jsx)(E.div,{initial:{height:0,opacity:0},animate:{height:`auto`,opacity:1},exit:{height:0,opacity:0},className:`overflow-hidden`,children:(0,P.jsxs)(`div`,{className:M(`mt-3 p-4 border space-y-4 rounded-none shadow-sm`,`z-panel shadow-sm`),children:[(0,P.jsx)(`div`,{className:`flex flex-wrap gap-x-6 gap-y-2`,children:[[`required`,`Required`],[`unique`,`Unique`],[`index`,`Index`],[`hidden`,`Hidden`],[`readOnly`,`Read Only`]].map(([n,r])=>(0,P.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,P.jsx)(`input`,{type:`checkbox`,checked:!!e[n],onChange:e=>t(n,e.target.checked),className:s}),(0,P.jsx)(`span`,{className:c,children:r})]},n))}),(0,P.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-3`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Placeholder`}),(0,P.jsx)(`input`,{type:`text`,value:e.placeholder||``,onChange:e=>t(`placeholder`,e.target.value),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Default Value`}),(0,P.jsx)(`input`,{type:`text`,value:e.defaultValue??``,onChange:e=>t(`defaultValue`,e.target.value),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Description`}),(0,P.jsx)(`input`,{type:`text`,value:e.description||``,onChange:e=>t(`description`,e.target.value),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Width (e.g. 50%)`}),(0,P.jsx)(`input`,{type:`text`,value:e.width||``,onChange:e=>t(`width`,e.target.value),className:o})]}),(e.type===`text`||e.type===`textarea`)&&(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Min Length`}),(0,P.jsx)(`input`,{type:`number`,value:e.min??``,onChange:e=>t(`min`,Number(e.target.value)),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Max Length`}),(0,P.jsx)(`input`,{type:`number`,value:e.max??``,onChange:e=>t(`max`,Number(e.target.value)),className:o})]}),(0,P.jsxs)(`div`,{className:`col-span-2`,children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Regex Pattern`}),(0,P.jsx)(`input`,{type:`text`,value:e.regex||``,onChange:e=>t(`regex`,e.target.value),className:o,placeholder:`^[a-z]+$`})]})]}),e.type===`number`&&(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Min`}),(0,P.jsx)(`input`,{type:`number`,value:e.min??``,onChange:e=>t(`min`,Number(e.target.value)),className:o})]}),(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Max`}),(0,P.jsx)(`input`,{type:`number`,value:e.max??``,onChange:e=>t(`max`,Number(e.target.value)),className:o})]})]})]}),e.type===`relation`&&(0,P.jsxs)(`div`,{className:`space-y-3`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-1`),children:`Relates To Collection`}),(0,P.jsxs)(`select`,{value:e.relationTo||``,onChange:e=>t(`relationTo`,e.target.value),className:M(o,`cursor-pointer`),children:[(0,P.jsx)(`option`,{value:``,children:`-- Select Collection --`}),r.map(e=>(0,P.jsx)(`option`,{value:e,children:e},e))]})]}),(0,P.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,P.jsx)(`input`,{type:`checkbox`,checked:!!e.hasMany,onChange:e=>t(`hasMany`,e.target.checked),className:s}),(0,P.jsx)(`span`,{className:c,children:`Has Many (array of references)`})]})]}),(e.type===`array`||e.type===`group`)&&(0,P.jsx)(z,{fields:e.fields||[],onUpdate:e=>t(`fields`,e),theme:n,availableCollections:r}),e.type===`select`&&(0,P.jsxs)(`div`,{children:[(0,P.jsx)(`label`,{className:M(c,`block mb-2`),children:`Options`}),(0,P.jsxs)(`div`,{className:`space-y-2`,children:[(e.options||[]).map((n,r)=>(0,P.jsxs)(`div`,{className:`flex gap-2`,children:[(0,P.jsx)(`input`,{type:`text`,value:n.label,onChange:n=>{let i=[...e.options||[]];i[r]={...i[r],label:n.target.value},t(`options`,i)},placeholder:`Label`,className:M(o,`flex-1`)}),(0,P.jsx)(`input`,{type:`text`,value:n.value,onChange:n=>{let i=[...e.options||[]];i[r]={...i[r],value:n.target.value},t(`options`,i)},placeholder:`value`,className:M(o,`flex-1 font-mono`)}),(0,P.jsx)(`button`,{type:`button`,onClick:()=>t(`options`,(e.options||[]).filter((e,t)=>t!==r)),className:`p-2 text-red-500/60 hover:text-red-500 transition-colors`,children:(0,P.jsx)(b,{size:12})})]},r)),(0,P.jsxs)(`button`,{type:`button`,onClick:()=>t(`options`,[...e.options||[],{label:``,value:``}]),className:`flex items-center gap-1 text-sm font-semibold text-z-secondary hover:text-z-secondary`,children:[(0,P.jsx)(m,{size:10}),` Add Option`]})]})]})]})})})]})}function V(){let{theme:e}=re(),t=e===`dark`,[n,i]=(0,N.useState)(`New Collection`),[a,l]=(0,N.useState)(`new-collection`),[d,f]=(0,N.useState)([]),[p,h]=(0,N.useState)(I),[_,y]=(0,N.useState)([]),[x,ne]=(0,N.useState)(!0),[w,D]=(0,N.useState)(null),O=_.find(e=>(e._id||e.id)===w),k=O?.isCodeFirst,[A,F]=(0,N.useState)(!1),[z,V]=(0,N.useState)(!1),[oe,H]=(0,N.useState)(!1),[se,U]=(0,N.useState)(!1),[W,ce]=(0,N.useState)(``),[G,K]=(0,N.useState)(!1),[q,le]=(0,N.useState)(``),[J,ue]=(0,N.useState)(!1),[de,Y]=(0,N.useState)(!1),[fe,pe]=(0,N.useState)([]),[me,he]=(0,N.useState)(!1);(0,N.useEffect)(()=>{let e=JSON.stringify({slug:a,collectionName:n,fields:d,settings:p});he(O?e!==JSON.stringify({slug:O.slug,collectionName:O.plural||O.slug,fields:O.fields||[],settings:{...I,...O.settings||{}}}):e!==JSON.stringify({slug:`new-collection`,collectionName:`New Collection`,fields:[],settings:I}))},[a,n,d,p,O]),ae({hasUnsavedChanges:me});let X=(0,N.useCallback)(async()=>{try{let[e,t]=await Promise.all([j.get(`/schemas`).catch(()=>({data:{data:[]}})),j.get(`/system/schemas`).catch(()=>({data:{data:{collections:[]}}}))]),n=e.data?.data,r=Array.isArray(n)?n:Array.isArray(n?.schemas)?n.schemas:[],i=t.data?.data?.collections||[],a=Array.isArray(i)?i.map(e=>({...e,id:e.slug,isCodeFirst:!0})):[],o=new Map;for(let e of[...r,...a])o.set(e.slug,e);y(Array.from(o.values()).sort((e,t)=>e.slug.localeCompare(t.slug)))}catch{y([])}finally{ne(!1)}},[]);(0,N.useEffect)(()=>{X(),j.get(`/schemas`).then(e=>{let t=e.data?.data;pe((Array.isArray(t?.collections)?t.collections:Array.isArray(t)?t:[]).map(e=>e.slug).filter(Boolean))}).catch(()=>{})},[X]);let ge=e=>{D(e._id||e.id||null),i(e.plural||e.slug),l(e.slug),f(e.fields||[]),h({...I,...e.settings||{}}),C.success(`Loaded schema: ${e.slug}`)},Z=()=>{D(null),i(`New Collection`),l(`new-collection`),f([]),h(I)},_e=()=>{f(e=>[...e,{name:`field${e.length+1}`,type:`text`,label:`Field ${e.length+1}`}])},ve=e=>{f(t=>t.filter((t,n)=>n!==e))},Q=(e,t,n)=>{f(r=>{let i=[...r];return i[e]={...i[e],[t]:n},i})},ye=async()=>{if(!a||!n)return C.error(`Name and slug required`);F(!0);try{let e={slug:a,singular:n,plural:n,fields:d,settings:p};if(w)await j.put(`/schemas/${w}`,e),C.success(`Schema updated!`);else{let t=await j.post(`/schemas`,e),n=t.data?.data?._id||t.data?.data?.id;n&&D(n),C.success(`Schema created!`)}await X(),await j.post(`/system/schema/reload`).catch(()=>{})}catch(e){C.error(e.response?.data?.error?.message||`Failed to save schema`)}finally{F(!1)}},be=async(e,t)=>{try{await j.delete(`/schemas/${e}`),C.success(`Schema "${t}" deleted`),w===e&&Z(),await X()}catch{C.error(`Failed to delete schema`)}},xe=async()=>{if(!W)return C.error(`Please provide a connection string`);K(!0);try{let e=(await j.post(`/system/introspect`,{connectionString:W})).data.data;if(e?.length>0){let t=e[0];i(t.name),l(L(t.name)),f(t.fields||[]),C.success(`Introspected: ${t.name}`),U(!1)}else C.error(`No tables found`)}catch(e){C.error(e.response?.data?.error||`Introspection failed`)}finally{K(!1)}},Se=async()=>{if(!q)return C.error(`Enter a prompt first`);ue(!0);try{let e=(await j.post(`/system/ai-architect`,{prompt:q})).data?.data;e&&(i(e.name||e.slug||`AI Collection`),l(e.slug||L(e.name||`ai-collection`)),f(e.fields||[]),C.success(`AI schema generated!`),Y(!1))}catch(e){C.error(e.response?.data?.error?.message||`AI generation failed`)}finally{ue(!1)}},Ce=()=>{let e=d.map(e=>{let t=` name: '${e.name}',\n type: '${e.type}',`;return e.label&&(t+=`\n label: '${e.label}',`),e.required&&(t+=`
2
2
  required: true,`),e.unique&&(t+=`
3
3
  unique: true,`),e.relationTo&&(t+=`\n relationTo: '${e.relationTo}',`),e.options?.length&&(t+=`\n options: ${JSON.stringify(e.options)},`),` {\n${t}\n },`}).join(`
4
4
  `),t=Object.entries(p).filter(([,e])=>e===!0).map(([e])=>` ${e}: true,`).join(`