@zenith-open/zenithcms-admin 1.0.0-beta.1

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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +43 -0
  3. package/dist/assets/ApiExplorerPage-UJpoKRI0.js +42 -0
  4. package/dist/assets/ApiExplorerPage-UJpoKRI0.js.map +1 -0
  5. package/dist/assets/AuditLogPage-8xYlRl1I.js +1 -0
  6. package/dist/assets/AuditLogPage-8xYlRl1I.js.map +1 -0
  7. package/dist/assets/BlockBuilderPage-DcOo3Vnt.js +1 -0
  8. package/dist/assets/BlockBuilderPage-DcOo3Vnt.js.map +1 -0
  9. package/dist/assets/BuilderPage-Iu8F_bN1.js +1 -0
  10. package/dist/assets/BuilderPage-Iu8F_bN1.js.map +1 -0
  11. package/dist/assets/CollectionHooksPage-Dn_ujtlp.js +7 -0
  12. package/dist/assets/CollectionHooksPage-Dn_ujtlp.js.map +1 -0
  13. package/dist/assets/CollectionsPage-BSPHf7H2.js +1 -0
  14. package/dist/assets/CollectionsPage-BSPHf7H2.js.map +1 -0
  15. package/dist/assets/ComponentBuilderPage-CT6S12LA.js +14 -0
  16. package/dist/assets/ComponentBuilderPage-CT6S12LA.js.map +1 -0
  17. package/dist/assets/DashboardBuilder-Cbi9Ddiu.js +1 -0
  18. package/dist/assets/DashboardBuilder-Cbi9Ddiu.js.map +1 -0
  19. package/dist/assets/EmptyState-X_SXKpQY.js +1 -0
  20. package/dist/assets/EmptyState-X_SXKpQY.js.map +1 -0
  21. package/dist/assets/MediaLibrary-BzXE95xo.js +1 -0
  22. package/dist/assets/MediaLibrary-BzXE95xo.js.map +1 -0
  23. package/dist/assets/PluginsPage-5YRpbP-N.js +10 -0
  24. package/dist/assets/PluginsPage-5YRpbP-N.js.map +1 -0
  25. package/dist/assets/RedirectsPage-D_4jAdaI.js +1 -0
  26. package/dist/assets/RedirectsPage-D_4jAdaI.js.map +1 -0
  27. package/dist/assets/SchemaBuilderPage-EFA5XIAa.js +14 -0
  28. package/dist/assets/SchemaBuilderPage-EFA5XIAa.js.map +1 -0
  29. package/dist/assets/SettingsPage-BRpcMw48.js +33 -0
  30. package/dist/assets/SettingsPage-BRpcMw48.js.map +1 -0
  31. package/dist/assets/SetupWizard-D57HIkrs.js +62 -0
  32. package/dist/assets/SetupWizard-D57HIkrs.js.map +1 -0
  33. package/dist/assets/SpatialEditor-CPgS7Zrd.js +3 -0
  34. package/dist/assets/SpatialEditor-CPgS7Zrd.js.map +1 -0
  35. package/dist/assets/TemplatesPage-B-nNYv3o.js +1 -0
  36. package/dist/assets/TemplatesPage-B-nNYv3o.js.map +1 -0
  37. package/dist/assets/TrashPage-Ccusal1w.js +1 -0
  38. package/dist/assets/TrashPage-Ccusal1w.js.map +1 -0
  39. package/dist/assets/index-ChcKY5Xe.js +11 -0
  40. package/dist/assets/index-ChcKY5Xe.js.map +1 -0
  41. package/dist/assets/index-CxhwdV2K.css +1 -0
  42. package/dist/assets/login-bg.png +0 -0
  43. package/dist/assets/rolldown-runtime-CNC7AqOf.js +1 -0
  44. package/dist/assets/useUnsavedGuard-CMMKQT9a.js +1 -0
  45. package/dist/assets/useUnsavedGuard-CMMKQT9a.js.map +1 -0
  46. package/dist/assets/utils-fgvbH6CB.js +1 -0
  47. package/dist/assets/utils-fgvbH6CB.js.map +1 -0
  48. package/dist/assets/vendor-C-9IqjvY.js +1 -0
  49. package/dist/assets/vendor-C-9IqjvY.js.map +1 -0
  50. package/dist/assets/vendor-forms-BnBLxarY.js +1 -0
  51. package/dist/assets/vendor-forms-BnBLxarY.js.map +1 -0
  52. package/dist/assets/vendor-react-DQVTOTFO.js +195 -0
  53. package/dist/assets/vendor-react-DQVTOTFO.js.map +1 -0
  54. package/dist/favicon.svg +1 -0
  55. package/dist/icons.svg +24 -0
  56. package/dist/index.html +30 -0
  57. package/dist/logo/zenith.svg +9 -0
  58. package/dist/sw.js +3 -0
  59. package/dist/sw.js.map +1 -0
  60. package/dist/workbox-9c191d2f.js +3 -0
  61. package/dist/workbox-9c191d2f.js.map +1 -0
  62. package/dist/zenith.svg +9 -0
  63. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aman T Shekar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @zenith-open/zenithcms-admin
2
+
3
+ The strictly decoupled React 18 Single Page Application (SPA) that serves as the administrative control plane for the Zenith CMS ecosystem.
4
+
5
+ ## Overview
6
+
7
+ Unlike traditional monolithic CMS platforms, Zenith's Admin UI is completely headless. It communicates with `@zenith-open/zenithcms-core` exclusively via REST and GraphQL. This allows you to host the Admin UI anywhere (Vercel, Netlify, AWS S3, etc.) independently of your backend infrastructure.
8
+
9
+ ## Installation & Bootstrapping
10
+
11
+ The Admin UI is bundled as an NPM package, but it is typically initialized within the standard monorepo scaffolding.
12
+
13
+ ### Development Mode
14
+ ```bash
15
+ # Start the Vite development server (usually orchestrated via turborepo at the root)
16
+ pnpm dev --filter @zenith-open/zenithcms-admin
17
+ ```
18
+
19
+ ### Production Build
20
+ ```bash
21
+ # Compiles the React SPA into the dist/ directory for static hosting
22
+ pnpm build
23
+ ```
24
+
25
+ ## Environment Configuration
26
+
27
+ Because this is a static SPA, all environment variables must be exposed to Vite at build time using the `VITE_` prefix.
28
+
29
+ | Variable | Description |
30
+ |---|---|
31
+ | `VITE_API_URL` | The fully qualified URL of the core backend (e.g., `https://api.zenith.dev`) |
32
+ | `VITE_TELEMETRY_ENABLED` | Set to `false` to disable anonymous usage telemetry |
33
+
34
+ ## Injecting Custom Components
35
+
36
+ If you are developing a plugin that requires injecting React components (such as custom Field Types or Dashboard Widgets) into the UI, you must register them in your project's `main.tsx` payload via the `ComponentRegistry`:
37
+
38
+ ```tsx
39
+ import { ComponentRegistry } from '@zenith-open/zenithcms-admin'
40
+ import { MyCustomField } from './plugins/my-custom-field'
41
+
42
+ ComponentRegistry.registerField('acme-color-picker', MyCustomField)
43
+ ```
@@ -0,0 +1,42 @@
1
+ import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{$n as t,E as n,Ht as r,J as i,Jt as a,Ln as o,Mt as s,Zt as c,cn as l,in as u,ir as d,rr as f,sn as p,vr as m,xr as h}from"./vendor-react-DQVTOTFO.js";import{a as g,o as _,s as v,t as y}from"./utils-fgvbH6CB.js";import{d as b,f as x,p as S}from"./index-ChcKY5Xe.js";var C=e(h(),1),w=m(),T={get:`bg-emerald-500/10 text-emerald-400 border-emerald-500/20`,post:`bg-sky-500/10 text-sky-400 border-sky-500/20`,put:`bg-amber-500/10 text-amber-400 border-amber-500/20`,patch:`bg-violet-500/10 text-violet-400 border-violet-500/20`,delete:`bg-red-500/10 text-red-400 border-red-500/20`};function E(){let[e,m]=(0,C.useState)(`graphql`),{theme:h}=g(),E=h===`dark`,[D,O]=(0,C.useState)(null),k=(0,C.useRef)(null),A=v(e=>e.token),[j,M]=(0,C.useState)(null),[N,P]=(0,C.useState)(!1),[F,I]=(0,C.useState)(null),[L,R]=(0,C.useState)(null),z=`/graphql`,B=`/api/docs`,V=(0,C.useCallback)(async()=>{P(!0),I(null);try{M((await _.get(`/system/openapi.json`)).data)}catch{I(`Could not load API schema. Make sure the backend server is running.`)}finally{P(!1)}},[]);(0,C.useEffect)(()=>{e===`rest`&&!j&&V()},[e,j,V]);let H=(e,t)=>{navigator.clipboard.writeText(e),O(t),setTimeout(()=>O(null),2e3)},U=()=>{k.current?.contentWindow&&A&&k.current.contentWindow.postMessage({type:`ZENITH_AUTH_TOKEN`,token:A},`*`)},W=`3.7.1`,G=`18.3.1`,K=`
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <title>GraphiQL</title>
8
+ <style>
9
+ body { margin: 0; width: 100%; height: 100%; overflow: hidden; }
10
+ #graphiql { height: 100vh; }
11
+ </style>
12
+ <link rel="stylesheet" href="https://unpkg.com/graphiql@${W}/graphiql.min.css" />
13
+ </head>
14
+ <body class="${E?`graphiql-dark`:`graphiql-light`}">
15
+ <div id="graphiql">Loading...</div>
16
+ <script src="https://unpkg.com/react@${G}/umd/react.production.min.js" crossorigin><\/script>
17
+ <script src="https://unpkg.com/react-dom@${G}/umd/react-dom.production.min.js" crossorigin><\/script>
18
+ <script src="https://unpkg.com/graphiql@${W}/graphiql.min.js" crossorigin><\/script>
19
+ <script>
20
+ let authToken = '';
21
+
22
+ window.addEventListener('message', function(event) {
23
+ if (event.data && event.data.type === 'ZENITH_AUTH_TOKEN') {
24
+ authToken = event.data.token || '';
25
+ renderGraphiQL();
26
+ }
27
+ });
28
+
29
+ function renderGraphiQL() {
30
+ const fetcher = GraphiQL.createFetcher({
31
+ url: '${z}',
32
+ headers: { 'Authorization': 'Bearer ' + authToken }
33
+ });
34
+ const root = ReactDOM.createRoot(document.getElementById('graphiql'));
35
+ root.render(React.createElement(GraphiQL, { fetcher: fetcher }));
36
+ }
37
+
38
+ renderGraphiQL();
39
+ <\/script>
40
+ </body>
41
+ </html>
42
+ `;return(0,w.jsxs)(`div`,{className:`flex-1 overflow-y-auto bg-z-body text-z-text`,children:[(0,w.jsx)(S,{title:`API Explorer`,description:`Test and discover GraphQL and REST API endpoints instantly.`,icon:(0,w.jsx)(n,{size:24}),breadcrumbs:[{label:`Development`,path:`/api-explorer`},{label:`API Explorer`}],actions:(0,w.jsxs)(`div`,{className:`flex bg-z-input border border-z-border p-1 rounded-none-none`,children:[(0,w.jsxs)(`button`,{onClick:()=>m(`graphql`),className:y(`flex items-center gap-2 px-4 py-1.5 text-sm font-semibold transition-all`,e===`graphql`?`bg-z-panel text-z-primary shadow-sm border border-z-border`:`text-z-secondary hover:text-z-primary border border-transparent`),children:[(0,w.jsx)(t,{size:14}),` GraphQL`]}),(0,w.jsxs)(`button`,{onClick:()=>m(`rest`),className:y(`flex items-center gap-2 px-4 py-1.5 text-sm font-semibold transition-all`,e===`rest`?`bg-z-panel text-z-primary shadow-sm border border-z-border`:`text-z-secondary hover:text-z-primary border border-transparent`),children:[(0,w.jsx)(c,{size:14}),` REST API`]})]})}),(0,w.jsxs)(`div`,{className:`p-6 max-w-7xl mx-auto space-y-6`,children:[(0,w.jsx)(b,{children:(0,w.jsxs)(x,{className:`p-4 flex flex-col md:flex-row items-start md:items-center justify-between gap-4`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsxs)(`h3`,{className:`text-sm font-bold flex items-center gap-2`,children:[(0,w.jsx)(`span`,{className:y(`w-2 h-2 rounded-full`,e===`graphql`?`bg-pink-500`:`bg-emerald-500`)}),e===`graphql`?`GraphQL Endpoint`:`REST API Explorer`]}),(0,w.jsx)(`p`,{className:`text-xs text-z-secondary mt-1`,children:e===`graphql`?`Queries, Mutations, and automatic Schema Introspection via the Neural Schema Orchestrator.`:`All collection endpoints auto-discovered from your active schema. Click an endpoint to expand.`})]}),(0,w.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,w.jsx)(`code`,{className:y(`px-3 py-1.5 border text-xs font-mono font-medium`,E?`bg-app border-z-border text-z-primary`:`bg-z-body border-z-border text-z-primary`),children:e===`graphql`?z:B}),(0,w.jsx)(`button`,{onClick:()=>H(e===`graphql`?z:B,e),className:`p-1.5 border border-z-border hover:bg-z-hover text-z-secondary hover:text-z-primary transition-colors`,title:`Copy URL`,children:D===e?(0,w.jsx)(l,{size:14,className:`text-green-500`}):(0,w.jsx)(a,{size:14})}),(0,w.jsx)(`a`,{href:e===`graphql`?z:B,target:`_blank`,rel:`noreferrer`,className:`p-1.5 border border-z-border hover:bg-z-hover text-z-secondary hover:text-z-primary transition-colors`,title:`Open in new tab`,children:(0,w.jsx)(r,{size:14})})]})]})}),(0,w.jsx)(b,{className:`flex flex-col overflow-hidden`,style:{minHeight:`600px`},children:(0,w.jsx)(d,{mode:`wait`,children:(0,w.jsx)(f.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},exit:{opacity:0,y:-10},transition:{duration:.15},className:`flex-1 w-full`,style:{minHeight:`600px`},children:e===`graphql`?(0,w.jsx)(`iframe`,{ref:k,title:`GraphQL Playground`,srcDoc:K,className:`w-full border-none bg-white`,style:{height:`700px`},sandbox:`allow-scripts allow-same-origin`,onLoad:U}):(0,w.jsxs)(`div`,{className:`overflow-y-auto p-6 space-y-4`,style:{maxHeight:`700px`},children:[(0,w.jsxs)(`div`,{className:`flex items-center justify-between mb-2`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`h3`,{className:`text-sm font-bold text-z-primary`,children:`REST Endpoints`}),(0,w.jsx)(`p`,{className:`text-xs text-z-secondary mt-0.5`,children:j?`${Object.keys(j.paths||{}).length} paths • Click to expand`:`Fetching from server…`})]}),(0,w.jsx)(`button`,{onClick:V,disabled:N,className:`p-2 border border-z-border hover:bg-z-hover text-z-secondary hover:text-z-primary transition-colors`,title:`Reload schema`,children:(0,w.jsx)(i,{size:13,className:N?`animate-spin`:``})})]}),N?(0,w.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-24 gap-3`,children:[(0,w.jsx)(o,{size:28,className:`animate-spin text-z-secondary`}),(0,w.jsx)(`p`,{className:`text-sm text-z-secondary`,children:`Loading API schema…`})]}):F?(0,w.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-24 gap-4 text-center`,children:[(0,w.jsx)(`div`,{className:y(`w-14 h-14 flex items-center justify-center border`,E?`bg-red-500/5 border-red-500/20`:`bg-red-50 border-red-200`),children:(0,w.jsx)(s,{size:24,className:`text-red-400`})}),(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-sm font-semibold text-z-primary`,children:`Schema unavailable`}),(0,w.jsx)(`p`,{className:`text-xs text-z-secondary mt-1 max-w-xs`,children:F})]}),(0,w.jsxs)(`button`,{onClick:V,className:`flex items-center gap-2 px-4 py-2 border border-z-border hover:border-z-active-border hover:bg-z-hover text-sm font-semibold text-z-secondary hover:text-z-primary transition-all`,children:[(0,w.jsx)(i,{size:12}),` Retry`]})]}):j?(0,w.jsx)(`div`,{className:`space-y-1.5`,children:Object.entries(j.paths||{}).map(([e,t])=>(0,w.jsxs)(`div`,{className:y(`border overflow-hidden`,`border-z-border`),children:[(0,w.jsxs)(`button`,{onClick:()=>R(L===e?null:e),className:y(`w-full flex items-center justify-between px-4 py-3 transition-colors text-left gap-3`,E?`hover:bg-z-hover`:`hover:bg-z-input`),children:[(0,w.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap min-w-0`,children:[Object.keys(t).map(e=>(0,w.jsx)(`span`,{className:y(`px-1.5 py-0.5 text-xs font-bold font-mono border uppercase shrink-0`,T[e]||`text-z-secondary border-z-border bg-z-hover`),children:e},e)),(0,w.jsx)(`code`,{className:`text-xs font-mono text-z-primary truncate`,children:e})]}),(0,w.jsx)(`div`,{className:`shrink-0 text-z-secondary`,children:L===e?(0,w.jsx)(u,{size:13}):(0,w.jsx)(p,{size:13})})]}),(0,w.jsx)(d,{children:L===e&&(0,w.jsx)(f.div,{initial:{height:0,opacity:0},animate:{height:`auto`,opacity:1},exit:{height:0,opacity:0},transition:{duration:.15},className:`overflow-hidden`,children:(0,w.jsx)(`div`,{className:y(`px-4 pb-4 pt-3 space-y-3 border-t`,E?`border-z-border bg-z-hover/20`:`border-z-border bg-z-input/30`),children:Object.entries(t).map(([e,t])=>(0,w.jsxs)(`div`,{className:`space-y-1`,children:[(0,w.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,w.jsx)(`span`,{className:y(`px-1.5 py-0.5 text-xs font-bold font-mono border uppercase shrink-0`,T[e]||`text-z-secondary border-z-border`),children:e}),(0,w.jsx)(`span`,{className:`text-sm font-semibold text-z-primary`,children:t.summary})]}),t.parameters&&t.parameters.length>0&&(0,w.jsxs)(`div`,{className:`ml-14 flex flex-wrap gap-1 text-xs`,children:[(0,w.jsx)(`span`,{className:`text-z-secondary`,children:`Params:`}),t.parameters.map(e=>(0,w.jsxs)(`code`,{className:y(`px-1.5 py-0.5 border font-mono`,E?`bg-z-panel border-z-border text-z-primary`:`bg-white border-z-border text-z-primary`),children:[e.name,e.required&&(0,w.jsx)(`span`,{className:`text-red-400 ml-0.5`,children:`*`})]},e.name))]}),t.responses&&(0,w.jsxs)(`div`,{className:`ml-14 flex gap-1 text-xs`,children:[(0,w.jsx)(`span`,{className:`text-z-secondary`,children:`Responses:`}),Object.keys(t.responses).map(e=>(0,w.jsx)(`span`,{className:y(`px-1.5 py-0.5 border font-mono font-bold`,e.startsWith(`2`)?`text-emerald-400 border-emerald-500/20 bg-emerald-500/10`:`text-amber-400 border-amber-500/20 bg-amber-500/10`),children:e},e))]})]},e))})})})]},e))}):null]})},e)})})]})]})}export{E as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiExplorerPage-UJpoKRI0.js","names":[],"sources":["../../src/pages/ApiExplorerPage.tsx"],"sourcesContent":["import { useState, useEffect, useRef, useCallback } from 'react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { Terminal, Braces, Code, Copy, Check, ExternalLink, RefreshCw, Globe, ChevronDown, ChevronUp, Loader2 } from 'lucide-react'\nimport { cn } from '../lib/utils'\nimport { useTheme } from '../context/ThemeContext'\nimport { PageHeader } from '../components/ui/PageHeader'\nimport { Card, CardContent } from '../components/ui/Card'\nimport { useTenantStore } from '../lib/tenantStore'\nimport api from '../lib/api'\n\nconst METHOD_COLORS: Record<string, string> = {\n get: 'bg-emerald-500/10 text-emerald-400 border-emerald-500/20',\n post: 'bg-sky-500/10 text-sky-400 border-sky-500/20',\n put: 'bg-amber-500/10 text-amber-400 border-amber-500/20',\n patch: 'bg-violet-500/10 text-violet-400 border-violet-500/20',\n delete: 'bg-red-500/10 text-red-400 border-red-500/20',\n}\n\nexport default function ApiExplorerPage() {\n const [activeTab, setActiveTab] = useState<'graphql' | 'rest'>('graphql')\n const { theme } = useTheme()\n const dark = theme === 'dark'\n const [copiedUrl, setCopiedUrl] = useState<string | null>(null)\n const iframeRef = useRef<HTMLIFrameElement>(null)\n const token = useTenantStore((s) => s.token)\n\n // REST inline spec state\n const [restSpec, setRestSpec] = useState<any>(null)\n const [restLoading, setRestLoading] = useState(false)\n const [restError, setRestError] = useState<string | null>(null)\n const [expandedPath, setExpandedPath] = useState<string | null>(null)\n\n const graphqlUrl = `${import.meta.env.VITE_API_URL || '/api/v1'}`.replace('/api/v1', '/graphql')\n const restDocsUrl = `${import.meta.env.VITE_API_URL || '/api/v1'}`.replace('/api/v1', '/api/docs')\n\n const fetchRestSpec = useCallback(async () => {\n setRestLoading(true)\n setRestError(null)\n try {\n const res = await api.get('/system/openapi.json')\n setRestSpec(res.data)\n } catch {\n setRestError('Could not load API schema. Make sure the backend server is running.')\n } finally {\n setRestLoading(false)\n }\n }, [])\n\n useEffect(() => {\n if (activeTab === 'rest' && !restSpec) fetchRestSpec()\n }, [activeTab, restSpec, fetchRestSpec])\n\n const handleCopy = (url: string, type: string) => {\n navigator.clipboard.writeText(url)\n setCopiedUrl(type)\n setTimeout(() => setCopiedUrl(null), 2000)\n }\n\n // Securely pass token to the iframe via postMessage after it loads\n const handleIframeLoad = () => {\n if (iframeRef.current?.contentWindow && token) {\n iframeRef.current.contentWindow.postMessage(\n { type: 'ZENITH_AUTH_TOKEN', token },\n '*'\n )\n }\n }\n\n // Version-pinned CDN resources for security and stability\n const GRAPHIQL_VERSION = '3.7.1'\n const REACT_VERSION = '18.3.1'\n\n const graphiqlHTML = `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>GraphiQL</title>\n <style>\n body { margin: 0; width: 100%; height: 100%; overflow: hidden; }\n #graphiql { height: 100vh; }\n </style>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/graphiql@${GRAPHIQL_VERSION}/graphiql.min.css\" />\n </head>\n <body class=\"${dark ? 'graphiql-dark' : 'graphiql-light'}\">\n <div id=\"graphiql\">Loading...</div>\n <script src=\"https://unpkg.com/react@${REACT_VERSION}/umd/react.production.min.js\" crossorigin></script>\n <script src=\"https://unpkg.com/react-dom@${REACT_VERSION}/umd/react-dom.production.min.js\" crossorigin></script>\n <script src=\"https://unpkg.com/graphiql@${GRAPHIQL_VERSION}/graphiql.min.js\" crossorigin></script>\n <script>\n let authToken = '';\n\n window.addEventListener('message', function(event) {\n if (event.data && event.data.type === 'ZENITH_AUTH_TOKEN') {\n authToken = event.data.token || '';\n renderGraphiQL();\n }\n });\n\n function renderGraphiQL() {\n const fetcher = GraphiQL.createFetcher({\n url: '${graphqlUrl}',\n headers: { 'Authorization': 'Bearer ' + authToken }\n });\n const root = ReactDOM.createRoot(document.getElementById('graphiql'));\n root.render(React.createElement(GraphiQL, { fetcher: fetcher }));\n }\n\n renderGraphiQL();\n </script>\n </body>\n </html>\n `\n\n return (\n <div className=\"flex-1 overflow-y-auto bg-z-body text-z-text\">\n <PageHeader\n title=\"API Explorer\"\n description=\"Test and discover GraphQL and REST API endpoints instantly.\"\n icon={<Terminal size={24} />}\n breadcrumbs={[{ label: 'Development', path: '/api-explorer' }, { label: 'API Explorer' }]}\n actions={\n <div className=\"flex bg-z-input border border-z-border p-1 rounded-none-none\">\n <button\n onClick={() => setActiveTab('graphql')}\n className={cn(\n 'flex items-center gap-2 px-4 py-1.5 text-sm font-semibold transition-all',\n activeTab === 'graphql'\n ? 'bg-z-panel text-z-primary shadow-sm border border-z-border'\n : 'text-z-secondary hover:text-z-primary border border-transparent'\n )}\n >\n <Braces size={14} /> GraphQL\n </button>\n <button\n onClick={() => setActiveTab('rest')}\n className={cn(\n 'flex items-center gap-2 px-4 py-1.5 text-sm font-semibold transition-all',\n activeTab === 'rest'\n ? 'bg-z-panel text-z-primary shadow-sm border border-z-border'\n : 'text-z-secondary hover:text-z-primary border border-transparent'\n )}\n >\n <Code size={14} /> REST API\n </button>\n </div>\n }\n />\n\n <div className=\"p-6 max-w-7xl mx-auto space-y-6\">\n <Card>\n <CardContent className=\"p-4 flex flex-col md:flex-row items-start md:items-center justify-between gap-4\">\n <div>\n <h3 className=\"text-sm font-bold flex items-center gap-2\">\n <span className={cn('w-2 h-2 rounded-full', activeTab === 'graphql' ? 'bg-pink-500' : 'bg-emerald-500')} />\n {activeTab === 'graphql' ? 'GraphQL Endpoint' : 'REST API Explorer'}\n </h3>\n <p className=\"text-xs text-z-secondary mt-1\">\n {activeTab === 'graphql'\n ? 'Queries, Mutations, and automatic Schema Introspection via the Neural Schema Orchestrator.'\n : 'All collection endpoints auto-discovered from your active schema. Click an endpoint to expand.'}\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <code className={cn('px-3 py-1.5 border text-xs font-mono font-medium', dark ? 'bg-app border-z-border text-z-primary' : 'bg-z-body border-z-border text-z-primary')}>\n {activeTab === 'graphql' ? graphqlUrl : restDocsUrl}\n </code>\n <button\n onClick={() => handleCopy(activeTab === 'graphql' ? graphqlUrl : restDocsUrl, activeTab)}\n className=\"p-1.5 border border-z-border hover:bg-z-hover text-z-secondary hover:text-z-primary transition-colors\"\n title=\"Copy URL\"\n >\n {copiedUrl === activeTab ? <Check size={14} className=\"text-green-500\" /> : <Copy size={14} />}\n </button>\n <a\n href={activeTab === 'graphql' ? graphqlUrl : restDocsUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"p-1.5 border border-z-border hover:bg-z-hover text-z-secondary hover:text-z-primary transition-colors\"\n title=\"Open in new tab\"\n >\n <ExternalLink size={14} />\n </a>\n </div>\n </CardContent>\n </Card>\n\n <Card className=\"flex flex-col overflow-hidden\" style={{ minHeight: '600px' }}>\n <AnimatePresence mode=\"wait\">\n <motion.div\n key={activeTab}\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -10 }}\n transition={{ duration: 0.15 }}\n className=\"flex-1 w-full\"\n style={{ minHeight: '600px' }}\n >\n {activeTab === 'graphql' ? (\n <iframe\n ref={iframeRef}\n title=\"GraphQL Playground\"\n srcDoc={graphiqlHTML}\n className=\"w-full border-none bg-white\"\n style={{ height: '700px' }}\n sandbox=\"allow-scripts allow-same-origin\"\n onLoad={handleIframeLoad}\n />\n ) : (\n /* ── Inline REST endpoint explorer ── */\n <div className=\"overflow-y-auto p-6 space-y-4\" style={{ maxHeight: '700px' }}>\n <div className=\"flex items-center justify-between mb-2\">\n <div>\n <h3 className=\"text-sm font-bold text-z-primary\">REST Endpoints</h3>\n <p className=\"text-xs text-z-secondary mt-0.5\">\n {restSpec ? `${Object.keys(restSpec.paths || {}).length} paths • Click to expand` : 'Fetching from server…'}\n </p>\n </div>\n <button\n onClick={fetchRestSpec}\n disabled={restLoading}\n className=\"p-2 border border-z-border hover:bg-z-hover text-z-secondary hover:text-z-primary transition-colors\"\n title=\"Reload schema\"\n >\n <RefreshCw size={13} className={restLoading ? 'animate-spin' : ''} />\n </button>\n </div>\n\n {restLoading ? (\n <div className=\"flex flex-col items-center justify-center py-24 gap-3\">\n <Loader2 size={28} className=\"animate-spin text-z-secondary\" />\n <p className=\"text-sm text-z-secondary\">Loading API schema…</p>\n </div>\n ) : restError ? (\n <div className=\"flex flex-col items-center justify-center py-24 gap-4 text-center\">\n <div className={cn('w-14 h-14 flex items-center justify-center border', dark ? 'bg-red-500/5 border-red-500/20' : 'bg-red-50 border-red-200')}>\n <Globe size={24} className=\"text-red-400\" />\n </div>\n <div>\n <p className=\"text-sm font-semibold text-z-primary\">Schema unavailable</p>\n <p className=\"text-xs text-z-secondary mt-1 max-w-xs\">{restError}</p>\n </div>\n <button\n onClick={fetchRestSpec}\n className=\"flex items-center gap-2 px-4 py-2 border border-z-border hover:border-z-active-border hover:bg-z-hover text-sm font-semibold text-z-secondary hover:text-z-primary transition-all\"\n >\n <RefreshCw size={12} /> Retry\n </button>\n </div>\n ) : restSpec ? (\n <div className=\"space-y-1.5\">\n {Object.entries(restSpec.paths || {}).map(([path, methods]: [string, any]) => (\n <div key={path} className={cn('border overflow-hidden', dark ? 'border-z-border' : 'border-z-border')}>\n <button\n onClick={() => setExpandedPath(expandedPath === path ? null : path)}\n className={cn(\n 'w-full flex items-center justify-between px-4 py-3 transition-colors text-left gap-3',\n dark ? 'hover:bg-z-hover' : 'hover:bg-z-input'\n )}\n >\n <div className=\"flex items-center gap-2 flex-wrap min-w-0\">\n {Object.keys(methods).map(method => (\n <span\n key={method}\n className={cn('px-1.5 py-0.5 text-xs font-bold font-mono border uppercase shrink-0', METHOD_COLORS[method] || 'text-z-secondary border-z-border bg-z-hover')}\n >\n {method}\n </span>\n ))}\n <code className=\"text-xs font-mono text-z-primary truncate\">{path}</code>\n </div>\n <div className=\"shrink-0 text-z-secondary\">\n {expandedPath === path ? <ChevronUp size={13} /> : <ChevronDown size={13} />}\n </div>\n </button>\n <AnimatePresence>\n {expandedPath === path && (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: 'auto', opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={{ duration: 0.15 }}\n className=\"overflow-hidden\"\n >\n <div className={cn('px-4 pb-4 pt-3 space-y-3 border-t', dark ? 'border-z-border bg-z-hover/20' : 'border-z-border bg-z-input/30')}>\n {Object.entries(methods).map(([method, op]: [string, any]) => (\n <div key={method} className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <span className={cn('px-1.5 py-0.5 text-xs font-bold font-mono border uppercase shrink-0', METHOD_COLORS[method] || 'text-z-secondary border-z-border')}>\n {method}\n </span>\n <span className=\"text-sm font-semibold text-z-primary\">{op.summary}</span>\n </div>\n {op.parameters && op.parameters.length > 0 && (\n <div className=\"ml-14 flex flex-wrap gap-1 text-xs\">\n <span className=\"text-z-secondary\">Params:</span>\n {op.parameters.map((p: any) => (\n <code key={p.name} className={cn('px-1.5 py-0.5 border font-mono', dark ? 'bg-z-panel border-z-border text-z-primary' : 'bg-white border-z-border text-z-primary')}>\n {p.name}\n {p.required && <span className=\"text-red-400 ml-0.5\">*</span>}\n </code>\n ))}\n </div>\n )}\n {op.responses && (\n <div className=\"ml-14 flex gap-1 text-xs\">\n <span className=\"text-z-secondary\">Responses:</span>\n {Object.keys(op.responses).map(code => (\n <span key={code} className={cn('px-1.5 py-0.5 border font-mono font-bold',\n code.startsWith('2') ? 'text-emerald-400 border-emerald-500/20 bg-emerald-500/10' : 'text-amber-400 border-amber-500/20 bg-amber-500/10'\n )}>{code}</span>\n ))}\n </div>\n )}\n </div>\n ))}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n )}\n </motion.div>\n </AnimatePresence>\n </Card>\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{C as t,Ct as n,Dt as r,En as i,H as a,J as o,Kt as s,Ln as c,Ut as l,_n as u,an as d,l as f,on as p,rr as m,u as h,vr as g,xr as _}from"./vendor-react-DQVTOTFO.js";import{a as v,o as y,t as b}from"./utils-fgvbH6CB.js";import{p as x}from"./index-ChcKY5Xe.js";var S=e(_(),1),C=g(),w=()=>{let{theme:e}=v(),[g,_]=(0,S.useState)([]),[w,T]=(0,S.useState)(!0),[E,D]=(0,S.useState)(1),[O,k]=(0,S.useState)(0),[A,j]=(0,S.useState)(1),[M,N]=(0,S.useState)(``),[P,F]=(0,S.useState)(!1),[I,L]=(0,S.useState)(null),[R,z]=(0,S.useState)(!1),[B,V]=(0,S.useState)(null),[H,U]=(0,S.useState)(``),[W,G]=(0,S.useState)(!1),[K,q]=(0,S.useState)(``),[J,Y]=(0,S.useState)(``),[X,Z]=(0,S.useState)(30),Q=(0,S.useCallback)(async()=>{T(!0);try{let e={page:E,limit:25};M&&(e.search=M),H&&(e.action=H);let t=await y.get(`/system/audit-logs`,{params:e});_(t.data.data||[]),t.data.meta?.pagination&&(k(t.data.meta.pagination.total),j(t.data.meta.pagination.totalPages))}catch{f.error(`Failed to fetch audit logs`)}finally{setTimeout(()=>T(!1),300)}},[E,M,H]),$=(0,S.useCallback)(async()=>{try{let e=await y.get(`/system/audit-logs/stats`);e.data.data&&L(e.data.data)}catch{}},[]);(0,S.useEffect)(()=>{Q(),$()},[Q,$]);let ee=()=>{D(1),Q()},te=async()=>{F(!0);try{let e=await y.get(`/system/audit-logs`,{params:{limit:500}}),t=new Blob([JSON.stringify(e.data.data,null,2)],{type:`application/json`}),n=window.URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.setAttribute(`download`,`ZENITH_AUDIT_${new Date().toISOString().replace(/[:.]/g,`-`)}.json`),document.body.appendChild(r),r.click(),r.remove(),window.URL.revokeObjectURL(n),f.success(`Report exported`)}catch{f.error(`Export failed`)}finally{F(!1)}},ne=()=>{q(Math.floor(1e5+Math.random()*9e5).toString()),Y(``),Z(30),G(!0)},re=()=>{if(J!==K){f.error(`Authorization code does not match`);return}G(!1),z(!0);let e=new Date(Date.now()-X*24*60*60*1e3).toISOString();f.promise(y.post(`/system/audit-logs/purge`,{before:e}),{loading:`Purging audit logs...`,success:e=>(Q(),$(),e.data?.data?.message||`Purged ${e.data?.data?.deleted||0} audit log entries`),error:`Purge failed`}).finally(()=>z(!1))},ie=e=>e?.toUpperCase()||`UNKNOWN`,ae=e=>{let t=e?.toUpperCase();return t===`CREATE`?`bg-emerald-50 text-emerald-600 dark:bg-emerald-500/10 dark:text-emerald-400 border-emerald-200 dark:border-emerald-500/20`:t===`UPDATE`?`bg-blue-50 text-blue-600 dark:bg-blue-500/10 dark:text-blue-400 border-blue-200 dark:border-blue-500/20`:t===`DELETE`?`bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400 border-red-200 dark:border-red-500/20`:`bg-amber-50 text-amber-600 dark:bg-amber-500/10 dark:text-amber-400 border-amber-200 dark:border-amber-500/20`},oe=e=>e.userName||e.userEmail||`System`;return(0,C.jsxs)(`div`,{className:`flex flex-col h-[calc(100vh-64px)] overflow-hidden`,children:[(0,C.jsx)(x,{title:`Audit Logs`,description:`System History`,icon:(0,C.jsx)(r,{size:24}),backLink:{to:`/`,label:`Dashboard`},actions:(0,C.jsxs)(`div`,{className:`flex items-center gap-4`,children:[(0,C.jsxs)(`div`,{className:b(`px-6 py-2 border rounded-lg flex items-center gap-8 shadow-sm transition-all`,`bg-z-panel border-z-border`),children:[(0,C.jsxs)(`div`,{className:`flex flex-col items-end`,children:[(0,C.jsx)(`span`,{className:`text-sm font-semibold text-z-muted opacity-60`,children:`Total Logs`}),(0,C.jsx)(`span`,{className:`text-xl font-semibold leading-none text-z-secondary `,children:O.toLocaleString()})]}),I&&(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(`div`,{className:b(`w-px h-8`,e===`dark`?`bg-z-hover`:`bg-[var(--z-bg-hover)]`)}),(0,C.jsxs)(`div`,{className:`flex flex-col items-end`,children:[(0,C.jsx)(`span`,{className:`text-sm font-semibold text-z-muted opacity-60`,children:`Failed`}),(0,C.jsx)(`span`,{className:`text-xl font-semibold leading-none text-red-500`,children:I.failed})]}),(0,C.jsx)(`div`,{className:b(`w-px h-8`,e===`dark`?`bg-z-hover`:`bg-[var(--z-bg-hover)]`)}),(0,C.jsxs)(`div`,{className:`flex flex-col items-end`,children:[(0,C.jsx)(`span`,{className:`text-sm font-semibold text-z-muted opacity-60`,children:`Status`}),(0,C.jsx)(`span`,{className:`text-xs font-semibold text-z-secondary leading-none`,children:`Stable`})]})]})]}),(0,C.jsx)(`button`,{onClick:()=>{D(1),Q()},className:b(`w-10 h-10 border rounded-lg flex items-center justify-center transition-all hover:scale-105 active:scale-95 shadow-sm`,e===`dark`?`bg-z-panel border-z-border text-z-muted hover:border-z-border`:`bg-z-panel border-z-border text-z-muted hover:border-[var(--z-border-strong)]`),children:(0,C.jsx)(o,{size:20,className:w?`animate-spin`:``})})]})}),(0,C.jsx)(`div`,{className:b(`flex-1 overflow-y-auto p-10 space-y-6 transition-colors duration-500`,e===`dark`?`bg-app text-z-primary`:`bg-[#fafafa] text-z-primary`),children:(0,C.jsxs)(`div`,{className:b(`flex flex-col border rounded-xl shadow-sm transition-all overflow-hidden`,`bg-z-panel border-z-border`),children:[(0,C.jsxs)(`div`,{className:b(`px-8 py-5 border-b flex items-center justify-between gap-6 transition-colors`,`border-z-border`),children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-4 flex-1`,children:[(0,C.jsxs)(`div`,{className:b(`flex items-center gap-3 border px-4 py-2 rounded-md w-full max-w-md shadow-sm transition-all group relative overflow-hidden`,e===`dark`?`bg-[#1c1c1c] border-z-border focus-within:border-z-accent`:`bg-z-panel border-[var(--z-border-strong)] focus-within:border-z-accent`),children:[(0,C.jsx)(a,{size:16,className:`text-z-secondary group-focus-within:text-z-secondary transition-colors`}),(0,C.jsx)(`input`,{type:`text`,value:M,onChange:e=>N(e.target.value),onKeyDown:e=>e.key===`Enter`&&ee(),placeholder:`Search by email, name, collection...`,className:`bg-transparent border-none outline-none text-sm w-full placeholder:text-z-muted dark:placeholder:text-z-secondary`})]}),(0,C.jsxs)(`select`,{value:H,onChange:e=>{U(e.target.value),D(1)},className:b(`px-4 py-2 border rounded-md text-sm outline-none transition-all shadow-sm`,e===`dark`?`bg-[#1c1c1c] border-z-border text-z-primary focus:border-z-accent`:`bg-z-panel border-[var(--z-border-strong)] text-z-primary focus:border-z-accent`),children:[(0,C.jsx)(`option`,{value:``,children:`All Actions`}),(0,C.jsx)(`option`,{value:`create`,children:`Create`}),(0,C.jsx)(`option`,{value:`update`,children:`Update`}),(0,C.jsx)(`option`,{value:`delete`,children:`Delete`}),(0,C.jsx)(`option`,{value:`publish`,children:`Publish`}),(0,C.jsx)(`option`,{value:`unpublish`,children:`Unpublish`}),(0,C.jsx)(`option`,{value:`login`,children:`Login`})]})]}),(0,C.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,C.jsxs)(`button`,{onClick:ne,disabled:R,className:b(`flex items-center gap-2 px-4 py-2 border rounded-md text-sm font-medium transition-all hover:bg-red-50 hover:text-red-600 hover:border-red-200 dark:hover:bg-red-500/10 dark:hover:text-red-400 dark:hover:border-red-500/20`,e===`dark`?`bg-[#1c1c1c] border-z-border text-z-muted`:`bg-z-panel border-[var(--z-border-strong)] text-z-secondary`),children:[(0,C.jsx)(t,{size:14}),`Purge`]}),(0,C.jsxs)(`button`,{onClick:te,disabled:P,className:b(`flex items-center gap-2 px-5 py-2 rounded-md font-medium text-sm transition-all shadow-sm active:scale-95`,e===`dark`?`bg-z-panel text-z-primary hover:bg-[var(--z-border)]`:`bg-z-accent text-z-primary hover:brightness-110`),children:[P?(0,C.jsx)(o,{className:`animate-spin`,size:14}):(0,C.jsx)(l,{size:14}),`Export`]})]})]}),(0,C.jsx)(`div`,{className:`overflow-x-auto`,children:(0,C.jsx)(`div`,{className:`overflow-x-auto min-w-full pb-4`,children:(0,C.jsxs)(`table`,{className:`w-full border-collapse`,children:[(0,C.jsx)(`thead`,{children:(0,C.jsxs)(`tr`,{className:b(`border-b text-left`,e===`dark`?`border-z-border bg-[#1c1c1c]`:`border-z-border bg-[var(--z-bg-input)]`),children:[(0,C.jsx)(`th`,{className:`px-6 py-3 text-xs font-semibold uppercase tracking-wider text-z-muted`,children:`Operator`}),(0,C.jsx)(`th`,{className:`px-6 py-3 text-xs font-semibold uppercase tracking-wider text-z-muted`,children:`Action`}),(0,C.jsx)(`th`,{className:`px-6 py-3 text-xs font-semibold uppercase tracking-wider text-z-muted`,children:`Collection`}),(0,C.jsx)(`th`,{className:`px-6 py-3 text-xs font-semibold uppercase tracking-wider text-z-muted`,children:`Status`}),(0,C.jsx)(`th`,{className:`px-6 py-3 text-xs font-semibold uppercase tracking-wider text-z-muted text-right`,children:`Timestamp`})]})}),(0,C.jsx)(`tbody`,{className:b(`divide-y`,`divide-z-border`),children:w?(0,C.jsx)(`tr`,{children:(0,C.jsx)(`td`,{colSpan:5,className:`py-20 text-center`,children:(0,C.jsx)(c,{size:24,className:`animate-spin text-z-secondary mx-auto opacity-40`})})}):g.length===0?(0,C.jsx)(`tr`,{children:(0,C.jsx)(`td`,{colSpan:5,className:`py-20 text-center`,children:(0,C.jsx)(`div`,{className:`text-z-secondary text-sm font-bold`,children:`No audit logs found`})})}):g.map(t=>(0,C.jsxs)(m.tr,{initial:{opacity:0},animate:{opacity:1},onClick:()=>V(B===(t._id||t.id)?null:t._id||t.id),className:`hover:bg-z-border/[0.02] transition-colors cursor-pointer group`,children:[(0,C.jsx)(`td`,{className:`px-6 py-4`,children:(0,C.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,C.jsx)(`div`,{className:b(`w-8 h-8 rounded-full border flex items-center justify-center flex-shrink-0`,e===`dark`?`bg-[#2c2c2c] border-z-border text-z-secondary`:`bg-[var(--z-bg-hover)] border-z-border text-z-secondary`),children:(0,C.jsx)(n,{size:14})}),(0,C.jsxs)(`div`,{className:`flex flex-col`,children:[(0,C.jsx)(`span`,{className:b(`text-sm font-semibold leading-none`,`text-z-primary`),children:oe(t)}),(0,C.jsx)(`span`,{className:`text-xs text-z-muted mt-1`,children:t.userId?`ID: ${t.userId.slice(-8).toUpperCase()}`:`SYSTEM`})]})]})}),(0,C.jsx)(`td`,{className:`px-6 py-4`,children:(0,C.jsxs)(`div`,{className:b(`px-2.5 py-1 rounded-md text-xs font-semibold inline-flex items-center gap-1.5 border`,ae(t.action)),children:[(0,C.jsx)(h,{size:10,fill:`currentColor`}),ie(t.action)]})}),(0,C.jsx)(`td`,{className:`px-6 py-4`,children:(0,C.jsxs)(`div`,{className:`flex flex-col`,children:[(0,C.jsx)(`span`,{className:b(`text-sm font-medium leading-none`,`text-z-primary`),children:t.collectionName||`SYSTEM`}),t.documentId&&(0,C.jsxs)(`div`,{className:`flex items-center gap-1.5 mt-1 text-z-muted`,children:[(0,C.jsx)(u,{size:10}),(0,C.jsxs)(`span`,{className:`text-xs font-mono`,children:[`DOC_`,t.documentId.slice(-12).toUpperCase()]})]})]})}),(0,C.jsx)(`td`,{className:`px-6 py-4`,children:(0,C.jsx)(`span`,{className:b(`text-sm font-medium`,t.status===`failed`?`text-red-500`:`text-emerald-600 dark:text-emerald-400`),children:t.status===`failed`?`Failed`:`Success`})}),(0,C.jsx)(`td`,{className:`px-6 py-4 text-right`,children:(0,C.jsxs)(`div`,{className:`flex flex-col items-end gap-1`,children:[(0,C.jsx)(`span`,{className:b(`text-sm font-medium leading-none`,e===`dark`?`text-z-secondary`:`text-z-primary`),children:t.timestamp?new Date(t.timestamp).toLocaleDateString():`-`}),(0,C.jsx)(`span`,{className:`text-xs text-z-muted leading-none`,children:t.timestamp?new Date(t.timestamp).toLocaleTimeString():`-`})]})})]},t._id||t.id))})]})})}),B&&(()=>{let t=g.find(e=>(e._id||e.id)===B);return t?(0,C.jsxs)(`div`,{className:b(`px-8 py-6 border-t transition-colors`,e===`dark`?`bg-[#151515] border-z-border`:`bg-[#fafafa] border-z-border`),children:[(0,C.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 text-sm font-mono`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-wider text-z-muted mb-1`,children:`IP Address`}),(0,C.jsx)(`div`,{className:`text-sm font-medium`,children:t.ip||`N/A`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-wider text-z-muted mb-1`,children:`User Agent`}),(0,C.jsx)(`div`,{className:`text-sm font-medium truncate`,title:t.userAgent,children:t.userAgent||`N/A`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-wider text-z-muted mb-1`,children:`Resource`}),(0,C.jsx)(`div`,{className:`text-sm font-medium truncate`,title:t.resource,children:t.resource||`N/A`})]}),t.siteId&&(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-wider text-z-muted mb-1`,children:`Site ID`}),(0,C.jsx)(`div`,{className:`text-sm font-medium`,children:t.siteId})]}),t.hash&&(0,C.jsxs)(C.Fragment,{children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-wider text-z-muted mb-1`,children:`Audit Hash`}),(0,C.jsxs)(`div`,{className:`text-sm font-medium truncate font-mono`,title:t.hash,children:[t.hash.slice(0,24),`...`]})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-wider text-z-muted mb-1`,children:`Prev Hash`}),(0,C.jsx)(`div`,{className:`text-sm font-medium truncate font-mono`,title:t.previousHash,children:t.previousHash?t.previousHash.slice(0,24)+`...`:`GENESIS`})]})]})]}),t.changes&&(0,C.jsxs)(`div`,{className:`mt-4`,children:[(0,C.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-wider text-z-muted mb-2`,children:`Changes`}),(0,C.jsx)(`pre`,{className:b(`p-4 rounded-md text-xs font-mono max-h-48 overflow-auto border shadow-sm`,e===`dark`?`bg-[#111111] border-z-border text-z-secondary`:`bg-z-panel border-z-border text-z-primary`),children:JSON.stringify(t.changes,null,2)})]})]}):null})(),(0,C.jsxs)(`div`,{className:b(`px-8 py-5 border-t flex items-center justify-between transition-colors rounded-b-xl`,e===`dark`?`bg-[#1c1c1c] border-z-border`:`bg-[var(--z-bg-input)] border-z-border`),children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-4`,children:[(0,C.jsx)(s,{size:14,className:`text-z-muted`}),(0,C.jsx)(`span`,{className:`text-xs font-semibold uppercase tracking-wider text-z-muted`,children:`SECURE AUDIT TRAIL`}),I?.byAction&&Object.keys(I.byAction).length>0&&(0,C.jsx)(`div`,{className:`flex items-center gap-3 ml-4`,children:Object.entries(I.byAction).map(([e,t])=>(0,C.jsxs)(`span`,{className:`text-xs font-semibold uppercase tracking-wider text-z-muted`,children:[e,`:`,t]},e))})]}),(0,C.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,C.jsxs)(`span`,{className:`text-xs font-semibold text-z-muted tracking-wider uppercase mr-2`,children:[`Page `,E,` of `,A]}),(0,C.jsx)(`button`,{disabled:E===1,onClick:()=>D(E-1),className:b(`w-8 h-8 border rounded-md flex items-center justify-center transition-all disabled:opacity-20`,e===`dark`?`bg-[#2c2c2c] border-z-border text-z-secondary hover:bg-[#3c3c3c]`:`bg-z-panel border-[var(--z-border-strong)] shadow-sm text-z-secondary hover:bg-[var(--z-bg-input)]`),children:(0,C.jsx)(p,{size:16})}),(0,C.jsx)(`div`,{className:b(`px-3 py-1 rounded-md text-sm font-medium border shadow-sm`,e===`dark`?`bg-z-panel text-z-primary border-z-border`:`bg-z-accent border-z-border text-z-primary`),children:E}),(0,C.jsx)(`button`,{disabled:E>=A,onClick:()=>D(E+1),className:b(`w-8 h-8 border rounded-md flex items-center justify-center transition-all disabled:opacity-20`,e===`dark`?`bg-[#2c2c2c] border-z-border text-z-secondary hover:bg-[#3c3c3c]`:`bg-z-panel border-[var(--z-border-strong)] shadow-sm text-z-secondary hover:bg-[var(--z-bg-input)]`),children:(0,C.jsx)(d,{size:16})})]})]})]})}),W&&(0,C.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm`,children:(0,C.jsxs)(m.div,{initial:{opacity:0,scale:.95},animate:{opacity:1,scale:1},className:b(`w-full max-w-md rounded-xl p-8 shadow-2xl border`,`bg-z-panel border-z-border`),children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-3 text-red-500 mb-4`,children:[(0,C.jsx)(i,{size:24}),(0,C.jsx)(`h2`,{className:`text-xl font-bold text-z-primary tracking-tight`,children:`Purge Audit Logs`})]}),(0,C.jsxs)(`p`,{className:b(`text-sm mb-6 leading-relaxed`,`text-z-muted`),children:[`This action is `,(0,C.jsx)(`span`,{className:`font-bold text-red-500`,children:`irreversible`}),`. It will permanently delete audit logs matching your criteria.`]}),(0,C.jsxs)(`div`,{className:`space-y-5 mb-8`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`label`,{className:b(`block text-xs font-semibold uppercase tracking-wider mb-2`,`text-z-secondary`),children:`Logs older than (days):`}),(0,C.jsx)(`input`,{type:`number`,min:`0`,value:X,onChange:e=>Z(parseInt(e.target.value)||0),className:b(`w-full border rounded-md px-4 py-2.5 text-sm outline-none transition-all`,e===`dark`?`bg-[#1c1c1c] border-z-border text-z-primary focus:border-red-500/50`:`bg-[var(--z-bg-input)] border-[var(--z-border-strong)] text-z-primary focus:border-red-500/50`)}),(0,C.jsx)(`p`,{className:`text-[10px] text-z-muted mt-1.5 font-medium uppercase tracking-wide`,children:`Set to 0 to delete all logs.`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsxs)(`label`,{className:b(`block text-xs font-semibold uppercase tracking-wider mb-2`,`text-z-secondary`),children:[`Authorization Code: `,(0,C.jsx)(`span`,{className:`text-red-400 font-mono select-all font-bold tracking-widest`,children:K})]}),(0,C.jsx)(`input`,{type:`text`,value:J,onChange:e=>Y(e.target.value),placeholder:`Enter the 6-digit code above`,className:b(`w-full border rounded-md px-4 py-2.5 text-sm outline-none transition-all font-mono tracking-widest`,e===`dark`?`bg-[#1c1c1c] border-z-border text-z-primary focus:border-red-500/50`:`bg-[var(--z-bg-input)] border-[var(--z-border-strong)] text-z-primary focus:border-red-500/50`)})]})]}),(0,C.jsxs)(`div`,{className:`flex justify-end gap-3 pt-2`,children:[(0,C.jsx)(`button`,{onClick:()=>G(!1),className:b(`px-5 py-2.5 text-sm font-semibold border rounded-md transition-all`,e===`dark`?`border-z-border bg-z-panel text-z-muted hover:text-z-primary hover:brightness-110`:`border-z-border bg-z-panel text-z-secondary hover:bg-[var(--z-bg-input)]`),children:`Cancel`}),(0,C.jsx)(`button`,{onClick:re,disabled:J!==K,className:`px-5 py-2.5 text-sm font-semibold bg-red-500/10 text-red-500 border border-red-500/20 rounded-md hover:bg-red-500 hover:text-z-primary transition-all duration-300 disabled:opacity-30 disabled:cursor-not-allowed shadow-sm`,children:`Confirm Purge`})]})]})})]})};export{w as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuditLogPage-8xYlRl1I.js","names":[],"sources":["../../src/pages/AuditLogPage.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback } from 'react'\nimport {\n History,\n Search,\n Download,\n RefreshCw,\n KeyRound,\n Zap,\n ArrowRight,\n Cpu,\n ChevronLeft,\n ChevronRight,\n Loader2,\n Trash2,\n Shield,\n Globe,\n AlertTriangle,\n} from 'lucide-react'\nimport api from '../lib/api'\nimport { cn } from '../lib/utils'\nimport { motion } from 'framer-motion'\nimport { useTheme } from '../context/ThemeContext'\nimport toast from 'react-hot-toast'\nimport { PageHeader } from '../components/ui/PageHeader'\nimport { Card } from '../components/ui/Card'\nimport { Badge } from '../components/ui/Badge'\n\ninterface AuditLogEntry {\n _id?: string\n id?: string\n userEmail?: string\n userName?: string\n userId?: string\n action: string\n collectionName?: string\n documentId?: string\n changes?: any\n ip?: string\n userAgent?: string\n timestamp: string\n status?: string\n resource?: string\n siteId?: string\n hash?: string\n previousHash?: string\n}\n\ninterface AuditStats {\n total: number\n failed: number\n success: number\n byAction: Record<string, number>\n}\n\nconst AuditLogPage: React.FC = () => {\n const { theme } = useTheme()\n const [logs, setLogs] = useState<AuditLogEntry[]>([])\n const [loading, setLoading] = useState(true)\n const [page, setPage] = useState(1)\n const [total, setTotal] = useState(0)\n const [totalPages, setTotalPages] = useState(1)\n const [searchQuery, setSearchQuery] = useState('')\n const [exporting, setExporting] = useState(false)\n const [stats, setStats] = useState<AuditStats | null>(null)\n const [purging, setPurging] = useState(false)\n const [showDetails, setShowDetails] = useState<string | null>(null)\n const [filterAction, setFilterAction] = useState('')\n const [showPurgeModal, setShowPurgeModal] = useState(false)\n const [purgeExpectedCode, setPurgeExpectedCode] = useState('')\n const [purgeInputCode, setPurgeInputCode] = useState('')\n const [purgeDays, setPurgeDays] = useState(30)\n\n const fetchLogs = useCallback(async () => {\n setLoading(true)\n try {\n const params: any = { page, limit: 25 }\n if (searchQuery) params.search = searchQuery\n if (filterAction) params.action = filterAction\n const res = await api.get('/system/audit-logs', { params })\n setLogs(res.data.data || [])\n if (res.data.meta?.pagination) {\n setTotal(res.data.meta.pagination.total)\n setTotalPages(res.data.meta.pagination.totalPages)\n }\n } catch {\n toast.error('Failed to fetch audit logs')\n } finally {\n setTimeout(() => setLoading(false), 300)\n }\n }, [page, searchQuery, filterAction])\n\n const fetchStats = useCallback(async () => {\n try {\n const res = await api.get('/system/audit-logs/stats')\n if (res.data.data) setStats(res.data.data)\n } catch {\n // stats are non-critical\n }\n }, [])\n\n useEffect(() => {\n fetchLogs()\n fetchStats()\n }, [fetchLogs, fetchStats])\n\n const handleSearch = () => {\n setPage(1)\n fetchLogs()\n }\n\n const handleExport = async () => {\n setExporting(true)\n try {\n const res = await api.get('/system/audit-logs', { params: { limit: 500 } })\n const blob = new Blob([JSON.stringify(res.data.data, null, 2)], { type: 'application/json' })\n const url = window.URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.setAttribute(\n 'download',\n `ZENITH_AUDIT_${new Date().toISOString().replace(/[:.]/g, '-')}.json`\n )\n document.body.appendChild(link)\n link.click()\n link.remove()\n window.URL.revokeObjectURL(url)\n toast.success('Report exported')\n } catch {\n toast.error('Export failed')\n } finally {\n setExporting(false)\n }\n }\n\n const handlePurgeClick = () => {\n setPurgeExpectedCode(Math.floor(100000 + Math.random() * 900000).toString())\n setPurgeInputCode('')\n setPurgeDays(30)\n setShowPurgeModal(true)\n }\n\n const executePurge = () => {\n if (purgeInputCode !== purgeExpectedCode) {\n toast.error('Authorization code does not match')\n return\n }\n \n setShowPurgeModal(false)\n setPurging(true)\n const before = new Date(Date.now() - purgeDays * 24 * 60 * 60 * 1000).toISOString()\n toast\n .promise(api.post('/system/audit-logs/purge', { before }), {\n loading: `Purging audit logs...`,\n success: (res: any) => {\n fetchLogs()\n fetchStats()\n return res.data?.data?.message || `Purged ${res.data?.data?.deleted || 0} audit log entries`\n },\n error: 'Purge failed',\n })\n .finally(() => setPurging(false))\n }\n\n const formatAction = (action: string): string => action?.toUpperCase() || 'UNKNOWN'\n\n const getActionColor = (action: string) => {\n const upper = action?.toUpperCase()\n if (upper === 'CREATE')\n return 'bg-emerald-50 text-emerald-600 dark:bg-emerald-500/10 dark:text-emerald-400 border-emerald-200 dark:border-emerald-500/20'\n if (upper === 'UPDATE')\n return 'bg-blue-50 text-blue-600 dark:bg-blue-500/10 dark:text-blue-400 border-blue-200 dark:border-blue-500/20'\n if (upper === 'DELETE') \n return 'bg-red-50 text-red-600 dark:bg-red-500/10 dark:text-red-400 border-red-200 dark:border-red-500/20'\n return 'bg-amber-50 text-amber-600 dark:bg-amber-500/10 dark:text-amber-400 border-amber-200 dark:border-amber-500/20'\n }\n\n const displayName = (log: AuditLogEntry) => log.userName || log.userEmail || 'System'\n\n return (\n <div className=\"flex flex-col h-[calc(100vh-64px)] overflow-hidden\">\n {/* Header */}\n <PageHeader\n title=\"Audit Logs\"\n description=\"System History\"\n icon={<History size={24} />}\n backLink={{ to: '/', label: 'Dashboard' }}\n actions={\n <div className=\"flex items-center gap-4\">\n <div\n className={cn(\n 'px-6 py-2 border rounded-lg flex items-center gap-8 shadow-sm transition-all',\n theme === 'dark'\n ? 'bg-z-panel border-z-border'\n : 'bg-z-panel border-z-border'\n )}\n >\n <div className=\"flex flex-col items-end\">\n <span className=\"text-sm font-semibold text-z-muted opacity-60\">\n Total Logs\n </span>\n <span className=\"text-xl font-semibold leading-none text-z-secondary \">\n {total.toLocaleString()}\n </span>\n </div>\n {stats && (\n <>\n <div\n className={cn('w-px h-8', theme === 'dark' ? 'bg-z-hover' : 'bg-[var(--z-bg-hover)]')}\n />\n <div className=\"flex flex-col items-end\">\n <span className=\"text-sm font-semibold text-z-muted opacity-60\">\n Failed\n </span>\n <span className=\"text-xl font-semibold leading-none text-red-500\">\n {stats.failed}\n </span>\n </div>\n <div\n className={cn('w-px h-8', theme === 'dark' ? 'bg-z-hover' : 'bg-[var(--z-bg-hover)]')}\n />\n <div className=\"flex flex-col items-end\">\n <span className=\"text-sm font-semibold text-z-muted opacity-60\">\n Status\n </span>\n <span className=\"text-xs font-semibold text-z-secondary leading-none\">\n Stable\n </span>\n </div>\n </>\n )}\n </div>\n\n <button\n onClick={() => {\n setPage(1)\n fetchLogs()\n }}\n className={cn(\n 'w-10 h-10 border rounded-lg flex items-center justify-center transition-all hover:scale-105 active:scale-95 shadow-sm',\n theme === 'dark'\n ? 'bg-z-panel border-z-border text-z-muted hover:border-z-border'\n : 'bg-z-panel border-z-border text-z-muted hover:border-[var(--z-border-strong)]'\n )}\n >\n <RefreshCw size={20} className={loading ? 'animate-spin' : ''} />\n </button>\n </div>\n }\n />\n\n <div\n className={cn(\n 'flex-1 overflow-y-auto p-10 space-y-6 transition-colors duration-500',\n theme === 'dark' ? 'bg-app text-z-primary' : 'bg-[#fafafa] text-z-primary'\n )}\n >\n {/* Table Card */}\n <div\n className={cn(\n 'flex flex-col border rounded-xl shadow-sm transition-all overflow-hidden',\n theme === 'dark'\n ? 'bg-z-panel border-z-border'\n : 'bg-z-panel border-z-border'\n )}\n >\n {/* Control Bar */}\n <div\n className={cn(\n 'px-8 py-5 border-b flex items-center justify-between gap-6 transition-colors',\n 'border-z-border'\n )}\n >\n <div className=\"flex items-center gap-4 flex-1\">\n <div\n className={cn(\n 'flex items-center gap-3 border px-4 py-2 rounded-md w-full max-w-md shadow-sm transition-all group relative overflow-hidden',\n theme === 'dark'\n ? 'bg-[#1c1c1c] border-z-border focus-within:border-z-accent'\n : 'bg-z-panel border-[var(--z-border-strong)] focus-within:border-z-accent'\n )}\n >\n <Search\n size={16}\n className=\"text-z-secondary group-focus-within:text-z-secondary transition-colors\"\n />\n <input\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n onKeyDown={(e) => e.key === 'Enter' && handleSearch()}\n placeholder=\"Search by email, name, collection...\"\n className=\"bg-transparent border-none outline-none text-sm w-full placeholder:text-z-muted dark:placeholder:text-z-secondary\"\n />\n </div>\n\n <select\n value={filterAction}\n onChange={(e) => {\n setFilterAction(e.target.value)\n setPage(1)\n }}\n className={cn(\n 'px-4 py-2 border rounded-md text-sm outline-none transition-all shadow-sm',\n theme === 'dark'\n ? 'bg-[#1c1c1c] border-z-border text-z-primary focus:border-z-accent'\n : 'bg-z-panel border-[var(--z-border-strong)] text-z-primary focus:border-z-accent'\n )}\n >\n <option value=\"\">All Actions</option>\n <option value=\"create\">Create</option>\n <option value=\"update\">Update</option>\n <option value=\"delete\">Delete</option>\n <option value=\"publish\">Publish</option>\n <option value=\"unpublish\">Unpublish</option>\n <option value=\"login\">Login</option>\n </select>\n </div>\n\n <div className=\"flex items-center gap-3\">\n <button\n onClick={handlePurgeClick}\n disabled={purging}\n className={cn(\n 'flex items-center gap-2 px-4 py-2 border rounded-md text-sm font-medium transition-all hover:bg-red-50 hover:text-red-600 hover:border-red-200 dark:hover:bg-red-500/10 dark:hover:text-red-400 dark:hover:border-red-500/20',\n theme === 'dark'\n ? 'bg-[#1c1c1c] border-z-border text-z-muted'\n : 'bg-z-panel border-[var(--z-border-strong)] text-z-secondary'\n )}\n >\n <Trash2 size={14} />\n Purge\n </button>\n <button\n onClick={handleExport}\n disabled={exporting}\n className={cn(\n 'flex items-center gap-2 px-5 py-2 rounded-md font-medium text-sm transition-all shadow-sm active:scale-95',\n theme === 'dark'\n ? 'bg-z-panel text-z-primary hover:bg-[var(--z-border)]'\n : 'bg-z-accent text-z-primary hover:brightness-110'\n )}\n >\n {exporting ? (\n <RefreshCw className=\"animate-spin\" size={14} />\n ) : (\n <Download size={14} />\n )}\n Export\n </button>\n </div>\n </div>\n\n {/* Log Table */}\n <div className=\"overflow-x-auto\">\n <div className=\"overflow-x-auto min-w-full pb-4\">\n <table className=\"w-full border-collapse\">\n <thead>\n <tr\n className={cn(\n 'border-b text-left',\n theme === 'dark'\n ? 'border-z-border bg-[#1c1c1c]'\n : 'border-z-border bg-[var(--z-bg-input)]'\n )}\n >\n <th className=\"px-6 py-3 text-xs font-semibold uppercase tracking-wider text-z-muted\">\n Operator\n </th>\n <th className=\"px-6 py-3 text-xs font-semibold uppercase tracking-wider text-z-muted\">\n Action\n </th>\n <th className=\"px-6 py-3 text-xs font-semibold uppercase tracking-wider text-z-muted\">\n Collection\n </th>\n <th className=\"px-6 py-3 text-xs font-semibold uppercase tracking-wider text-z-muted\">\n Status\n </th>\n <th className=\"px-6 py-3 text-xs font-semibold uppercase tracking-wider text-z-muted text-right\">\n Timestamp\n </th>\n </tr>\n </thead>\n <tbody\n className={cn(\n 'divide-y',\n theme === 'dark' ? 'divide-z-border' : 'divide-z-border'\n )}\n >\n {loading ? (\n <tr>\n <td colSpan={5} className=\"py-20 text-center\">\n <Loader2\n size={24}\n className=\"animate-spin text-z-secondary mx-auto opacity-40\"\n />\n </td>\n </tr>\n ) : logs.length === 0 ? (\n <tr>\n <td colSpan={5} className=\"py-20 text-center\">\n <div className=\"text-z-secondary text-sm font-bold\">\n No audit logs found\n </div>\n </td>\n </tr>\n ) : (\n logs.map((log) => (\n <motion.tr\n key={log._id || log.id}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n onClick={() =>\n setShowDetails(\n showDetails === (log._id || log.id) ? null : log._id || log.id\n )\n }\n className=\"hover:bg-z-border/[0.02] transition-colors cursor-pointer group\"\n >\n <td className=\"px-6 py-4\">\n <div className=\"flex items-center gap-3\">\n <div\n className={cn(\n 'w-8 h-8 rounded-full border flex items-center justify-center flex-shrink-0',\n theme === 'dark'\n ? 'bg-[#2c2c2c] border-z-border text-z-secondary'\n : 'bg-[var(--z-bg-hover)] border-z-border text-z-secondary'\n )}\n >\n <KeyRound size={14} />\n </div>\n <div className=\"flex flex-col\">\n <span className={cn(\"text-sm font-semibold leading-none\", theme === 'dark' ? \"text-z-primary\" : \"text-z-primary\")}>\n {displayName(log)}\n </span>\n <span className=\"text-xs text-z-muted mt-1\">\n {log.userId\n ? `ID: ${log.userId.slice(-8).toUpperCase()}`\n : 'SYSTEM'}\n </span>\n </div>\n </div>\n </td>\n <td className=\"px-6 py-4\">\n <div\n className={cn(\n 'px-2.5 py-1 rounded-md text-xs font-semibold inline-flex items-center gap-1.5 border',\n getActionColor(log.action)\n )}\n >\n <Zap size={10} fill=\"currentColor\" />\n {formatAction(log.action)}\n </div>\n </td>\n <td className=\"px-6 py-4\">\n <div className=\"flex flex-col\">\n <span className={cn(\"text-sm font-medium leading-none\", theme === 'dark' ? \"text-z-primary\" : \"text-z-primary\")}>\n {log.collectionName || 'SYSTEM'}\n </span>\n {log.documentId && (\n <div className=\"flex items-center gap-1.5 mt-1 text-z-muted\">\n <ArrowRight size={10} />\n <span className=\"text-xs font-mono\">\n DOC_{log.documentId.slice(-12).toUpperCase()}\n </span>\n </div>\n )}\n </div>\n </td>\n <td className=\"px-6 py-4\">\n <span\n className={cn(\n 'text-sm font-medium',\n log.status === 'failed'\n ? 'text-red-500'\n : 'text-emerald-600 dark:text-emerald-400'\n )}\n >\n {log.status === 'failed' ? 'Failed' : 'Success'}\n </span>\n </td>\n <td className=\"px-6 py-4 text-right\">\n <div className=\"flex flex-col items-end gap-1\">\n <span className={cn(\"text-sm font-medium leading-none\", theme === 'dark' ? \"text-z-secondary\" : \"text-z-primary\")}>\n {log.timestamp ? new Date(log.timestamp).toLocaleDateString() : '-'}\n </span>\n <span className=\"text-xs text-z-muted leading-none\">\n {log.timestamp ? new Date(log.timestamp).toLocaleTimeString() : '-'}\n </span>\n </div>\n </td>\n </motion.tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n </div>\n\n {/* Detail Expand */}\n {showDetails &&\n (() => {\n const log = logs.find((l) => (l._id || l.id) === showDetails)\n if (!log) return null\n return (\n <div\n className={cn(\n 'px-8 py-6 border-t transition-colors',\n theme === 'dark'\n ? 'bg-[#151515] border-z-border'\n : 'bg-[#fafafa] border-z-border'\n )}\n >\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 text-sm font-mono\">\n <div>\n <div className=\"text-xs font-semibold uppercase tracking-wider text-z-muted mb-1\">\n IP Address\n </div>\n <div className=\"text-sm font-medium\">{log.ip || 'N/A'}</div>\n </div>\n <div>\n <div className=\"text-xs font-semibold uppercase tracking-wider text-z-muted mb-1\">\n User Agent\n </div>\n <div className=\"text-sm font-medium truncate\" title={log.userAgent}>\n {log.userAgent || 'N/A'}\n </div>\n </div>\n <div>\n <div className=\"text-xs font-semibold uppercase tracking-wider text-z-muted mb-1\">\n Resource\n </div>\n <div className=\"text-sm font-medium truncate\" title={log.resource}>\n {log.resource || 'N/A'}\n </div>\n </div>\n {log.siteId && (\n <div>\n <div className=\"text-xs font-semibold uppercase tracking-wider text-z-muted mb-1\">\n Site ID\n </div>\n <div className=\"text-sm font-medium\">{log.siteId}</div>\n </div>\n )}\n {log.hash && (\n <>\n <div>\n <div className=\"text-xs font-semibold uppercase tracking-wider text-z-muted mb-1\">\n Audit Hash\n </div>\n <div className=\"text-sm font-medium truncate font-mono\" title={log.hash}>\n {log.hash.slice(0, 24)}...\n </div>\n </div>\n <div>\n <div className=\"text-xs font-semibold uppercase tracking-wider text-z-muted mb-1\">\n Prev Hash\n </div>\n <div className=\"text-sm font-medium truncate font-mono\" title={log.previousHash}>\n {log.previousHash ? log.previousHash.slice(0, 24) + '...' : 'GENESIS'}\n </div>\n </div>\n </>\n )}\n </div>\n {log.changes && (\n <div className=\"mt-4\">\n <div className=\"text-xs font-semibold uppercase tracking-wider text-z-muted mb-2\">\n Changes\n </div>\n <pre\n className={cn(\n 'p-4 rounded-md text-xs font-mono max-h-48 overflow-auto border shadow-sm',\n theme === 'dark'\n ? 'bg-[#111111] border-z-border text-z-secondary'\n : 'bg-z-panel border-z-border text-z-primary'\n )}\n >\n {JSON.stringify(log.changes, null, 2)}\n </pre>\n </div>\n )}\n </div>\n )\n })()}\n\n {/* Footer */}\n <div\n className={cn(\n 'px-8 py-5 border-t flex items-center justify-between transition-colors rounded-b-xl',\n theme === 'dark' ? 'bg-[#1c1c1c] border-z-border' : 'bg-[var(--z-bg-input)] border-z-border'\n )}\n >\n <div className=\"flex items-center gap-4\">\n <Cpu size={14} className=\"text-z-muted\" />\n <span className=\"text-xs font-semibold uppercase tracking-wider text-z-muted\">\n SECURE AUDIT TRAIL\n </span>\n {stats?.byAction && Object.keys(stats.byAction).length > 0 && (\n <div className=\"flex items-center gap-3 ml-4\">\n {Object.entries(stats.byAction).map(([action, count]) => (\n <span\n key={action}\n className=\"text-xs font-semibold uppercase tracking-wider text-z-muted\"\n >\n {action}:{count}\n </span>\n ))}\n </div>\n )}\n </div>\n\n <div className=\"flex items-center gap-3\">\n <span className=\"text-xs font-semibold text-z-muted tracking-wider uppercase mr-2\">\n Page {page} of {totalPages}\n </span>\n <button\n disabled={page === 1}\n onClick={() => setPage(page - 1)}\n className={cn(\n 'w-8 h-8 border rounded-md flex items-center justify-center transition-all disabled:opacity-20',\n theme === 'dark'\n ? 'bg-[#2c2c2c] border-z-border text-z-secondary hover:bg-[#3c3c3c]'\n : 'bg-z-panel border-[var(--z-border-strong)] shadow-sm text-z-secondary hover:bg-[var(--z-bg-input)]'\n )}\n >\n <ChevronLeft size={16} />\n </button>\n\n <div\n className={cn(\n 'px-3 py-1 rounded-md text-sm font-medium border shadow-sm',\n theme === 'dark'\n ? 'bg-z-panel text-z-primary border-z-border'\n : 'bg-z-accent border-z-border text-z-primary'\n )}\n >\n {page}\n </div>\n\n <button\n disabled={page >= totalPages}\n onClick={() => setPage(page + 1)}\n className={cn(\n 'w-8 h-8 border rounded-md flex items-center justify-center transition-all disabled:opacity-20',\n theme === 'dark'\n ? 'bg-[#2c2c2c] border-z-border text-z-secondary hover:bg-[#3c3c3c]'\n : 'bg-z-panel border-[var(--z-border-strong)] shadow-sm text-z-secondary hover:bg-[var(--z-bg-input)]'\n )}\n >\n <ChevronRight size={16} />\n </button>\n </div>\n </div>\n </div>\n </div>\n\n {/* Custom Purge Modal */}\n {showPurgeModal && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm\">\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n className={cn(\n \"w-full max-w-md rounded-xl p-8 shadow-2xl border\",\n theme === 'dark' ? \"bg-z-panel border-z-border\" : \"bg-z-panel border-z-border\"\n )}\n >\n <div className=\"flex items-center gap-3 text-red-500 mb-4\">\n <AlertTriangle size={24} />\n <h2 className=\"text-xl font-bold text-z-primary tracking-tight\">Purge Audit Logs</h2>\n </div>\n <p className={cn(\"text-sm mb-6 leading-relaxed\", theme === 'dark' ? \"text-z-muted\" : \"text-z-muted\")}>\n This action is <span className=\"font-bold text-red-500\">irreversible</span>. It will permanently delete audit logs matching your criteria.\n </p>\n \n <div className=\"space-y-5 mb-8\">\n <div>\n <label className={cn(\"block text-xs font-semibold uppercase tracking-wider mb-2\", theme === 'dark' ? \"text-z-secondary\" : \"text-z-secondary\")}>\n Logs older than (days):\n </label>\n <input\n type=\"number\"\n min=\"0\"\n value={purgeDays}\n onChange={(e) => setPurgeDays(parseInt(e.target.value) || 0)}\n className={cn(\n \"w-full border rounded-md px-4 py-2.5 text-sm outline-none transition-all\",\n theme === 'dark' \n ? \"bg-[#1c1c1c] border-z-border text-z-primary focus:border-red-500/50\" \n : \"bg-[var(--z-bg-input)] border-[var(--z-border-strong)] text-z-primary focus:border-red-500/50\"\n )}\n />\n <p className=\"text-[10px] text-z-muted mt-1.5 font-medium uppercase tracking-wide\">Set to 0 to delete all logs.</p>\n </div>\n \n <div>\n <label className={cn(\"block text-xs font-semibold uppercase tracking-wider mb-2\", theme === 'dark' ? \"text-z-secondary\" : \"text-z-secondary\")}>\n Authorization Code: <span className=\"text-red-400 font-mono select-all font-bold tracking-widest\">{purgeExpectedCode}</span>\n </label>\n <input\n type=\"text\"\n value={purgeInputCode}\n onChange={(e) => setPurgeInputCode(e.target.value)}\n placeholder=\"Enter the 6-digit code above\"\n className={cn(\n \"w-full border rounded-md px-4 py-2.5 text-sm outline-none transition-all font-mono tracking-widest\",\n theme === 'dark' \n ? \"bg-[#1c1c1c] border-z-border text-z-primary focus:border-red-500/50\" \n : \"bg-[var(--z-bg-input)] border-[var(--z-border-strong)] text-z-primary focus:border-red-500/50\"\n )}\n />\n </div>\n </div>\n \n <div className=\"flex justify-end gap-3 pt-2\">\n <button\n onClick={() => setShowPurgeModal(false)}\n className={cn(\n \"px-5 py-2.5 text-sm font-semibold border rounded-md transition-all\",\n theme === 'dark' \n ? \"border-z-border bg-z-panel text-z-muted hover:text-z-primary hover:brightness-110\" \n : \"border-z-border bg-z-panel text-z-secondary hover:bg-[var(--z-bg-input)]\"\n )}\n >\n Cancel\n </button>\n <button\n onClick={executePurge}\n disabled={purgeInputCode !== purgeExpectedCode}\n className=\"px-5 py-2.5 text-sm font-semibold bg-red-500/10 text-red-500 border border-red-500/20 rounded-md hover:bg-red-500 hover:text-z-primary transition-all duration-300 disabled:opacity-30 disabled:cursor-not-allowed shadow-sm\"\n >\n Confirm Purge\n </button>\n </div>\n </motion.div>\n </div>\n )}\n\n </div>\n )\n}\n\nexport default AuditLogPage\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{$n as t,C as n,Dn as r,Et as i,Ft as a,G as o,Ln as s,Lt as c,Mt as l,Ot as u,Q as d,R as f,Rn as p,Sn as m,T as h,Wt as g,Zt as _,_t as v,d as ee,fn as y,gt as b,ir as te,l as x,pt as S,rr as C,un as w,vr as T,xr as E}from"./vendor-react-DQVTOTFO.js";import{a as ne,o as D,t as O}from"./utils-fgvbH6CB.js";import{c as k,p as A}from"./index-ChcKY5Xe.js";var j=e(E(),1),M=T(),N=[{value:`text`,label:`Text`,icon:c,color:`#6b7280`,desc:`Small or long text like title or description`},{value:`textarea`,label:`Textarea`,icon:r,color:`#6b7280`,desc:`Multi-line text for longer descriptions`},{value:`number`,label:`Number`,icon:u,color:`#3b82f6`,desc:`Numbers (integer, float, decimal)`},{value:`email`,label:`Email`,icon:l,color:`var(--z-accent)`,desc:`Email field with validation format`},{value:`password`,label:`Password`,icon:S,color:`#ef4444`,desc:`Password field with encryption`},{value:`checkbox`,label:`Boolean`,icon:h,color:`var(--z-accent)`,desc:`Yes/No, 1/0, True/False`},{value:`date`,label:`Date`,icon:w,color:`#f59e0b`,desc:`A date picker with hours, minutes and seconds`},{value:`media`,label:`Media`,icon:i,color:`#06b6d4`,desc:`Files like images, videos, etc`},{value:`richtext`,label:`Rich Text`,icon:c,color:`#84cc16`,desc:`A rich text editor with formatting options`},{value:`relation`,label:`Relation`,icon:b,color:`#ec4899`,desc:`Refers to another collection`},{value:`json`,label:`JSON`,icon:t,color:`#6366f1`,desc:`Data in JSON format`},{value:`array`,label:`Array`,icon:p,color:`#f59e0b`,desc:`A repeating group of fields`},{value:`row`,label:`Row`,icon:v,color:`#ec4899`,desc:`Group fields side-by-side`},{value:`collapsible`,label:`Collapsible`,icon:m,color:`var(--z-accent)`,desc:`Wrap fields in an accordion`},{value:`tabs`,label:`Tabs`,icon:a,color:`#3b82f6`,desc:`Organize fields into tabs`}];function P(){let{theme:e}=ne(),t=e===`dark`,[r,i]=(0,j.useState)(`New Block`),[a,c]=(0,j.useState)(`new-block`),[u,m]=(0,j.useState)(`General`),[h,v]=(0,j.useState)(`Box`),[b,S]=(0,j.useState)(``),[w,T]=(0,j.useState)([]),[E,P]=(0,j.useState)([]),[F,I]=(0,j.useState)(!0),[L,R]=(0,j.useState)([]),[z,B]=(0,j.useState)(!1),[V,H]=(0,j.useState)(!1),[U,W]=(0,j.useState)(`TYPE`),[G,K]=(0,j.useState)(`BASIC`),[q,J]=(0,j.useState)(null),[Y,X]=(0,j.useState)(null),Z=(0,j.useCallback)(async()=>{try{let e=(await D.get(`/blocks`)).data?.data;P(Array.isArray(e)?e:[])}catch{P([])}finally{I(!1)}},[]);(0,j.useEffect)(()=>{Z(),R([`users`,`pages`,`media`,`categories`])},[Z]);let re=e=>{i(e.labels?.singular||e.slug),c(e.slug),m(e.admin?.category||`General`),v(e.admin?.icon||`Box`),S(e.admin?.description||``),T(e.fields||[]),x.success(`Loaded block: ${e.slug}`)},ie=()=>{i(`New Block`),c(`new-block`),m(`General`),v(`Box`),S(``),T([])},ae=async()=>{if(!a||!r)return x.error(`Name and slug required`);B(!0);try{let e={slug:a,title:r,description:b,category:u,icon:h,fields:w},t=await D.post(`/blocks/generate`,e);k(),x.success(t.data.message||`Block generated as JSON!`),await Z()}catch(e){x.error(e.response?.data?.error?.message||`Failed to generate block`)}finally{B(!1)}},oe=()=>{if(!q?.type)return x.error(`Field type required`);if(q.type!==`row`&&q.type!==`tabs`&&!q.name)return x.error(`Field name is required`);if(Y!==null){let e=[...w];e[Y]=q,T(e)}else T(e=>[...e,q]);H(!1)},se=e=>{T(t=>t.filter((t,n)=>n!==e))},Q=O(`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.5 px-3 rounded-none shadow-sm`,t?`bg-z-panel backdrop-blur-md border-z-border focus:border-z-accent text-z-primary placeholder:text-z-muted`:`bg-z-panel border-z-border focus:border-z-accent text-z-primary placeholder:text-z-muted`),$=E.reduce((e,t)=>{let n=t.admin?.category||`General`;return e[n]||(e[n]=[]),e[n].push(t),e},{});return(0,M.jsxs)(`div`,{className:O(`flex h-[calc(100vh-4rem)] overflow-hidden`,t?`bg-app text-z-primary`:`bg-[var(--z-bg-input)] text-z-primary`),children:[(0,M.jsxs)(`div`,{className:O(`w-64 flex-shrink-0 border-r flex flex-col`,`border-z-border bg-z-panel`),children:[(0,M.jsxs)(`div`,{className:`p-4 border-b border-inherit flex items-center justify-between`,children:[(0,M.jsxs)(`h2`,{className:`text-sm font-semibold flex items-center gap-2`,children:[(0,M.jsx)(g,{size:14,className:`text-z-secondary `}),` Blocks`]}),(0,M.jsx)(`button`,{onClick:ie,className:`p-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary rounded-none transition-colors`,title:`New Block`,children:(0,M.jsx)(d,{size:14})})]}),(0,M.jsx)(`div`,{className:`flex-1 overflow-auto p-4 space-y-4`,children:F?(0,M.jsx)(`div`,{className:`flex justify-center`,children:(0,M.jsx)(s,{className:`animate-spin text-z-muted`,size:16})}):Object.keys($).length===0?(0,M.jsx)(`div`,{className:`text-center text-sm text-z-secondary`,children:`No blocks yet`}):Object.entries($).map(([e,n])=>(0,M.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,M.jsx)(`h3`,{className:`text-sm font-semibold text-z-secondary`,children:e}),(0,M.jsx)(`div`,{className:`space-y-0.5`,children:n.map(e=>(0,M.jsxs)(`button`,{onClick:()=>re(e),className:O(`w-full flex items-center gap-2 text-left px-3 py-2 text-sm font-semibold transition-colors rounded-none truncate`,a===e.slug?`bg-z-accent text-z-logo-text shadow-sm`:t?`text-z-muted hover:bg-z-hover hover:text-z-primary`:`text-z-secondary hover:bg-[var(--z-bg-input)]`),children:[e.isGenerated?(0,M.jsx)(_,{size:12,className:a===e.slug?`text-z-primary`:`text-z-secondary/50`}):(0,M.jsx)(y,{size:12}),e.labels?.singular||e.slug]},e.slug))})]},e))})]}),(0,M.jsxs)(`div`,{className:`flex-1 flex flex-col overflow-hidden relative`,children:[(0,M.jsx)(A,{title:`Component Builder`,description:`${w.length} fields · Generating to config/blocks/${a}.json`,icon:(0,M.jsx)(p,{size:24}),backLink:{to:`/`,label:`Dashboard`},actions:(0,M.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,M.jsxs)(`button`,{onClick:ae,disabled:z,className:`flex items-center gap-2 px-6 py-2.5 bg-z-accent hover:brightness-110 text-z-logo-text text-sm font-semibold rounded-none transition-all shadow-sm disabled:opacity-50`,children:[z?(0,M.jsx)(s,{size:14,className:`animate-spin`}):(0,M.jsx)(o,{size:14}),` Save Code`]})})}),(0,M.jsxs)(`div`,{className:`flex-1 overflow-auto p-6 space-y-6`,children:[(0,M.jsxs)(`div`,{className:O(`rounded-none border p-6 space-y-4 shadow-sm transition-all`,`z-panel`),children:[(0,M.jsxs)(`h3`,{className:`text-sm font-semibold text-z-secondary flex items-center gap-2`,children:[(0,M.jsx)(f,{size:12}),` Component Settings`]}),(0,M.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Display Name`}),(0,M.jsx)(`input`,{type:`text`,value:r,onChange:e=>{i(e.target.value),c(e.target.value.toLowerCase().replace(/\s+/g,`-`).replace(/[^a-z0-9-]/g,``))},className:O(Q,`w-full rounded-none`),placeholder:`e.g. Hero Banner`})]}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`API Slug (filename)`}),(0,M.jsx)(`input`,{type:`text`,value:a,onChange:e=>c(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g,``)),className:O(Q,`w-full rounded-none font-mono`),placeholder:`e.g. hero-banner`})]}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Category`}),(0,M.jsx)(`input`,{type:`text`,value:u,onChange:e=>m(e.target.value),className:O(Q,`w-full rounded-none`),placeholder:`e.g. Layout, Content, Media`})]}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Description`}),(0,M.jsx)(`input`,{type:`text`,value:b,onChange:e=>S(e.target.value),className:O(Q,`w-full rounded-none`),placeholder:`Brief description for editors`})]})]})]}),(0,M.jsxs)(`div`,{className:O(`rounded-none border shadow-sm transition-all`,`z-panel`),children:[(0,M.jsxs)(`div`,{className:`px-6 py-4 border-b border-inherit flex items-center justify-between`,children:[(0,M.jsxs)(`h3`,{className:`text-sm font-semibold text-z-secondary flex items-center gap-2`,children:[(0,M.jsx)(p,{size:12}),` Fields (`,w.length,`)`]}),(0,M.jsxs)(`button`,{onClick:()=>{W(`TYPE`),J({}),X(null),K(`BASIC`),H(!0)},className:`flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary text-sm font-semibold rounded-none transition-all`,children:[(0,M.jsx)(d,{size:12}),` Add new field`]})]}),(0,M.jsx)(`div`,{className:`p-0`,children:w.length===0?(0,M.jsxs)(`div`,{className:`py-16 text-center`,children:[(0,M.jsx)(p,{size:40,className:`mx-auto text-z-primary mb-4`,strokeWidth:1}),(0,M.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary`,children:`No fields yet`})]}):(0,M.jsx)(`div`,{className:`divide-y divide-z-border dark:divide-z-border`,children:w.map((e,t)=>(0,M.jsxs)(`div`,{className:`flex items-center justify-between px-6 py-4 hover:bg-z-hover transition-colors group cursor-pointer`,onClick:()=>{J(e),X(t),W(`SETTINGS`),K(`BASIC`),H(!0)},children:[(0,M.jsxs)(`div`,{className:`flex items-center gap-4`,children:[(0,M.jsx)(`div`,{className:`w-8 h-8 rounded-none bg-z-panel flex items-center justify-center`,children:(()=>{let t=N.find(t=>t.value===e.type);return(0,M.jsx)(t?t.icon:y,{size:14,className:`text-z-secondary `})})()}),(0,M.jsxs)(`div`,{children:[(0,M.jsxs)(`div`,{className:`text-sm font-bold text-z-primary dark:text-z-primary flex items-center gap-2`,children:[e.name||`[${e.type}]`,e.required&&(0,M.jsx)(`span`,{className:`text-sm text-red-500`,children:`*`}),e.i18n&&(0,M.jsx)(l,{size:10,className:`text-z-active-text`})]}),(0,M.jsxs)(`div`,{className:`text-sm font-bold text-z-secondary mt-0.5`,children:[e.type,` `,e.label?`· ${e.label}`:``]})]})]}),(0,M.jsx)(`button`,{onClick:e=>{e.stopPropagation(),se(t)},className:`opacity-0 group-hover:opacity-100 p-2 text-red-500 hover:bg-red-500/10 rounded-none transition-all`,children:(0,M.jsx)(n,{size:14})})]},t))})})]})]})]}),(0,M.jsx)(te,{children:V&&(0,M.jsx)(C.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,M.jsxs)(C.div,{initial:{scale:.95,y:10},animate:{scale:1,y:0},exit:{scale:.95,y:10},className:`w-full max-w-4xl border rounded-none shadow-sm flex flex-col max-h-[85vh] bg-app border-z-border overflow-hidden`,children:[(0,M.jsxs)(`div`,{className:`px-6 py-4 border-b border-z-border flex items-center justify-between bg-app/50`,children:[(0,M.jsx)(`h2`,{className:`text-sm font-semibold text-z-primary flex items-center gap-2`,children:U===`TYPE`?`Select a field for your Component`:`Configure ${q?.type} field`}),(0,M.jsx)(`button`,{onClick:()=>H(!1),className:`text-z-secondary hover:text-z-primary p-1`,children:(0,M.jsx)(ee,{size:18})})]}),U===`TYPE`&&(0,M.jsx)(`div`,{className:`flex-1 overflow-auto p-6 grid grid-cols-2 lg:grid-cols-3 gap-4`,children:N.map(e=>{let t=e.icon;return(0,M.jsxs)(`button`,{onClick:()=>{J({type:e.value,admin:{}}),W(`SETTINGS`)},className:`flex items-start gap-4 p-4 rounded-none border border-z-border bg-z-hover hover:border-z-accent/50 hover:opacity-90/5 transition-all text-left`,children:[(0,M.jsx)(`div`,{className:`mt-1 p-2 rounded-none bg-app/50 border border-z-border`,children:(0,M.jsx)(t,{size:18,style:{color:e.color}})}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`div`,{className:`text-sm font-semibold text-z-primary mb-1`,children:e.label}),(0,M.jsx)(`div`,{className:`text-sm text-z-muted leading-relaxed font-bold`,children:e.desc})]})]},e.value)})}),U===`SETTINGS`&&(0,M.jsxs)(`div`,{className:`flex flex-col flex-1 overflow-hidden`,children:[(0,M.jsx)(`div`,{className:`flex border-b border-z-border px-6 pt-4 gap-6 bg-app/20`,children:[`BASIC`,`VALIDATION`,`ADMIN`].map(e=>(0,M.jsxs)(`button`,{onClick:()=>K(e),className:O(`pb-3 text-sm font-semibold transition-colors relative`,G===e?`text-z-secondary `:`text-z-secondary hover:text-z-primary`),children:[e,G===e&&(0,M.jsx)(C.div,{layoutId:`tab-indicator`,className:`absolute bottom-0 left-0 right-0 h-0.5 bg-z-border`})]},e))}),(0,M.jsxs)(`div`,{className:`flex-1 overflow-auto p-6 max-w-3xl mx-auto w-full`,children:[G===`BASIC`&&(0,M.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,M.jsxs)(`div`,{className:`col-span-2 sm:col-span-1`,children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Name (Key in JSON)*`}),(0,M.jsx)(`input`,{type:`text`,value:q?.name||``,onChange:e=>J(t=>({...t,name:e.target.value.replace(/\s+/g,`_`).replace(/[^a-zA-Z0-9_]/g,``)})),className:O(Q,`w-full rounded-none font-mono`),placeholder:`e.g. heroTitle`})]}),(0,M.jsxs)(`div`,{className:`col-span-2 sm:col-span-1`,children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Display Label`}),(0,M.jsx)(`input`,{type:`text`,value:q?.label||``,onChange:e=>J(t=>({...t,label:e.target.value})),className:O(Q,`w-full rounded-none`),placeholder:`e.g. Hero Title`})]}),(0,M.jsxs)(`div`,{className:`col-span-2`,children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Description`}),(0,M.jsx)(`input`,{type:`text`,value:q?.description||``,onChange:e=>J(t=>({...t,description:e.target.value})),className:O(Q,`w-full rounded-none`),placeholder:`Help text for content editors`})]}),(0,M.jsxs)(`div`,{className:`col-span-2`,children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Default Value`}),(0,M.jsx)(`input`,{type:`text`,value:q?.defaultValue||``,onChange:e=>J(t=>({...t,defaultValue:e.target.value})),className:O(Q,`w-full rounded-none`),placeholder:`e.g. Welcome`})]}),q?.type===`relation`&&(0,M.jsxs)(`div`,{className:`col-span-2 pt-4 border-t border-z-border space-y-4`,children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Relation Options`}),(0,M.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Relates To`}),(0,M.jsxs)(`select`,{value:q.relationTo||``,onChange:e=>J(t=>({...t,relationTo:e.target.value})),className:O(Q,`w-full rounded-none cursor-pointer`),children:[(0,M.jsx)(`option`,{value:``,children:`-- Select Collection --`}),L.map(e=>(0,M.jsx)(`option`,{value:e,children:e},e))]})]}),(0,M.jsx)(`div`,{className:`flex items-center`,children:(0,M.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer mt-4`,children:[(0,M.jsx)(`input`,{type:`checkbox`,checked:!!q?.hasMany,onChange:e=>J(t=>({...t,hasMany:e.target.checked})),className:`accent-gray-500 w-4 h-4`}),(0,M.jsx)(`span`,{className:`text-xs font-bold text-z-secondary`,children:`Has Many (Array of references)`})]})})]})]})]}),G===`VALIDATION`&&(0,M.jsxs)(`div`,{className:`space-y-6`,children:[(0,M.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4 bg-z-hover p-4 rounded-none border border-z-border`,children:[(0,M.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,M.jsx)(`input`,{type:`checkbox`,checked:!!q?.required,onChange:e=>J(t=>({...t,required:e.target.checked})),className:`accent-gray-500 w-4 h-4`}),(0,M.jsx)(`span`,{className:`text-xs font-bold text-z-secondary`,children:`Required field`})]}),(0,M.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,M.jsx)(`input`,{type:`checkbox`,checked:!!q?.unique,onChange:e=>J(t=>({...t,unique:e.target.checked})),className:`accent-gray-500 w-4 h-4`}),(0,M.jsx)(`span`,{className:`text-xs font-bold text-z-secondary`,children:`Unique field`})]})]}),(q?.type===`text`||q?.type===`textarea`)&&(0,M.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Min Length`}),(0,M.jsx)(`input`,{type:`number`,value:q?.minLength||``,onChange:e=>J(t=>({...t,minLength:parseInt(e.target.value)||void 0})),className:O(Q,`w-full rounded-none`),placeholder:`e.g. 5`})]}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Max Length`}),(0,M.jsx)(`input`,{type:`number`,value:q?.maxLength||``,onChange:e=>J(t=>({...t,maxLength:parseInt(e.target.value)||void 0})),className:O(Q,`w-full rounded-none`),placeholder:`e.g. 100`})]}),(0,M.jsxs)(`div`,{className:`col-span-2`,children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Regex Pattern`}),(0,M.jsx)(`input`,{type:`text`,value:q?.regex||``,onChange:e=>J(t=>({...t,regex:e.target.value})),className:O(Q,`w-full rounded-none font-mono`),placeholder:`^[A-Za-z]+$`})]})]}),q?.type===`number`&&(0,M.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Minimum Value`}),(0,M.jsx)(`input`,{type:`number`,value:q?.min||``,onChange:e=>J(t=>({...t,min:parseInt(e.target.value)||void 0})),className:O(Q,`w-full rounded-none`),placeholder:`e.g. 0`})]}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Maximum Value`}),(0,M.jsx)(`input`,{type:`number`,value:q?.max||``,onChange:e=>J(t=>({...t,max:parseInt(e.target.value)||void 0})),className:O(Q,`w-full rounded-none`),placeholder:`e.g. 100`})]})]}),q?.type===`date`&&(0,M.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Date Mode`}),(0,M.jsxs)(`select`,{value:q?.dateFormat||`date`,onChange:e=>J(t=>({...t,dateFormat:e.target.value})),className:O(Q,`w-full rounded-none cursor-pointer`),children:[(0,M.jsx)(`option`,{value:`date`,children:`Date Only`}),(0,M.jsx)(`option`,{value:`datetime`,children:`Date & Time`}),(0,M.jsx)(`option`,{value:`time`,children:`Time Only`})]})]})})]}),G===`ADMIN`&&(0,M.jsxs)(`div`,{className:`space-y-6`,children:[(0,M.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4 bg-z-hover p-4 rounded-none border border-z-border`,children:[(0,M.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,M.jsx)(`input`,{type:`checkbox`,checked:!!q?.i18n,onChange:e=>J(t=>({...t,i18n:e.target.checked})),className:`accent-z-accent w-4 h-4`}),(0,M.jsx)(`span`,{className:`text-xs font-bold text-z-secondary`,children:`Enable Localization (i18n)`})]}),(0,M.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,M.jsx)(`input`,{type:`checkbox`,checked:!!q?.admin?.hidden,onChange:e=>J(t=>({...t,admin:{...t.admin,hidden:e.target.checked}})),className:`accent-gray-500 w-4 h-4`}),(0,M.jsx)(`span`,{className:`text-xs font-bold text-z-secondary`,children:`Hidden in UI`})]}),(0,M.jsxs)(`label`,{className:`flex items-center gap-2 cursor-pointer`,children:[(0,M.jsx)(`input`,{type:`checkbox`,checked:!!q?.admin?.readOnly,onChange:e=>J(t=>({...t,admin:{...t.admin,readOnly:e.target.checked}})),className:`accent-gray-500 w-4 h-4`}),(0,M.jsx)(`span`,{className:`text-xs font-bold text-z-secondary`,children:`Read-Only`})]})]}),(0,M.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Field Width`}),(0,M.jsxs)(`select`,{value:q?.admin?.width||`100%`,onChange:e=>J(t=>({...t,admin:{...t.admin,width:e.target.value}})),className:O(Q,`w-full rounded-none cursor-pointer`),children:[(0,M.jsx)(`option`,{value:`100%`,children:`100% (Full Width)`}),(0,M.jsx)(`option`,{value:`50%`,children:`50% (Half Width)`}),(0,M.jsx)(`option`,{value:`33%`,children:`33% (One Third)`}),(0,M.jsx)(`option`,{value:`25%`,children:`25% (One Quarter)`})]})]}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Placeholder`}),(0,M.jsx)(`input`,{type:`text`,value:q?.admin?.placeholder||``,onChange:e=>J(t=>({...t,admin:{...t.admin,placeholder:e.target.value}})),className:O(Q,`w-full rounded-none`),placeholder:`e.g. Enter a value...`})]}),(0,M.jsxs)(`div`,{className:`col-span-2`,children:[(0,M.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block mb-1.5`,children:`Conditional Visibility JSON`}),(0,M.jsx)(`textarea`,{rows:3,value:q?.admin?.condition?JSON.stringify(q.admin.condition):``,onChange:e=>{try{let t=e.target.value?JSON.parse(e.target.value):void 0;J(e=>({...e,admin:{...e.admin,condition:t}}))}catch{}},className:O(Q,`w-full rounded-none font-mono`),placeholder:`{"field": "theme", "equals": "dark"}`})]})]})]})]})]}),(0,M.jsxs)(`div`,{className:`px-6 py-4 border-t border-z-border bg-app/50 flex justify-between`,children:[U===`SETTINGS`?(0,M.jsx)(`button`,{onClick:()=>W(`TYPE`),className:`px-4 py-2 text-sm font-bold text-z-muted hover:text-z-primary transition-colors`,children:`← Back to Types`}):(0,M.jsx)(`div`,{}),U===`SETTINGS`&&(0,M.jsx)(`button`,{onClick:oe,className:`px-6 py-2 bg-z-accent hover:brightness-110 text-z-logo-text text-sm font-semibold rounded-none transition-all shadow-sm`,children:Y===null?`Add Field`:`Update Field`})]})]})})})]})}export{P as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockBuilderPage-DcOo3Vnt.js","names":[],"sources":["../../src/pages/BlockBuilderPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react'\nimport {\n Plus, Database, Code, Check, Trash2, Box, Settings, X,\n Save, Loader2, FileText, Hash, Globe, Lock, Calendar,\n Image, Link2, ToggleLeft, AlignLeft, Braces, Tag, Layers, Eye,\n LayoutTemplate, ArrowDownToLine, Folders\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 { clearBlockCache } from '../hooks/useBlockLibrary'\nimport api from '../lib/api'\nimport { PageHeader } from '../components/ui/PageHeader'\n\n// ── Full field type catalogue ────────────────────────────────────────────────\nconst FIELD_TYPES = [\n // Basic\n { value: 'text', label: 'Text', icon: FileText, color: '#6b7280', desc: 'Small or long text like title or description' },\n { value: 'textarea', label: 'Textarea', icon: AlignLeft, color: '#6b7280', desc: 'Multi-line text for longer descriptions' },\n { value: 'number', label: 'Number', icon: Hash, color: '#3b82f6', desc: 'Numbers (integer, float, decimal)' },\n { value: 'email', label: 'Email', icon: Globe, color: 'var(--z-accent)', desc: 'Email field with validation format' },\n { value: 'password', label: 'Password', icon: Lock, color: '#ef4444', desc: 'Password field with encryption' },\n { value: 'checkbox', label: 'Boolean', icon: ToggleLeft, color: 'var(--z-accent)', desc: 'Yes/No, 1/0, True/False' },\n { value: 'date', label: 'Date', icon: Calendar, color: '#f59e0b', desc: 'A date picker with hours, minutes and seconds' },\n { value: 'media', label: 'Media', icon: Image, color: '#06b6d4', desc: 'Files like images, videos, etc' },\n { value: 'richtext', label: 'Rich Text', icon: FileText, color: '#84cc16', desc: 'A rich text editor with formatting options' },\n { value: 'relation', label: 'Relation', icon: Link2, color: '#ec4899', desc: 'Refers to another collection' },\n { value: 'json', label: 'JSON', icon: Braces, color: '#6366f1', desc: 'Data in JSON format' },\n { value: 'array', label: 'Array', icon: Layers, color: '#f59e0b', desc: 'A repeating group of fields' },\n // Structural (Payload-style)\n { value: 'row', label: 'Row', icon: LayoutTemplate, color: '#ec4899', desc: 'Group fields side-by-side' },\n { value: 'collapsible', label: 'Collapsible', icon: ArrowDownToLine, color: 'var(--z-accent)', desc: 'Wrap fields in an accordion' },\n { value: 'tabs', label: 'Tabs', icon: Folders, color: '#3b82f6', desc: 'Organize fields into tabs' },\n] as const\n\ntype FieldType = typeof FIELD_TYPES[number]['value']\n\ninterface FieldConfig {\n name?: string\n type: FieldType\n label?: string\n required?: boolean\n unique?: boolean\n description?: string\n defaultValue?: any\n relationTo?: string\n hasMany?: boolean\n options?: { label: string; value: string }[]\n fields?: FieldConfig[]\n \n // Validation\n min?: number\n max?: number\n minLength?: number\n maxLength?: number\n regex?: string\n dateFormat?: string\n \n i18n?: boolean\n \n // Admin & Layout\n admin?: {\n width?: string\n placeholder?: string\n hidden?: boolean\n readOnly?: boolean\n condition?: any\n }\n}\n\ninterface SavedBlock {\n slug: string\n labels?: { singular?: string; plural?: string }\n fields?: FieldConfig[]\n admin?: { category?: string; icon?: string; description?: string }\n isGenerated?: boolean\n}\n\n// ── Main Block Builder Page ─────────────────────────────────────────────────\nexport default function BlockBuilderPage() {\n const { theme } = useTheme()\n const dark = theme === 'dark'\n\n // Block being edited\n const [title, setTitle] = useState('New Block')\n const [slug, setSlug] = useState('new-block')\n const [category, setCategory] = useState('General')\n const [icon, setIcon] = useState('Box')\n const [description, setDescription] = useState('')\n const [fields, setFields] = useState<FieldConfig[]>([])\n\n // Saved blocks list\n const [savedBlocks, setSavedBlocks] = useState<SavedBlock[]>([])\n const [loadingBlocks, setLoadingBlocks] = useState(true)\n\n // Collections for relations\n const [availableCollections, setAvailableCollections] = useState<string[]>([])\n\n // UI state\n const [saving, setSaving] = useState(false)\n \n // Modal State\n const [isFieldModalOpen, setIsFieldModalOpen] = useState(false)\n const [modalStep, setModalStep] = useState<'TYPE' | 'SETTINGS'>('TYPE')\n const [settingsTab, setSettingsTab] = useState<'BASIC' | 'VALIDATION' | 'ADMIN'>('BASIC')\n \n const [activeField, setActiveField] = useState<Partial<FieldConfig> | null>(null)\n \n // To handle nested fields, we need a path array. [0, 'fields', 1] means fields[0].fields[1]\n // But for this simple implementation, let's keep it flat first, and then allow nesting arrays/rows if needed.\n // We'll support editing a flat list for now, and allow structural fields to just be defined.\n // Actually, for a fully deep UX, we would have a recursive editor. For this page, we'll keep the list top-level but allow recursive config inside the advanced JSON or just as a flat list if row.\n const [editingFieldIndex, setEditingFieldIndex] = useState<number | null>(null)\n\n const loadBlocks = useCallback(async () => {\n try {\n const res = await api.get('/blocks')\n const raw = res.data?.data\n setSavedBlocks(Array.isArray(raw) ? raw : [])\n } catch {\n setSavedBlocks([])\n } finally {\n setLoadingBlocks(false)\n }\n }, [])\n\n useEffect(() => {\n loadBlocks()\n // Mocking collections for relation dropdown. \n // Usually this hits /api/collections or introspect.\n setAvailableCollections(['users', 'pages', 'media', 'categories'])\n }, [loadBlocks])\n\n const loadBlock = (block: SavedBlock) => {\n setTitle(block.labels?.singular || block.slug)\n setSlug(block.slug)\n setCategory(block.admin?.category || 'General')\n setIcon(block.admin?.icon || 'Box')\n setDescription(block.admin?.description || '')\n setFields(block.fields || [])\n toast.success(`Loaded block: ${block.slug}`)\n }\n\n const resetEditor = () => {\n setTitle('New Block')\n setSlug('new-block')\n setCategory('General')\n setIcon('Box')\n setDescription('')\n setFields([])\n }\n\n const handleSave = async () => {\n if (!slug || !title) return toast.error('Name and slug required')\n setSaving(true)\n try {\n const payload = { slug, title, description, category, icon, fields }\n const res = await api.post('/blocks/generate', payload)\n clearBlockCache()\n toast.success(res.data.message || 'Block generated as JSON!')\n await loadBlocks()\n } catch (err: any) {\n toast.error(err.response?.data?.error?.message || 'Failed to generate block')\n } finally {\n setSaving(false)\n }\n }\n\n const handleFieldSubmit = () => {\n if (!activeField?.type) return toast.error('Field type required')\n if (activeField.type !== 'row' && activeField.type !== 'tabs' && !activeField.name) return toast.error('Field name is required')\n \n if (editingFieldIndex !== null) {\n const next = [...fields]\n next[editingFieldIndex] = activeField as FieldConfig\n setFields(next)\n } else {\n setFields(prev => [...prev, activeField as FieldConfig])\n }\n \n setIsFieldModalOpen(false)\n }\n\n const removeField = (index: number) => {\n setFields(prev => prev.filter((_, i) => i !== index))\n }\n\n const inputClass = cn(\n '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.5 px-3 rounded-none shadow-sm',\n dark ? 'bg-z-panel backdrop-blur-md border-z-border focus:border-z-accent text-z-primary placeholder:text-z-muted' : 'bg-z-panel border-z-border focus:border-z-accent text-z-primary placeholder:text-z-muted'\n )\n \n const blocksByCategory = savedBlocks.reduce((acc, block) => {\n const cat = block.admin?.category || 'General'\n if (!acc[cat]) acc[cat] = []\n acc[cat].push(block)\n return acc\n }, {} as Record<string, SavedBlock[]>)\n\n return (\n <div className={cn('flex h-[calc(100vh-4rem)] overflow-hidden', dark ? 'bg-app text-z-primary' : 'bg-[var(--z-bg-input)] text-z-primary')}>\n <div className={cn('w-64 flex-shrink-0 border-r flex flex-col', 'border-z-border bg-z-panel')}>\n <div className=\"p-4 border-b border-inherit flex items-center justify-between\">\n <h2 className=\"text-sm font-semibold flex items-center gap-2\">\n <Database size={14} className=\"text-z-secondary \" /> Blocks\n </h2>\n <button onClick={resetEditor} className=\"p-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary rounded-none transition-colors\" title=\"New Block\">\n <Plus size={14} />\n </button>\n </div>\n <div className=\"flex-1 overflow-auto p-4 space-y-4\">\n {loadingBlocks ? (\n <div className=\"flex justify-center\"><Loader2 className=\"animate-spin text-z-muted\" size={16} /></div>\n ) : Object.keys(blocksByCategory).length === 0 ? (\n <div className=\"text-center text-sm text-z-secondary\">No blocks yet</div>\n ) : (\n Object.entries(blocksByCategory).map(([cat, blocks]) => (\n <div key={cat} className=\"space-y-1.5\">\n <h3 className=\"text-sm font-semibold text-z-secondary\">{cat}</h3>\n <div className=\"space-y-0.5\">\n {blocks.map(block => (\n <button key={block.slug} onClick={() => loadBlock(block)} className={cn('w-full flex items-center gap-2 text-left px-3 py-2 text-sm font-semibold transition-colors rounded-none truncate', slug === block.slug ? 'bg-z-accent text-z-logo-text shadow-sm' : dark ? 'text-z-muted hover:bg-z-hover hover:text-z-primary' : 'text-z-secondary hover:bg-[var(--z-bg-input)]')}>\n {block.isGenerated ? <Code size={12} className={slug === block.slug ? 'text-z-primary' : 'text-z-secondary/50'} /> : <Box size={12} />}\n {block.labels?.singular || block.slug}\n </button>\n ))}\n </div>\n </div>\n ))\n )}\n </div>\n </div>\n\n <div className=\"flex-1 flex flex-col overflow-hidden relative\">\n <PageHeader\n title=\"Component Builder\"\n description={`${fields.length} fields · Generating to config/blocks/${slug}.json`}\n icon={<Layers size={24} />}\n backLink={{ to: '/', label: 'Dashboard' }}\n actions={\n <div className=\"flex items-center gap-2\">\n <button onClick={handleSave} disabled={saving} className=\"flex items-center gap-2 px-6 py-2.5 bg-z-accent hover:brightness-110 text-z-logo-text text-sm font-semibold rounded-none transition-all shadow-sm disabled:opacity-50\">\n {saving ? <Loader2 size={14} className=\"animate-spin\" /> : <Save size={14} />} Save Code\n </button>\n </div>\n }\n />\n\n <div className=\"flex-1 overflow-auto p-6 space-y-6\">\n <div className={cn('rounded-none border p-6 space-y-4 shadow-sm transition-all', 'z-panel')}>\n <h3 className=\"text-sm font-semibold text-z-secondary flex items-center gap-2\"><Settings size={12} /> Component Settings</h3>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Display Name</label>\n <input type=\"text\" value={title} onChange={e => { setTitle(e.target.value); setSlug(e.target.value.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '')) }} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Hero Banner\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">API Slug (filename)</label>\n <input type=\"text\" value={slug} onChange={e => setSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder=\"e.g. hero-banner\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Category</label>\n <input type=\"text\" value={category} onChange={e => setCategory(e.target.value)} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Layout, Content, Media\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Description</label>\n <input type=\"text\" value={description} onChange={e => setDescription(e.target.value)} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"Brief description for editors\" />\n </div>\n </div>\n </div>\n\n <div className={cn('rounded-none border shadow-sm transition-all', 'z-panel')}>\n <div className=\"px-6 py-4 border-b border-inherit flex items-center justify-between\">\n <h3 className=\"text-sm font-semibold text-z-secondary flex items-center gap-2\"><Layers size={12} /> Fields ({fields.length})</h3>\n <button onClick={() => { setModalStep('TYPE'); setActiveField({}); setEditingFieldIndex(null); setSettingsTab('BASIC'); setIsFieldModalOpen(true) }} className=\"flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary text-sm font-semibold rounded-none transition-all\">\n <Plus size={12} /> Add new field\n </button>\n </div>\n <div className=\"p-0\">\n {fields.length === 0 ? (\n <div className=\"py-16 text-center\">\n <Layers size={40} className=\"mx-auto text-z-primary mb-4\" strokeWidth={1} />\n <p className=\"text-sm font-semibold text-z-secondary\">No fields yet</p>\n </div>\n ) : (\n <div className=\"divide-y divide-z-border dark:divide-z-border\">\n {fields.map((field, i) => (\n <div key={i} className=\"flex items-center justify-between px-6 py-4 hover:bg-z-hover transition-colors group cursor-pointer\"\n onClick={() => { setActiveField(field); setEditingFieldIndex(i); setModalStep('SETTINGS'); setSettingsTab('BASIC'); setIsFieldModalOpen(true) }}>\n <div className=\"flex items-center gap-4\">\n <div className=\"w-8 h-8 rounded-none bg-z-panel flex items-center justify-center\">\n {(() => { const ft = FIELD_TYPES.find(t => t.value === field.type); const Icon = ft ? ft.icon : Box; return <Icon size={14} className=\"text-z-secondary \" /> })()}\n </div>\n <div>\n <div className=\"text-sm font-bold text-z-primary dark:text-z-primary flex items-center gap-2\">\n {field.name || `[${field.type}]`}\n {field.required && <span className=\"text-sm text-red-500\">*</span>}\n {field.i18n && <Globe size={10} className=\"text-z-active-text\" />}\n </div>\n <div className=\"text-sm font-bold text-z-secondary mt-0.5\">{field.type} {field.label ? `· ${field.label}` : ''}</div>\n </div>\n </div>\n <button onClick={(e) => { e.stopPropagation(); removeField(i) }} className=\"opacity-0 group-hover:opacity-100 p-2 text-red-500 hover:bg-red-500/10 rounded-none transition-all\"><Trash2 size={14} /></button>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n\n <AnimatePresence>\n {isFieldModalOpen && (\n <motion.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\">\n <motion.div initial={{ scale: 0.95, y: 10 }} animate={{ scale: 1, y: 0 }} exit={{ scale: 0.95, y: 10 }} className=\"w-full max-w-4xl border rounded-none shadow-sm flex flex-col max-h-[85vh] bg-app border-z-border overflow-hidden\">\n <div className=\"px-6 py-4 border-b border-z-border flex items-center justify-between bg-app/50\">\n <h2 className=\"text-sm font-semibold text-z-primary flex items-center gap-2\">\n {modalStep === 'TYPE' ? 'Select a field for your Component' : `Configure ${activeField?.type} field`}\n </h2>\n <button onClick={() => setIsFieldModalOpen(false)} className=\"text-z-secondary hover:text-z-primary p-1\"><X size={18} /></button>\n </div>\n\n {modalStep === 'TYPE' && (\n <div className=\"flex-1 overflow-auto p-6 grid grid-cols-2 lg:grid-cols-3 gap-4\">\n {FIELD_TYPES.map((ft) => {\n const Icon = ft.icon\n return (\n <button key={ft.value} onClick={() => { setActiveField({ type: ft.value, admin: {} }); setModalStep('SETTINGS') }} className=\"flex items-start gap-4 p-4 rounded-none border border-z-border bg-z-hover hover:border-z-accent/50 hover:opacity-90/5 transition-all text-left\">\n <div className=\"mt-1 p-2 rounded-none bg-app/50 border border-z-border\"><Icon size={18} style={{ color: ft.color }} /></div>\n <div>\n <div className=\"text-sm font-semibold text-z-primary mb-1\">{ft.label}</div>\n <div className=\"text-sm text-z-muted leading-relaxed font-bold\">{ft.desc}</div>\n </div>\n </button>\n )\n })}\n </div>\n )}\n\n {modalStep === 'SETTINGS' && (\n <div className=\"flex flex-col flex-1 overflow-hidden\">\n <div className=\"flex border-b border-z-border px-6 pt-4 gap-6 bg-app/20\">\n {['BASIC', 'VALIDATION', 'ADMIN'].map(tab => (\n <button key={tab} onClick={() => setSettingsTab(tab as any)} className={cn(\"pb-3 text-sm font-semibold transition-colors relative\", settingsTab === tab ? \"text-z-secondary \" : \"text-z-secondary hover:text-z-primary\")}>\n {tab}\n {settingsTab === tab && <motion.div layoutId=\"tab-indicator\" className=\"absolute bottom-0 left-0 right-0 h-0.5 bg-z-border\" />}\n </button>\n ))}\n </div>\n <div className=\"flex-1 overflow-auto p-6 max-w-3xl mx-auto w-full\">\n {settingsTab === 'BASIC' && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div className=\"col-span-2 sm:col-span-1\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Name (Key in JSON)*</label>\n <input type=\"text\" value={activeField?.name || ''} onChange={e => setActiveField(prev => ({ ...prev, name: e.target.value.replace(/\\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, '') }))} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder=\"e.g. heroTitle\" />\n </div>\n <div className=\"col-span-2 sm:col-span-1\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Display Label</label>\n <input type=\"text\" value={activeField?.label || ''} onChange={e => setActiveField(prev => ({ ...prev, label: e.target.value }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Hero Title\" />\n </div>\n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Description</label>\n <input type=\"text\" value={activeField?.description || ''} onChange={e => setActiveField(prev => ({ ...prev, description: e.target.value }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"Help text for content editors\" />\n </div>\n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Default Value</label>\n <input type=\"text\" value={activeField?.defaultValue || ''} onChange={e => setActiveField(prev => ({ ...prev, defaultValue: e.target.value }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Welcome\" />\n </div>\n \n {activeField?.type === 'relation' && (\n <div className=\"col-span-2 pt-4 border-t border-z-border space-y-4\">\n <label className=\"text-sm font-semibold text-z-secondary block\">Relation Options</label>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Relates To</label>\n <select value={activeField.relationTo || ''} onChange={e => setActiveField(prev => ({ ...prev, relationTo: e.target.value }))} className={cn(inputClass, 'w-full rounded-none cursor-pointer')}>\n <option value=\"\">-- Select Collection --</option>\n {availableCollections.map(c => <option key={c} value={c}>{c}</option>)}\n </select>\n </div>\n <div className=\"flex items-center\">\n <label className=\"flex items-center gap-2 cursor-pointer mt-4\">\n <input type=\"checkbox\" checked={!!activeField?.hasMany} onChange={e => setActiveField(prev => ({ ...prev, hasMany: e.target.checked }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Has Many (Array of references)</span>\n </label>\n </div>\n </div>\n </div>\n )}\n </div>\n )}\n\n {settingsTab === 'VALIDATION' && (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 bg-z-hover p-4 rounded-none border border-z-border\">\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.required} onChange={e => setActiveField(prev => ({ ...prev, required: e.target.checked }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Required field</span>\n </label>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.unique} onChange={e => setActiveField(prev => ({ ...prev, unique: e.target.checked }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Unique field</span>\n </label>\n </div>\n \n {(activeField?.type === 'text' || activeField?.type === 'textarea') && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Min Length</label>\n <input type=\"number\" value={activeField?.minLength || ''} onChange={e => setActiveField(prev => ({ ...prev, minLength: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 5\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Max Length</label>\n <input type=\"number\" value={activeField?.maxLength || ''} onChange={e => setActiveField(prev => ({ ...prev, maxLength: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 100\" />\n </div>\n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Regex Pattern</label>\n <input type=\"text\" value={activeField?.regex || ''} onChange={e => setActiveField(prev => ({ ...prev, regex: e.target.value }))} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder=\"^[A-Za-z]+$\" />\n </div>\n </div>\n )}\n \n {activeField?.type === 'number' && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Minimum Value</label>\n <input type=\"number\" value={activeField?.min || ''} onChange={e => setActiveField(prev => ({ ...prev, min: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 0\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Maximum Value</label>\n <input type=\"number\" value={activeField?.max || ''} onChange={e => setActiveField(prev => ({ ...prev, max: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 100\" />\n </div>\n </div>\n )}\n \n {activeField?.type === 'date' && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Date Mode</label>\n <select value={activeField?.dateFormat || 'date'} onChange={e => setActiveField(prev => ({ ...prev, dateFormat: e.target.value }))} className={cn(inputClass, 'w-full rounded-none cursor-pointer')}>\n <option value=\"date\">Date Only</option>\n <option value=\"datetime\">Date & Time</option>\n <option value=\"time\">Time Only</option>\n </select>\n </div>\n </div>\n )}\n </div>\n )}\n\n {settingsTab === 'ADMIN' && (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 bg-z-hover p-4 rounded-none border border-z-border\">\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.i18n} onChange={e => setActiveField(prev => ({ ...prev, i18n: e.target.checked }))} className=\"accent-z-accent w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Enable Localization (i18n)</span>\n </label>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.admin?.hidden} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, hidden: e.target.checked } }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Hidden in UI</span>\n </label>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.admin?.readOnly} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, readOnly: e.target.checked } }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Read-Only</span>\n </label>\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Field Width</label>\n <select value={activeField?.admin?.width || '100%'} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, width: e.target.value } }))} className={cn(inputClass, 'w-full rounded-none cursor-pointer')}>\n <option value=\"100%\">100% (Full Width)</option>\n <option value=\"50%\">50% (Half Width)</option>\n <option value=\"33%\">33% (One Third)</option>\n <option value=\"25%\">25% (One Quarter)</option>\n </select>\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Placeholder</label>\n <input type=\"text\" value={activeField?.admin?.placeholder || ''} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, placeholder: e.target.value } }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Enter a value...\" />\n </div>\n \n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Conditional Visibility JSON</label>\n <textarea rows={3} value={activeField?.admin?.condition ? JSON.stringify(activeField.admin.condition) : ''} onChange={e => {\n try {\n const parsed = e.target.value ? JSON.parse(e.target.value) : undefined;\n setActiveField(prev => ({ ...prev, admin: { ...prev.admin, condition: parsed } }))\n } catch { /* invalid JSON */ }\n }} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder='{\"field\": \"theme\", \"equals\": \"dark\"}' />\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n\n <div className=\"px-6 py-4 border-t border-z-border bg-app/50 flex justify-between\">\n {modalStep === 'SETTINGS' ? (\n <button onClick={() => setModalStep('TYPE')} className=\"px-4 py-2 text-sm font-bold text-z-muted hover:text-z-primary transition-colors\">\n ← Back to Types\n </button>\n ) : <div />}\n {modalStep === 'SETTINGS' && (\n <button onClick={handleFieldSubmit} className=\"px-6 py-2 bg-z-accent hover:brightness-110 text-z-logo-text text-sm font-semibold rounded-none transition-all shadow-sm\">\n {editingFieldIndex !== null ? 'Update Field' : 'Add Field'}\n </button>\n )}\n </div>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{C as t,G as n,Ln as r,Q as i,Wt as a,l as o,rr as s,vr as c,xr as l}from"./vendor-react-DQVTOTFO.js";import{a as u,o as d,t as f}from"./utils-fgvbH6CB.js";var p=e(l(),1),m=c(),h=[`text`,`number`,`boolean`,`richtext`,`date`,`email`],g=()=>{let{theme:e}=u(),[c,l]=(0,p.useState)([]),[g,_]=(0,p.useState)(!0),[v,y]=(0,p.useState)(!1),[b,x]=(0,p.useState)(null);(0,p.useEffect)(()=>{S()},[]);let S=async()=>{try{l((await d.get(`/schemas`)).data.data)}catch{o.error(`Failed to load schemas`)}finally{_(!1)}},C=()=>{x({slug:``,singular:``,plural:``,fields:[{name:`title`,type:`text`,required:!0}]})},w=()=>{b&&x({...b,fields:[...b.fields,{name:``,type:`text`}]})},T=(e,t,n)=>{if(!b)return;let r=[...b.fields];r[e]={...r[e],[t]:n},x({...b,fields:r})},E=e=>{if(!b)return;let t=[...b.fields];t.splice(e,1),x({...b,fields:t})};return(0,m.jsxs)(`div`,{className:`flex h-[calc(100vh-64px)] overflow-hidden`,children:[(0,m.jsxs)(`div`,{className:f(`w-64 border-r shrink-0 flex flex-col`,e===`dark`?`border-z-border bg-app`:`border-z-border bg-[var(--z-bg-input)]`),children:[(0,m.jsxs)(`div`,{className:`p-4 border-b border-inherit flex items-center justify-between`,children:[(0,m.jsxs)(`h2`,{className:`text-sm font-semibold flex items-center gap-2`,children:[(0,m.jsx)(a,{size:14}),` Models`]}),(0,m.jsx)(`button`,{onClick:C,className:`p-1.5 hover:bg-z-panel text-z-secondary rounded-none transition-colors`,children:(0,m.jsx)(i,{size:14})})]}),(0,m.jsxs)(`div`,{className:`flex-1 overflow-auto p-2 space-y-1`,children:[g?(0,m.jsx)(`div`,{className:`p-4 flex justify-center`,children:(0,m.jsx)(r,{className:`animate-spin text-z-muted`,size:16})}):c.map(t=>(0,m.jsx)(`button`,{onClick:()=>x(t),className:f(`w-full text-left px-3 py-2 text-sm font-bold transition-colors`,b?.id===t.id?`bg-z-border text-z-primary`:e===`dark`?`text-z-muted hover:bg-z-hover hover:text-z-primary`:`text-z-secondary hover:bg-app/5 hover:text-z-primary`),children:t.singular},t.id)),!g&&c.length===0&&(0,m.jsx)(`div`,{className:`p-4 text-center text-sm text-z-secondary`,children:`No schemas found`})]})]}),(0,m.jsx)(`div`,{className:`flex-1 overflow-auto bg-inherit p-8 relative`,children:b?(0,m.jsxs)(s.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},className:`max-w-3xl mx-auto space-y-8`,children:[(0,m.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`h1`,{className:`text-2xl font-semibold`,children:`Content-Type Builder`}),(0,m.jsx)(`p`,{className:`text-sm text-z-secondary font-bold mt-1`,children:`Design your database schema visually`})]}),(0,m.jsxs)(`button`,{onClick:async()=>{if(!b||!b.slug){o.error(`Schema slug is required`);return}y(!0);try{b.id?(await d.put(`/schemas/${b.id}`,b),o.success(`Schema updated successfully`)):(await d.post(`/schemas`,b),o.success(`Schema created successfully`)),S(),x(null)}catch(e){o.error(e.response?.data?.message||`Failed to save schema`)}finally{y(!1)}},disabled:v,className:`flex items-center gap-2 px-6 py-3 bg-z-accent hover:bg-z-base text-z-primary text-sm font-semibold shadow-lg transition-all`,children:[v?(0,m.jsx)(r,{size:14,className:`animate-spin`}):(0,m.jsx)(n,{size:14}),`Save Schema`]})]}),(0,m.jsxs)(`div`,{className:f(`p-6 border space-y-4`,`bg-z-panel border-z-border shadow-sm`),children:[(0,m.jsx)(`h3`,{className:`text-sm font-semibold text-z-secondary mb-4 border-b border-z-border/20 pb-2`,children:`General Info`}),(0,m.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[(0,m.jsxs)(`div`,{className:`space-y-1`,children:[(0,m.jsx)(`label`,{className:`text-sm font-bold text-z-secondary`,children:`Singular Name`}),(0,m.jsx)(`input`,{type:`text`,value:b.singular,onChange:e=>x({...b,singular:e.target.value}),className:f(`w-full border p-3 text-sm font-bold outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors`,e===`dark`?`bg-app border-z-border focus:border-z-border`:`bg-z-input border-z-border focus:border-z-border`),placeholder:`e.g. Article`})]}),(0,m.jsxs)(`div`,{className:`space-y-1`,children:[(0,m.jsx)(`label`,{className:`text-sm font-bold text-z-secondary`,children:`Plural Name`}),(0,m.jsx)(`input`,{type:`text`,value:b.plural,onChange:e=>x({...b,plural:e.target.value}),className:f(`w-full border p-3 text-sm font-bold outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors`,e===`dark`?`bg-app border-z-border focus:border-z-border`:`bg-z-input border-z-border focus:border-z-border`),placeholder:`e.g. Articles`})]}),(0,m.jsxs)(`div`,{className:`space-y-1 col-span-2`,children:[(0,m.jsx)(`label`,{className:`text-sm font-bold text-z-secondary`,children:`Database Slug (API Route)`}),(0,m.jsx)(`input`,{type:`text`,value:b.slug,onChange:e=>x({...b,slug:e.target.value.toLowerCase().replace(/[^a-z0-9_-]/g,``)}),disabled:!!b.id,className:f(`w-full border p-3 text-sm font-bold outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors`,e===`dark`?`bg-app border-z-border focus:border-z-border disabled:opacity-50`:`bg-z-input border-z-border focus:border-z-border disabled:opacity-50`),placeholder:`e.g. articles`})]})]})]}),(0,m.jsxs)(`div`,{className:f(`p-6 border space-y-4`,`bg-z-panel border-z-border shadow-sm`),children:[(0,m.jsxs)(`div`,{className:`flex items-center justify-between mb-4 border-b border-z-border/20 pb-2`,children:[(0,m.jsx)(`h3`,{className:`text-sm font-semibold text-z-secondary `,children:`Fields Configuration`}),(0,m.jsxs)(`button`,{onClick:w,className:`flex items-center gap-1 text-sm font-semibold text-z-secondary hover:text-z-secondary`,children:[(0,m.jsx)(i,{size:12}),` Add Field`]})]}),(0,m.jsx)(`div`,{className:`space-y-3`,children:b.fields.map((n,r)=>(0,m.jsxs)(`div`,{className:f(`flex items-center gap-3 p-3 border group`,e===`dark`?`bg-app border-z-border`:`bg-z-input border-z-border`),children:[(0,m.jsx)(`input`,{type:`text`,value:n.name,onChange:e=>T(r,`name`,e.target.value.toLowerCase().replace(/[^a-z0-9_]/g,``)),placeholder:`field_name`,className:`flex-1 bg-transparent border-b border-transparent focus:border-z-border 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 py-1`}),(0,m.jsx)(`select`,{value:n.type,onChange:e=>T(r,`type`,e.target.value),className:`w-32 bg-transparent border-b border-transparent focus:border-z-border text-sm font-semibold outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black py-1`,children:h.map(e=>(0,m.jsx)(`option`,{value:e,className:`text-z-primary`,children:e},e))}),(0,m.jsxs)(`label`,{className:`flex items-center gap-2 text-sm font-bold text-z-muted`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:n.required||!1,onChange:e=>T(r,`required`,e.target.checked),className:`accent-gray-500`}),`Req`]}),(0,m.jsx)(`button`,{onClick:()=>E(r),className:`text-red-500/50 hover:text-red-500 transition-colors p-1`,children:(0,m.jsx)(t,{size:14})})]},r))})]})]}):(0,m.jsx)(`div`,{className:`h-full flex items-center justify-center`,children:(0,m.jsxs)(`div`,{className:`text-center space-y-4 max-w-sm`,children:[(0,m.jsx)(a,{size:48,className:`mx-auto text-z-primary/5 dark:text-z-primary/10`,strokeWidth:1}),(0,m.jsx)(`p`,{className:`text-sm font-semibold text-z-muted`,children:`Schema Architect`}),(0,m.jsx)(`p`,{className:`text-sm font-bold text-z-secondary leading-relaxed`,children:`Select an existing collection model from the sidebar to edit, or deploy a new visual schema.`})]})})})]})};export{g as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuilderPage-Iu8F_bN1.js","names":[],"sources":["../../src/pages/BuilderPage.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react'\nimport { motion } from 'framer-motion'\nimport { Plus, Database, Save, Loader2, Trash2 } from 'lucide-react'\nimport { useTheme } from '../context/ThemeContext'\nimport { cn } from '../lib/utils'\nimport api from '../lib/api'\nimport toast from 'react-hot-toast'\n\ninterface SchemaField {\n name: string\n type: string\n required?: boolean\n}\n\ninterface SchemaConfig {\n id?: string\n slug: string\n singular: string\n plural: string\n fields: SchemaField[]\n}\n\nconst FIELD_TYPES = ['text', 'number', 'boolean', 'richtext', 'date', 'email']\n\nconst BuilderPage: React.FC = () => {\n const { theme } = useTheme()\n const [schemas, setSchemas] = useState<SchemaConfig[]>([])\n const [loading, setLoading] = useState(true)\n const [saving, setSaving] = useState(false)\n const [activeSchema, setActiveSchema] = useState<SchemaConfig | null>(null)\n\n useEffect(() => {\n loadSchemas()\n }, [])\n\n const loadSchemas = async () => {\n try {\n const res = await api.get('/schemas')\n setSchemas(res.data.data)\n } catch {\n toast.error('Failed to load schemas')\n } finally {\n setLoading(false)\n }\n }\n\n const handleCreateNew = () => {\n setActiveSchema({\n slug: '',\n singular: '',\n plural: '',\n fields: [{ name: 'title', type: 'text', required: true }]\n })\n }\n\n const addField = () => {\n if (!activeSchema) return\n setActiveSchema({\n ...activeSchema,\n fields: [...activeSchema.fields, { name: '', type: 'text' }]\n })\n }\n\n const updateField = (index: number, key: keyof SchemaField, value: any) => {\n if (!activeSchema) return\n const newFields = [...activeSchema.fields]\n newFields[index] = { ...newFields[index], [key]: value }\n setActiveSchema({ ...activeSchema, fields: newFields })\n }\n\n const removeField = (index: number) => {\n if (!activeSchema) return\n const newFields = [...activeSchema.fields]\n newFields.splice(index, 1)\n setActiveSchema({ ...activeSchema, fields: newFields })\n }\n\n const handleSave = async () => {\n if (!activeSchema || !activeSchema.slug) {\n toast.error('Schema slug is required')\n return\n }\n setSaving(true)\n try {\n if (activeSchema.id) {\n await api.put(`/schemas/${activeSchema.id}`, activeSchema)\n toast.success('Schema updated successfully')\n } else {\n await api.post('/schemas', activeSchema)\n toast.success('Schema created successfully')\n }\n loadSchemas()\n setActiveSchema(null)\n } catch (err: any) {\n toast.error(err.response?.data?.message || 'Failed to save schema')\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <div className=\"flex h-[calc(100vh-64px)] overflow-hidden\">\n {/* Sidebar List */}\n <div className={cn(\n 'w-64 border-r shrink-0 flex flex-col',\n theme === 'dark' ? 'border-z-border bg-app' : 'border-z-border bg-[var(--z-bg-input)]'\n )}>\n <div className=\"p-4 border-b border-inherit flex items-center justify-between\">\n <h2 className=\"text-sm font-semibold flex items-center gap-2\">\n <Database size={14} /> Models\n </h2>\n <button\n onClick={handleCreateNew}\n className=\"p-1.5 hover:bg-z-panel text-z-secondary rounded-none transition-colors\"\n >\n <Plus size={14} />\n </button>\n </div>\n <div className=\"flex-1 overflow-auto p-2 space-y-1\">\n {loading ? (\n <div className=\"p-4 flex justify-center\"><Loader2 className=\"animate-spin text-z-muted\" size={16} /></div>\n ) : schemas.map(s => (\n <button\n key={s.id}\n onClick={() => setActiveSchema(s)}\n className={cn(\n 'w-full text-left px-3 py-2 text-sm font-bold transition-colors',\n activeSchema?.id === s.id\n ? 'bg-z-border text-z-primary'\n : theme === 'dark'\n ? 'text-z-muted hover:bg-z-hover hover:text-z-primary'\n : 'text-z-secondary hover:bg-app/5 hover:text-z-primary'\n )}\n >\n {s.singular}\n </button>\n ))}\n {!loading && schemas.length === 0 && (\n <div className=\"p-4 text-center text-sm text-z-secondary\">\n No schemas found\n </div>\n )}\n </div>\n </div>\n\n {/* Editor Main */}\n <div className=\"flex-1 overflow-auto bg-inherit p-8 relative\">\n {activeSchema ? (\n <motion.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n className=\"max-w-3xl mx-auto space-y-8\"\n >\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Content-Type Builder</h1>\n <p className=\"text-sm text-z-secondary font-bold mt-1\">Design your database schema visually</p>\n </div>\n <button\n onClick={handleSave}\n disabled={saving}\n className=\"flex items-center gap-2 px-6 py-3 bg-z-accent hover:bg-z-base text-z-primary text-sm font-semibold shadow-lg transition-all\"\n >\n {saving ? <Loader2 size={14} className=\"animate-spin\" /> : <Save size={14} />}\n Save Schema\n </button>\n </div>\n\n <div className={cn(\n 'p-6 border space-y-4',\n 'bg-z-panel border-z-border shadow-sm'\n )}>\n <h3 className=\"text-sm font-semibold text-z-secondary mb-4 border-b border-z-border/20 pb-2\">General Info</h3>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div className=\"space-y-1\">\n <label className=\"text-sm font-bold text-z-secondary\">Singular Name</label>\n <input\n type=\"text\"\n value={activeSchema.singular}\n onChange={(e) => setActiveSchema({ ...activeSchema, singular: e.target.value })}\n className={cn(\n 'w-full border p-3 text-sm font-bold outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors',\n theme === 'dark' ? 'bg-app border-z-border focus:border-z-border' : 'bg-z-input border-z-border focus:border-z-border'\n )}\n placeholder=\"e.g. Article\"\n />\n </div>\n <div className=\"space-y-1\">\n <label className=\"text-sm font-bold text-z-secondary\">Plural Name</label>\n <input\n type=\"text\"\n value={activeSchema.plural}\n onChange={(e) => setActiveSchema({ ...activeSchema, plural: e.target.value })}\n className={cn(\n 'w-full border p-3 text-sm font-bold outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors',\n theme === 'dark' ? 'bg-app border-z-border focus:border-z-border' : 'bg-z-input border-z-border focus:border-z-border'\n )}\n placeholder=\"e.g. Articles\"\n />\n </div>\n <div className=\"space-y-1 col-span-2\">\n <label className=\"text-sm font-bold text-z-secondary\">Database Slug (API Route)</label>\n <input\n type=\"text\"\n value={activeSchema.slug}\n onChange={(e) => setActiveSchema({ ...activeSchema, slug: e.target.value.toLowerCase().replace(/[^a-z0-9_-]/g, '') })}\n disabled={!!activeSchema.id}\n className={cn(\n 'w-full border p-3 text-sm font-bold outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors',\n theme === 'dark' ? 'bg-app border-z-border focus:border-z-border disabled:opacity-50' : 'bg-z-input border-z-border focus:border-z-border disabled:opacity-50'\n )}\n placeholder=\"e.g. articles\"\n />\n </div>\n </div>\n </div>\n\n <div className={cn(\n 'p-6 border space-y-4',\n 'bg-z-panel border-z-border shadow-sm'\n )}>\n <div className=\"flex items-center justify-between mb-4 border-b border-z-border/20 pb-2\">\n <h3 className=\"text-sm font-semibold text-z-secondary \">Fields Configuration</h3>\n <button\n onClick={addField}\n className=\"flex items-center gap-1 text-sm font-semibold text-z-secondary hover:text-z-secondary\"\n >\n <Plus size={12} /> Add Field\n </button>\n </div>\n \n <div className=\"space-y-3\">\n {activeSchema.fields.map((field, idx) => (\n <div key={idx} className={cn(\n 'flex items-center gap-3 p-3 border group',\n theme === 'dark' ? 'bg-app border-z-border' : 'bg-z-input border-z-border'\n )}>\n <input\n type=\"text\"\n value={field.name}\n onChange={e => updateField(idx, 'name', e.target.value.toLowerCase().replace(/[^a-z0-9_]/g, ''))}\n placeholder=\"field_name\"\n className=\"flex-1 bg-transparent border-b border-transparent focus:border-z-border 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 py-1\"\n />\n <select\n value={field.type}\n onChange={e => updateField(idx, 'type', e.target.value)}\n className=\"w-32 bg-transparent border-b border-transparent focus:border-z-border text-sm font-semibold outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black py-1\"\n >\n {FIELD_TYPES.map(t => <option key={t} value={t} className=\"text-z-primary\">{t}</option>)}\n </select>\n <label className=\"flex items-center gap-2 text-sm font-bold text-z-muted\">\n <input\n type=\"checkbox\"\n checked={field.required || false}\n onChange={e => updateField(idx, 'required', e.target.checked)}\n className=\"accent-gray-500\"\n />\n Req\n </label>\n <button\n onClick={() => removeField(idx)}\n className=\"text-red-500/50 hover:text-red-500 transition-colors p-1\"\n >\n <Trash2 size={14} />\n </button>\n </div>\n ))}\n </div>\n </div>\n </motion.div>\n ) : (\n <div className=\"h-full flex items-center justify-center\">\n <div className=\"text-center space-y-4 max-w-sm\">\n <Database size={48} className=\"mx-auto text-z-primary/5 dark:text-z-primary/10\" strokeWidth={1} />\n <p className=\"text-sm font-semibold text-z-muted\">Schema Architect</p>\n <p className=\"text-sm font-bold text-z-secondary leading-relaxed\">\n Select an existing collection model from the sidebar to edit, or deploy a new visual schema.\n </p>\n </div>\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport default BuilderPage\n"],"mappings":"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"}