@zenith-open/zenithcms-admin 1.0.0-beta.1 → 1.0.0-beta.11
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.
- package/dist/assets/{ApiExplorerPage-UJpoKRI0.js → ApiExplorerPage-85UWt1EW.js} +1 -1
- package/dist/assets/{ApiExplorerPage-UJpoKRI0.js.map → ApiExplorerPage-85UWt1EW.js.map} +1 -1
- package/dist/assets/{AuditLogPage-8xYlRl1I.js → AuditLogPage-CwULx1tr.js} +1 -1
- package/dist/assets/{AuditLogPage-8xYlRl1I.js.map → AuditLogPage-CwULx1tr.js.map} +1 -1
- package/dist/assets/{BlockBuilderPage-DcOo3Vnt.js → BlockBuilderPage-XD1IjOgx.js} +1 -1
- package/dist/assets/{BlockBuilderPage-DcOo3Vnt.js.map → BlockBuilderPage-XD1IjOgx.js.map} +1 -1
- package/dist/assets/{CollectionHooksPage-Dn_ujtlp.js → CollectionHooksPage-DIaSrKDj.js} +1 -1
- package/dist/assets/{CollectionHooksPage-Dn_ujtlp.js.map → CollectionHooksPage-DIaSrKDj.js.map} +1 -1
- package/dist/assets/{CollectionsPage-BSPHf7H2.js → CollectionsPage-CL_t5JRI.js} +1 -1
- package/dist/assets/{CollectionsPage-BSPHf7H2.js.map → CollectionsPage-CL_t5JRI.js.map} +1 -1
- package/dist/assets/{ComponentBuilderPage-CT6S12LA.js → ComponentBuilderPage-C58Rr1cu.js} +1 -1
- package/dist/assets/{ComponentBuilderPage-CT6S12LA.js.map → ComponentBuilderPage-C58Rr1cu.js.map} +1 -1
- package/dist/assets/{DashboardBuilder-Cbi9Ddiu.js → DashboardBuilder-Chjyqyb7.js} +1 -1
- package/dist/assets/{DashboardBuilder-Cbi9Ddiu.js.map → DashboardBuilder-Chjyqyb7.js.map} +1 -1
- package/dist/assets/{PluginsPage-5YRpbP-N.js → PluginsPage-DAR4Fsz-.js} +1 -1
- package/dist/assets/{PluginsPage-5YRpbP-N.js.map → PluginsPage-DAR4Fsz-.js.map} +1 -1
- package/dist/assets/{RedirectsPage-D_4jAdaI.js → RedirectsPage-DfMTJsac.js} +1 -1
- package/dist/assets/{RedirectsPage-D_4jAdaI.js.map → RedirectsPage-DfMTJsac.js.map} +1 -1
- package/dist/assets/{SchemaBuilderPage-EFA5XIAa.js → SchemaBuilderPage-BYprOkEv.js} +1 -1
- package/dist/assets/{SchemaBuilderPage-EFA5XIAa.js.map → SchemaBuilderPage-BYprOkEv.js.map} +1 -1
- package/dist/assets/{SettingsPage-BRpcMw48.js → SettingsPage-B2r_uNVc.js} +1 -1
- package/dist/assets/{SettingsPage-BRpcMw48.js.map → SettingsPage-B2r_uNVc.js.map} +1 -1
- package/dist/assets/SetupWizard-CBA43yJr.js +62 -0
- package/dist/assets/SetupWizard-CBA43yJr.js.map +1 -0
- package/dist/assets/SpatialEditor-BohlovfE.js +3 -0
- package/dist/assets/SpatialEditor-BohlovfE.js.map +1 -0
- package/dist/assets/{TemplatesPage-B-nNYv3o.js → TemplatesPage-BplB2ksb.js} +1 -1
- package/dist/assets/{TemplatesPage-B-nNYv3o.js.map → TemplatesPage-BplB2ksb.js.map} +1 -1
- package/dist/assets/{TrashPage-Ccusal1w.js → TrashPage-BIhKrs5x.js} +1 -1
- package/dist/assets/{TrashPage-Ccusal1w.js.map → TrashPage-BIhKrs5x.js.map} +1 -1
- package/dist/assets/index-Umj4hIVD.css +1 -0
- package/dist/assets/{index-ChcKY5Xe.js → index-yE_3fruG.js} +3 -3
- package/dist/assets/index-yE_3fruG.js.map +1 -0
- package/dist/index.html +48 -6
- package/dist/manifest.webmanifest +1 -0
- package/dist/sw.js +1 -1
- package/dist/sw.js.map +1 -1
- package/dist/{workbox-9c191d2f.js → workbox-2fbc6a65.js} +3 -3
- package/dist/workbox-2fbc6a65.js.map +1 -0
- package/package.json +4 -4
- package/dist/assets/SetupWizard-D57HIkrs.js +0 -62
- package/dist/assets/SetupWizard-D57HIkrs.js.map +0 -1
- package/dist/assets/SpatialEditor-CPgS7Zrd.js +0 -3
- package/dist/assets/SpatialEditor-CPgS7Zrd.js.map +0 -1
- package/dist/assets/index-ChcKY5Xe.js.map +0 -1
- package/dist/assets/index-CxhwdV2K.css +0 -1
- package/dist/workbox-9c191d2f.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchemaBuilderPage-EFA5XIAa.js","names":[],"sources":["../../src/pages/SchemaBuilderPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react'\nimport {\n Plus, Database, Code, Copy, Check, Trash2, Box, Layers, Settings, X,\n Save, Loader2, ChevronDown, ChevronRight, Sparkles, RefreshCw, List,\n AlertCircle, Eye, EyeOff, Hash, Globe, Lock, Calendar, FileText,\n Image, Link2, ToggleLeft, AlignLeft, Braces, Tag\n} from 'lucide-react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { useTheme } from '../context/ThemeContext'\nimport toast from 'react-hot-toast'\nimport api from '../lib/api'\nimport { PageHeader } from '../components/ui/PageHeader'\nimport { cn } from '../lib/utils'\nimport { useUnsavedGuard } from '../hooks/useUnsavedGuard'\n\n// ── Full field type catalogue ────────────────────────────────────────────────\nconst FIELD_TYPES = [\n { value: 'text', label: 'Text', icon: FileText, color: '#6b7280' },\n { value: 'textarea', label: 'Textarea', icon: AlignLeft, color: '#6b7280' },\n { value: 'number', label: 'Number', icon: Hash, color: '#3b82f6' },\n { value: 'email', label: 'Email', icon: Globe, color: 'var(--z-accent)' },\n { value: 'password', label: 'Password', icon: Lock, color: '#ef4444' },\n { value: 'checkbox', label: 'Checkbox / Boolean', icon: ToggleLeft, color: 'var(--z-accent)' },\n { value: 'date', label: 'Date', icon: Calendar, color: '#f59e0b' },\n { value: 'select', label: 'Select / Enum', icon: List, color: '#f97316' },\n { value: 'media', label: 'Media / Image', icon: Image, color: '#06b6d4' },\n { value: 'richtext', label: 'Rich Text', icon: FileText, color: '#84cc16' },\n { value: 'relation', label: 'Relation', icon: Link2, color: '#ec4899' },\n { value: 'json', label: 'JSON Object', icon: Braces, color: '#6366f1' },\n { value: 'slug', label: 'Slug', icon: Tag, color: 'var(--z-accent)' },\n { value: 'array', label: 'Array / Repeater', icon: Layers, color: '#f59e0b' },\n { value: 'blocks', label: 'Dynamic Blocks', icon: Box, color: 'var(--z-accent)' },\n { value: 'group', label: 'Field Group', icon: Settings, color: '#3b82f6' },\n { value: 'code', label: 'Code Editor', icon: Code, color: '#6b7280' },\n { value: 'color', label: 'Color Picker', icon: Eye, color: '#f97316' },\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 index?: boolean\n hidden?: boolean\n readOnly?: boolean\n placeholder?: string\n description?: string\n defaultValue?: any\n min?: number\n max?: number\n regex?: string\n width?: string\n // select options\n options?: { label: string; value: string }[]\n // relation\n relationTo?: string\n hasMany?: boolean\n // array sub-fields\n fields?: FieldConfig[]\n}\n\ninterface CollectionSettings {\n drafts: boolean\n timestamps: boolean\n versions: boolean\n publicRead: boolean\n singleton: boolean\n auth: boolean\n softDelete: boolean\n}\n\ninterface SavedSchema {\n _id?: string\n id?: string\n slug: string\n singular?: string\n plural?: string\n fields?: FieldConfig[]\n settings?: CollectionSettings\n createdAt?: string\n isCodeFirst?: boolean\n}\n\nconst DEFAULT_SETTINGS: CollectionSettings = {\n drafts: true,\n timestamps: true,\n versions: false,\n publicRead: false,\n singleton: false,\n auth: false,\n softDelete: false,\n}\n\n// ── Helper ────────────────────────────────────────────────────────────────────\nfunction makeSlug(name: string): string {\n return name.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '')\n}\n\n// ── Field Type Picker ─────────────────────────────────────────────────────────\nfunction FieldTypePicker({ value, onChange, theme }: { value: FieldType; onChange: (t: FieldType) => void; theme: string }) {\n const [open, setOpen] = useState(false)\n const current = FIELD_TYPES.find(t => t.value === value)\n const Icon = current?.icon || FileText\n return (\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className={cn(\n 'flex items-center gap-2 px-3 py-2 border text-sm font-semibold transition-all w-full shadow-sm rounded-none',\n 'z-card-interactive'\n )}\n >\n <Icon size={12} style={{ color: current?.color }} />\n <span className=\"flex-1 text-left\">{current?.label || 'Select type'}</span>\n <ChevronDown size={10} className=\"text-z-secondary\" />\n </button>\n <AnimatePresence>\n {open && (\n <motion.div\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 4 }}\n className={cn(\n 'absolute z-50 top-full left-0 mt-1 w-64 border shadow-sm max-h-72 overflow-y-auto rounded-none',\n theme === 'dark' ? 'bg-z-popover backdrop-blur-xl border-z-border' : 'bg-z-panel border-z-border'\n )}\n >\n {FIELD_TYPES.map(ft => {\n const FtIcon = ft.icon\n return (\n <button\n key={ft.value}\n type=\"button\"\n onClick={() => { onChange(ft.value); setOpen(false) }}\n className={cn(\n 'w-full flex items-center gap-3 px-4 py-2.5 text-sm font-semibold transition-all rounded-none',\n value === ft.value\n ? 'bg-z-accent text-z-logo-text'\n : theme === 'dark' ? 'text-z-muted hover:bg-z-hover hover:text-z-primary' : 'text-z-secondary hover:bg-[var(--z-bg-input)]'\n )}\n >\n <FtIcon size={12} style={{ color: value === ft.value ? 'white' : ft.color }} />\n {ft.label}\n </button>\n )\n })}\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n\n\n\n// ── Nested Fields Editor ──────────────────────────────────────────────────────\nfunction NestedFieldsEditor({\n fields, onUpdate, theme, availableCollections\n}: {\n fields: FieldConfig[]\n onUpdate: (fields: FieldConfig[]) => void\n theme: string\n availableCollections: string[]\n}) {\n const addField = () => {\n onUpdate([...fields, { name: `nestedField${fields.length + 1}`, type: 'text', label: `Nested Field ${fields.length + 1}` }])\n }\n \n const removeField = (index: number) => {\n onUpdate(fields.filter((_, i) => i !== index))\n }\n\n const updateField = (index: number, key: string, value: any) => {\n const next = [...fields]\n next[index] = { ...next[index], [key]: value }\n onUpdate(next)\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 px-3 rounded-none shadow-sm',\n 'z-input'\n )\n\n return (\n <div className=\"mt-4 border-l-2 border-z-accent/50 pl-4 space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h4 className=\"text-sm font-bold text-z-primary\">Nested Fields ({fields.length})</h4>\n <button\n onClick={addField}\n type=\"button\"\n className=\"flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border border-z-border text-z-secondary text-sm font-semibold rounded-none transition-all\"\n >\n <Plus size={12} /> Add Field\n </button>\n </div>\n \n {fields.length === 0 ? (\n <div className=\"p-4 border border-dashed border-z-border text-center text-z-secondary text-sm\">\n No nested fields added yet.\n </div>\n ) : (\n <div className=\"space-y-4\">\n {fields.map((field, i) => (\n <div key={i} className=\"p-4 relative group border border-z-border bg-z-panel\">\n <button\n type=\"button\"\n onClick={() => removeField(i)}\n className=\"absolute top-2 right-2 opacity-0 group-hover:opacity-100 p-1 text-red-500/50 hover:text-red-500 transition-all rounded-none hover:bg-red-500/10 z-10\"\n >\n <Trash2 size={12} />\n </button>\n \n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 pr-6\">\n <div>\n <label className=\"text-xs font-semibold text-z-secondary block mb-1\">Field Name (key)</label>\n <input\n type=\"text\"\n value={field.name}\n onChange={e => updateField(i, 'name', e.target.value.replace(/\\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, ''))}\n className={cn(inputClass, 'w-full rounded-none font-mono text-xs')}\n placeholder=\"fieldName\"\n />\n </div>\n <div>\n <label className=\"text-xs font-semibold text-z-secondary block mb-1\">Field Type</label>\n <FieldTypePicker\n value={field.type}\n onChange={v => updateField(i, 'type', v)}\n theme={theme}\n />\n </div>\n <div>\n <label className=\"text-xs font-semibold text-z-secondary block mb-1\">Display Label</label>\n <input\n type=\"text\"\n value={field.label || ''}\n onChange={e => updateField(i, 'label', e.target.value)}\n className={cn(inputClass, 'w-full rounded-none text-xs')}\n placeholder=\"Human readable label\"\n />\n </div>\n </div>\n \n <FieldAdvancedPanel\n field={field}\n onUpdate={(key, value) => updateField(i, key, value)}\n theme={theme}\n availableCollections={availableCollections}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// ── Advanced Field Panel ──────────────────────────────────────────────────────\nfunction FieldAdvancedPanel({\n field, onUpdate, theme, availableCollections\n}: {\n field: FieldConfig\n onUpdate: (key: string, value: any) => void\n theme: string\n availableCollections: string[]\n}) {\n const [open, setOpen] = useState(false)\n const inputClass = cn(\n 'w-full border p-2 text-sm font-mono outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors rounded-none shadow-sm',\n 'z-input'\n )\n const checkClass = 'accent-gray-500 w-3.5 h-3.5'\n const labelClass = 'text-sm font-semibold text-z-secondary'\n\n return (\n <div className=\"mt-2\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className=\"flex items-center gap-1.5 text-sm font-semibold text-z-secondary hover:text-z-secondary transition-colors\"\n >\n {open ? <ChevronDown size={10} /> : <ChevronRight size={10} />}\n Advanced Options\n </button>\n <AnimatePresence>\n {open && (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: 'auto', opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n className=\"overflow-hidden\"\n >\n <div className={cn('mt-3 p-4 border space-y-4 rounded-none shadow-sm', 'z-panel shadow-sm')}>\n {/* Flags */}\n <div className=\"flex flex-wrap gap-x-6 gap-y-2\">\n {[\n ['required', 'Required'],\n ['unique', 'Unique'],\n ['index', 'Index'],\n ['hidden', 'Hidden'],\n ['readOnly', 'Read Only'],\n ].map(([key, lbl]) => (\n <label key={key} className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={!!(field as any)[key]}\n onChange={e => onUpdate(key, e.target.checked)}\n className={checkClass}\n />\n <span className={labelClass}>{lbl}</span>\n </label>\n ))}\n </div>\n\n {/* Text inputs */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Placeholder</label>\n <input type=\"text\" value={field.placeholder || ''} onChange={e => onUpdate('placeholder', e.target.value)} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Default Value</label>\n <input type=\"text\" value={field.defaultValue ?? ''} onChange={e => onUpdate('defaultValue', e.target.value)} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Description</label>\n <input type=\"text\" value={field.description || ''} onChange={e => onUpdate('description', e.target.value)} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Width (e.g. 50%)</label>\n <input type=\"text\" value={field.width || ''} onChange={e => onUpdate('width', e.target.value)} className={inputClass} />\n </div>\n {(field.type === 'text' || field.type === 'textarea') && (\n <>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Min Length</label>\n <input type=\"number\" value={field.min ?? ''} onChange={e => onUpdate('min', Number(e.target.value))} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Max Length</label>\n <input type=\"number\" value={field.max ?? ''} onChange={e => onUpdate('max', Number(e.target.value))} className={inputClass} />\n </div>\n <div className=\"col-span-2\">\n <label className={cn(labelClass, 'block mb-1')}>Regex Pattern</label>\n <input type=\"text\" value={field.regex || ''} onChange={e => onUpdate('regex', e.target.value)} className={inputClass} placeholder=\"^[a-z]+$\" />\n </div>\n </>\n )}\n {field.type === 'number' && (\n <>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Min</label>\n <input type=\"number\" value={field.min ?? ''} onChange={e => onUpdate('min', Number(e.target.value))} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Max</label>\n <input type=\"number\" value={field.max ?? ''} onChange={e => onUpdate('max', Number(e.target.value))} className={inputClass} />\n </div>\n </>\n )}\n </div>\n\n {/* Relation options */}\n {field.type === 'relation' && (\n <div className=\"space-y-3\">\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Relates To Collection</label>\n <select\n value={field.relationTo || ''}\n onChange={e => onUpdate('relationTo', e.target.value)}\n className={cn(inputClass, 'cursor-pointer')}\n >\n <option value=\"\">-- Select Collection --</option>\n {availableCollections.map(col => (\n <option key={col} value={col}>{col}</option>\n ))}\n </select>\n </div>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={!!field.hasMany}\n onChange={e => onUpdate('hasMany', e.target.checked)}\n className={checkClass}\n />\n <span className={labelClass}>Has Many (array of references)</span>\n </label>\n </div>\n )}\n\n {/* Nested fields for array/group */}\n {(field.type === 'array' || field.type === 'group') && (\n <NestedFieldsEditor\n fields={field.fields || []}\n onUpdate={newFields => onUpdate('fields', newFields)}\n theme={theme}\n availableCollections={availableCollections}\n />\n )}\n\n {/* Select options editor */}\n {field.type === 'select' && (\n <div>\n <label className={cn(labelClass, 'block mb-2')}>Options</label>\n <div className=\"space-y-2\">\n {(field.options || []).map((opt, oi) => (\n <div key={oi} className=\"flex gap-2\">\n <input\n type=\"text\"\n value={opt.label}\n onChange={e => {\n const newOpts = [...(field.options || [])]\n newOpts[oi] = { ...newOpts[oi], label: e.target.value }\n onUpdate('options', newOpts)\n }}\n placeholder=\"Label\"\n className={cn(inputClass, 'flex-1')}\n />\n <input\n type=\"text\"\n value={opt.value}\n onChange={e => {\n const newOpts = [...(field.options || [])]\n newOpts[oi] = { ...newOpts[oi], value: e.target.value }\n onUpdate('options', newOpts)\n }}\n placeholder=\"value\"\n className={cn(inputClass, 'flex-1 font-mono')}\n />\n <button\n type=\"button\"\n onClick={() => onUpdate('options', (field.options || []).filter((_, i) => i !== oi))}\n className=\"p-2 text-red-500/60 hover:text-red-500 transition-colors\"\n >\n <X size={12} />\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={() => onUpdate('options', [...(field.options || []), { label: '', value: '' }])}\n className=\"flex items-center gap-1 text-sm font-semibold text-z-secondary hover:text-z-secondary\"\n >\n <Plus size={10} /> Add Option\n </button>\n </div>\n </div>\n )}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n\n// ── Main Schema Builder Page ──────────────────────────────────────────────────\nexport default function SchemaBuilderPage() {\n const { theme } = useTheme()\n const dark = theme === 'dark'\n\n // Schema being edited\n const [collectionName, setCollectionName] = useState('New Collection')\n const [slug, setSlug] = useState('new-collection')\n const [fields, setFields] = useState<FieldConfig[]>([])\n const [settings, setSettings] = useState<CollectionSettings>(DEFAULT_SETTINGS)\n\n // Saved schemas list\n const [savedSchemas, setSavedSchemas] = useState<SavedSchema[]>([])\n const [loadingSchemas, setLoadingSchemas] = useState(true)\n const [activeSchemaId, setActiveSchemaId] = useState<string | null>(null)\n\n const activeSchemaObj = savedSchemas.find(s => (s._id || s.id) === activeSchemaId)\n const isCodeFirst = activeSchemaObj?.isCodeFirst\n\n // UI state\n const [saving, setSaving] = useState(false)\n const [showCode, setShowCode] = useState(false)\n const [copied, setCopied] = useState(false)\n const [showIntrospect, setShowIntrospect] = useState(false)\n const [dbUri, setDbUri] = useState('')\n const [isIntrospecting, setIsIntrospecting] = useState(false)\n const [aiPrompt, setAiPrompt] = useState('')\n const [isAIGenerating, setIsAIGenerating] = useState(false)\n const [showAI, setShowAI] = useState(false)\n const [availableCollections, setAvailableCollections] = useState<string[]>([])\n\n // Track unsaved changes\n const [isDirty, setIsDirty] = useState(false)\n useEffect(() => {\n const currentStr = JSON.stringify({ slug, collectionName, fields, settings })\n if (activeSchemaObj) {\n const activeStr = JSON.stringify({\n slug: activeSchemaObj.slug,\n collectionName: activeSchemaObj.plural || activeSchemaObj.slug,\n fields: activeSchemaObj.fields || [],\n settings: { ...DEFAULT_SETTINGS, ...(activeSchemaObj.settings || {}) }\n })\n setIsDirty(currentStr !== activeStr)\n } else {\n const defaultStr = JSON.stringify({\n slug: 'new-collection',\n collectionName: 'New Collection',\n fields: [],\n settings: DEFAULT_SETTINGS\n })\n setIsDirty(currentStr !== defaultStr)\n }\n }, [slug, collectionName, fields, settings, activeSchemaObj])\n\n useUnsavedGuard({ hasUnsavedChanges: isDirty })\n\n // Load saved schemas and collections list\n const loadSchemas = useCallback(async () => {\n try {\n // Fetch both Dynamic UI Schemas and Code-First JSON Schemas\n const [dbRes, systemRes] = await Promise.all([\n api.get('/schemas').catch(() => ({ data: { data: [] } })),\n api.get('/system/schemas').catch(() => ({ data: { data: { collections: [] } } }))\n ])\n\n const rawDb = dbRes.data?.data\n const dbList: SavedSchema[] = Array.isArray(rawDb) ? rawDb : Array.isArray(rawDb?.schemas) ? rawDb.schemas : []\n \n const rawSystem = systemRes.data?.data?.collections || []\n const systemList: SavedSchema[] = Array.isArray(rawSystem) \n ? rawSystem.map(c => ({\n ...c,\n id: c.slug, // Code-First schemas use slug as ID\n isCodeFirst: true\n }))\n : []\n\n // Combine and deduplicate (System Code-First schemas override DB schemas)\n const schemaMap = new Map<string, SavedSchema>()\n for (const s of [...dbList, ...systemList]) {\n schemaMap.set(s.slug, s)\n }\n const combined = Array.from(schemaMap.values()).sort((a, b) => a.slug.localeCompare(b.slug))\n setSavedSchemas(combined)\n } catch {\n setSavedSchemas([])\n } finally {\n setLoadingSchemas(false)\n }\n }, [])\n\n useEffect(() => {\n loadSchemas()\n // Load live collection slugs for relation field picker\n api.get('/schemas').then(res => {\n const d = res.data?.data\n const cols: any[] = Array.isArray(d?.collections) ? d.collections\n : Array.isArray(d) ? d : []\n setAvailableCollections(cols.map((c: any) => c.slug).filter(Boolean))\n }).catch(() => {})\n }, [loadSchemas])\n\n // Load a saved schema into the editor\n const loadSchema = (schema: SavedSchema) => {\n setActiveSchemaId(schema._id || schema.id || null)\n setCollectionName(schema.plural || schema.slug)\n setSlug(schema.slug)\n setFields(schema.fields || [])\n setSettings({ ...DEFAULT_SETTINGS, ...(schema.settings || {}) })\n toast.success(`Loaded schema: ${schema.slug}`)\n }\n\n const resetEditor = () => {\n setActiveSchemaId(null)\n setCollectionName('New Collection')\n setSlug('new-collection')\n setFields([])\n setSettings(DEFAULT_SETTINGS)\n }\n\n const addField = () => {\n setFields(prev => [...prev, { name: `field${prev.length + 1}`, type: 'text', label: `Field ${prev.length + 1}` }])\n }\n\n const removeField = (index: number) => {\n setFields(prev => prev.filter((_, i) => i !== index))\n }\n\n const updateField = (index: number, key: string, value: any) => {\n setFields(prev => {\n const next = [...prev]\n next[index] = { ...next[index], [key]: value }\n return next\n })\n }\n\n // Save schema to backend\n const handleSave = async () => {\n if (!slug || !collectionName) return toast.error('Name and slug required')\n setSaving(true)\n try {\n const payload = {\n slug,\n singular: collectionName,\n plural: collectionName,\n fields,\n settings,\n }\n if (activeSchemaId) {\n await api.put(`/schemas/${activeSchemaId}`, payload)\n toast.success('Schema updated!')\n } else {\n const res = await api.post('/schemas', payload)\n const id = res.data?.data?._id || res.data?.data?.id\n if (id) setActiveSchemaId(id)\n toast.success('Schema created!')\n }\n await loadSchemas()\n // Hot-reload backend routes\n await api.post('/system/schema/reload').catch(() => {})\n } catch (err: any) {\n toast.error(err.response?.data?.error?.message || 'Failed to save schema')\n } finally {\n setSaving(false)\n }\n }\n\n // Delete schema\n const handleDeleteSchema = async (id: string, slug: string) => {\n try {\n await api.delete(`/schemas/${id}`)\n toast.success(`Schema \"${slug}\" deleted`)\n if (activeSchemaId === id) resetEditor()\n await loadSchemas()\n } catch { toast.error('Failed to delete schema') }\n }\n\n // Introspect DB\n const handleIntrospect = async () => {\n if (!dbUri) return toast.error('Please provide a connection string')\n setIsIntrospecting(true)\n try {\n const res = await api.post('/system/introspect', { connectionString: dbUri })\n const collections = res.data.data\n if (collections?.length > 0) {\n const col = collections[0]\n setCollectionName(col.name)\n setSlug(makeSlug(col.name))\n setFields(col.fields || [])\n toast.success(`Introspected: ${col.name}`)\n setShowIntrospect(false)\n } else {\n toast.error('No tables found')\n }\n } catch (err: any) {\n toast.error(err.response?.data?.error || 'Introspection failed')\n } finally {\n setIsIntrospecting(false)\n }\n }\n\n // AI Generate\n const handleAIGenerate = async () => {\n if (!aiPrompt) return toast.error('Enter a prompt first')\n setIsAIGenerating(true)\n try {\n const res = await api.post('/system/ai-architect', { prompt: aiPrompt })\n const schema = res.data?.data\n if (schema) {\n setCollectionName(schema.name || schema.slug || 'AI Collection')\n setSlug(schema.slug || makeSlug(schema.name || 'ai-collection'))\n setFields(schema.fields || [])\n toast.success('AI schema generated!')\n setShowAI(false)\n }\n } catch (err: any) {\n toast.error(err.response?.data?.error?.message || 'AI generation failed')\n } finally {\n setIsAIGenerating(false)\n }\n }\n\n // Generate TypeScript code\n const generateCode = () => {\n const fieldsCode = fields.map(f => {\n let props = ` name: '${f.name}',\\n type: '${f.type}',`\n if (f.label) props += `\\n label: '${f.label}',`\n if (f.required) props += `\\n required: true,`\n if (f.unique) props += `\\n unique: true,`\n if (f.relationTo) props += `\\n relationTo: '${f.relationTo}',`\n if (f.options?.length) props += `\\n options: ${JSON.stringify(f.options)},`\n return ` {\\n${props}\\n },`\n }).join('\\n')\n\n const settingsCode = Object.entries(settings)\n .filter(([, v]) => v === true)\n .map(([k]) => ` ${k}: true,`)\n .join('\\n')\n\n return `import { CollectionConfig } from '@zenith-open/zenithcms-types'\n\nexport const ${collectionName.replace(/\\s+/g, '')}: CollectionConfig = {\n name: '${collectionName}',\n slug: '${slug}',\n${settingsCode ? settingsCode + '\\n' : ''} fields: [\n${fieldsCode}\n ],\n}`\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 'z-input'\n )\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\n {/* ── Schemas Sidebar ─────────────────────────────────────────────── */}\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-bold text-z-primary\">\n Schemas\n </h2>\n <button\n onClick={resetEditor}\n className=\"p-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary rounded-none transition-colors\"\n title=\"New Schema\"\n >\n <Plus size={14} />\n </button>\n </div>\n <div className=\"flex-1 overflow-auto p-2 space-y-1\">\n {loadingSchemas ? (\n <div className=\"p-4 flex justify-center\"><Loader2 className=\"animate-spin text-z-muted\" size={16} /></div>\n ) : savedSchemas.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-z-secondary\">\n No schemas yet\n </div>\n ) : savedSchemas.map(schema => {\n const id = schema._id || schema.id || ''\n const isActive = activeSchemaId === id\n return (\n <div key={id} className=\"group flex items-center gap-1\">\n <button\n onClick={() => loadSchema(schema)}\n className={cn(\n 'flex-1 flex items-center justify-between text-left px-3 py-2.5 text-sm font-semibold transition-colors rounded-none truncate',\n isActive ? '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 )}\n >\n <span>{schema.slug}</span>\n {schema.isCodeFirst && <Lock size={10} className={isActive ? 'text-z-primary' : 'text-z-secondary'} />}\n </button>\n {!schema.isCodeFirst && (\n <button\n onClick={() => handleDeleteSchema(id, schema.slug)}\n className=\"opacity-0 group-hover:opacity-100 p-1.5 text-red-500/50 hover:text-red-500 transition-all\"\n >\n <Trash2 size={12} />\n </button>\n )}\n </div>\n )\n })}\n </div>\n </div>\n\n {/* ── Main Editor ─────────────────────────────────────────────────── */}\n <div className=\"flex-1 flex flex-col overflow-hidden\">\n {/* Header toolbar */}\n <PageHeader\n title=\"Schema Builder\"\n backLink={{ to: '/', label: 'Dashboard' }}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setShowAI(true)}\n className=\"px-4 py-2 bg-z-active-bg text-z-accent hover:opacity-80 text-sm font-bold rounded-none transition-all\"\n >\n AI Generate\n </button>\n <button\n onClick={() => setShowIntrospect(true)}\n className=\"px-4 py-2 text-sm font-bold border border-z-border hover:bg-z-hover rounded-none transition-all\"\n >\n Introspect DB\n </button>\n <button\n onClick={() => setShowCode(true)}\n className=\"px-4 py-2 text-sm font-bold border border-z-border hover:bg-z-hover rounded-none transition-all\"\n >\n View Code\n </button>\n <button\n onClick={handleSave}\n disabled={saving || isCodeFirst}\n className=\"px-4 py-2 bg-z-accent hover:bg-z-accent/90 text-z-primary text-sm font-bold rounded-none transition-all disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {saving ? 'Saving...' : isCodeFirst ? 'Locked' : 'Save'}\n </button>\n </div>\n }\n />\n\n <div className=\"flex-1 overflow-auto p-6 space-y-6 custom-editor-scrollbar\">\n {isCodeFirst && (\n <div className=\"px-4 py-3 border border-amber-500/30 bg-amber-500/10 text-amber-500 text-sm font-bold flex items-center justify-between\">\n <span>Code-First Schema (Read Only)</span>\n <Lock size={14} />\n </div>\n )}\n\n {/* Collection Meta */}\n <div className={cn('rounded-none border p-6 space-y-4 shadow-sm transition-all', 'z-panel')}>\n <h3 className=\"text-sm font-bold text-z-primary\">\n Collection Settings\n </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\n type=\"text\"\n value={collectionName}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n setCollectionName(e.target.value)\n setSlug(makeSlug(e.target.value))\n }}\n className={cn(inputClass, 'w-full rounded-none', isCodeFirst && 'opacity-70 cursor-not-allowed')}\n placeholder=\"e.g. Blog Posts\"\n />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Slug (API ID)</label>\n <input\n type=\"text\"\n value={slug}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n setSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))\n }}\n className={cn(inputClass, 'w-full rounded-none font-mono', isCodeFirst && 'opacity-70 cursor-not-allowed')}\n placeholder=\"e.g. blog-posts\"\n />\n </div>\n </div>\n\n {/* Settings toggles */}\n <div className=\"flex flex-wrap gap-x-6 gap-y-3 pt-2 border-t border-z-border\">\n {(Object.keys(DEFAULT_SETTINGS) as (keyof CollectionSettings)[]).map(key => (\n <label key={key} className=\"flex items-center gap-2 cursor-pointer group\">\n <div\n onClick={() => {\n if (isCodeFirst) return\n setSettings(prev => ({ ...prev, [key]: !prev[key] }))\n }}\n className={cn(\n 'w-8 h-4 rounded-full relative transition-all cursor-pointer border border-transparent shadow-inner',\n settings[key] ? (dark ? 'bg-z-accent' : 'bg-z-accent') : (dark ? 'bg-gray-700' : 'bg-gray-300'),\n isCodeFirst && 'opacity-50 cursor-not-allowed'\n )}\n >\n <div className={cn(\n 'absolute top-[1.5px] w-3 h-3 rounded-full bg-white shadow-sm transition-all',\n settings[key] ? 'left-[17px]' : 'left-[1.5px]'\n )} />\n </div>\n <span className=\"text-sm font-bold capitalize text-z-muted group-hover:text-z-primary transition-colors\">\n {key.replace(/([A-Z])/g, ' $1').trim()}\n </span>\n </label>\n ))}\n </div>\n </div>\n\n {/* Fields */}\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-bold text-z-primary\">\n Fields ({fields.length})\n </h3>\n {!isCodeFirst && (\n <button\n onClick={addField}\n 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 >\n <Plus size={12} /> Add Field\n </button>\n )}\n </div>\n\n <div className=\"p-4 space-y-3\">\n <AnimatePresence>\n {fields.map((field, i) => (\n <motion.div\n key={i}\n layout\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.97 }}\n className={cn('p-4 relative group z-panel', isCodeFirst && 'opacity-70')}\n >\n {/* Delete button */}\n {!isCodeFirst && (\n <button\n onClick={() => removeField(i)}\n className=\"absolute top-3 right-3 opacity-0 group-hover:opacity-100 p-1.5 text-red-500/50 hover:text-red-500 transition-all rounded-none hover:bg-red-500/10\"\n >\n <Trash2 size={14} />\n </button>\n )}\n\n {/* Main row */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 pr-8\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Field Name (key)</label>\n <input\n type=\"text\"\n value={field.name}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n updateField(i, 'name', e.target.value.replace(/\\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, ''))\n }}\n className={cn(inputClass, 'w-full rounded-none-none font-mono text-sm', isCodeFirst && 'cursor-not-allowed')}\n placeholder=\"fieldName\"\n />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Field Type</label>\n <div className={cn(isCodeFirst && 'opacity-70 pointer-events-none')}>\n <FieldTypePicker\n value={field.type}\n onChange={v => updateField(i, 'type', v)}\n theme={theme}\n />\n </div>\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Display Label</label>\n <input\n type=\"text\"\n value={field.label || ''}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n updateField(i, 'label', e.target.value)\n }}\n className={cn(inputClass, 'w-full rounded-none-none', isCodeFirst && 'cursor-not-allowed')}\n placeholder=\"Human readable label\"\n />\n </div>\n </div>\n\n {/* Quick flags row */}\n <div className=\"flex items-center gap-5 mt-3 pt-2 border-t border-z-border\">\n {[['required', 'Required'], ['unique', 'Unique'], ['index', 'Index']].map(([k, l]) => (\n <label key={k} className=\"flex items-center gap-1.5 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={!!(field as any)[k]}\n disabled={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n updateField(i, k, e.target.checked)\n }}\n className=\"accent-gray-500 w-3 h-3 disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n <span className=\"text-sm font-semibold text-z-secondary\">{l}</span>\n </label>\n ))}\n </div>\n\n {/* Advanced panel */}\n {!isCodeFirst && (\n <FieldAdvancedPanel\n field={field}\n onUpdate={(key, value) => updateField(i, key, value)}\n theme={theme}\n availableCollections={availableCollections}\n />\n )}\n </motion.div>\n ))}\n </AnimatePresence>\n\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 <p className=\"text-sm text-z-secondary mt-1\">Click \"Add Field\" or use AI Generate to get started</p>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n\n {/* ── Code Modal ─────────────────────────────────────────────────── */}\n <AnimatePresence>\n {showCode && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95 }} animate={{ scale: 1 }} exit={{ scale: 0.95 }} className=\"w-full max-w-3xl border rounded-none-none shadow-2xl p-6 relative flex flex-col h-[80vh] bg-app border-z-border\">\n <button onClick={() => setShowCode(false)} className=\"absolute top-4 right-4 text-z-secondary hover:text-z-primary\"><X size={20} /></button>\n <h2 className=\"text-xl font-semibold mb-4 flex items-center gap-3\">\n <Code className=\"text-z-secondary \" /> Generated TypeScript\n </h2>\n <div className=\"flex-1 bg-[#1E1E1E] border border-z-border p-5 overflow-auto text-sm font-mono text-z-secondary relative rounded-none-none\">\n <button\n onClick={() => { navigator.clipboard.writeText(generateCode()); setCopied(true); setTimeout(() => setCopied(false), 2000) }}\n className=\"absolute top-3 right-3 p-2 bg-z-panel/10 hover:bg-z-panel/20 text-z-primary transition-colors rounded-none-none\"\n >\n {copied ? <Check size={14} /> : <Copy size={14} />}\n </button>\n <pre><code>{generateCode()}</code></pre>\n </div>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* ── AI Generate Modal ───────────────────────────────────────────── */}\n <AnimatePresence>\n {showAI && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95 }} animate={{ scale: 1 }} exit={{ scale: 0.95 }} className=\"w-full max-w-lg border rounded-none-none shadow-2xl p-6 relative bg-app border-z-border\">\n <button onClick={() => setShowAI(false)} className=\"absolute top-4 right-4 text-z-secondary hover:text-z-primary\"><X size={20} /></button>\n <h2 className=\"text-xl font-semibold mb-2 flex items-center gap-3\">\n <Sparkles className=\"text-purple-400\" /> AI Schema Architect\n </h2>\n <p className=\"text-sm text-z-muted mb-5 font-medium\">\n Describe what you need — the AI will generate a complete schema with fields, types, and relations.\n </p>\n <textarea\n rows={4}\n value={aiPrompt}\n onChange={e => setAiPrompt(e.target.value)}\n placeholder='e.g. \"A blog post collection with title, slug, content, featured image, author relation to users, published date, and category select field with options.\"'\n className=\"w-full bg-app border border-z-border focus:border-z-active-border/50 p-4 text-sm outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black rounded-none-none placeholder:text-z-secondary text-z-primary resize-none mb-4\"\n />\n <button\n disabled={isAIGenerating || !aiPrompt}\n onClick={handleAIGenerate}\n className=\"w-full py-3.5 bg-z-accent hover:opacity-80 text-z-logo-text text-sm font-semibold flex justify-center items-center gap-2 transition-all rounded-none-none disabled:opacity-50\"\n >\n {isAIGenerating ? <><Loader2 size={14} className=\"animate-spin\" /> Generating...</> : <><Sparkles size={14} /> Generate Schema</>}\n </button>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* ── Introspect Modal ─────────────────────────────────────────────── */}\n <AnimatePresence>\n {showIntrospect && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95 }} animate={{ scale: 1 }} exit={{ scale: 0.95 }} className=\"w-full max-w-lg border rounded-none-none shadow-2xl p-6 relative bg-app border-z-border\">\n <button onClick={() => setShowIntrospect(false)} className=\"absolute top-4 right-4 text-z-secondary hover:text-z-primary\"><X size={20} /></button>\n <h2 className=\"text-xl font-semibold mb-2 flex items-center gap-3\">\n <Database className=\"text-z-secondary \" /> DB Introspection\n </h2>\n <p className=\"text-sm text-z-muted mb-5 font-medium\">\n Connect to a Postgres database to reverse-engineer tables into Zenith schema fields.\n </p>\n <input\n type=\"text\"\n placeholder=\"postgresql://user:password@localhost:5432/mydb\"\n value={dbUri}\n onChange={e => setDbUri(e.target.value)}\n className=\"w-full bg-app border border-z-border focus:border-z-border/50 p-3.5 text-sm outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black rounded-none-none placeholder:text-z-secondary text-z-primary mb-4 font-mono\"\n />\n <button\n disabled={isIntrospecting}\n onClick={handleIntrospect}\n className=\"w-full py-3.5 bg-z-border hover:bg-z-input text-z-primary text-sm font-semibold flex justify-center items-center gap-2 transition-all rounded-none-none\"\n >\n {isIntrospecting ? <><Loader2 size={14} className=\"animate-spin\" /> Scanning...</> : <><RefreshCw size={14} /> Analyze Database</>}\n </button>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SchemaBuilderPage-BYprOkEv.js","names":[],"sources":["../../src/pages/SchemaBuilderPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react'\nimport {\n Plus, Database, Code, Copy, Check, Trash2, Box, Layers, Settings, X,\n Save, Loader2, ChevronDown, ChevronRight, Sparkles, RefreshCw, List,\n AlertCircle, Eye, EyeOff, Hash, Globe, Lock, Calendar, FileText,\n Image, Link2, ToggleLeft, AlignLeft, Braces, Tag\n} from 'lucide-react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { useTheme } from '../context/ThemeContext'\nimport toast from 'react-hot-toast'\nimport api from '../lib/api'\nimport { PageHeader } from '../components/ui/PageHeader'\nimport { cn } from '../lib/utils'\nimport { useUnsavedGuard } from '../hooks/useUnsavedGuard'\n\n// ── Full field type catalogue ────────────────────────────────────────────────\nconst FIELD_TYPES = [\n { value: 'text', label: 'Text', icon: FileText, color: '#6b7280' },\n { value: 'textarea', label: 'Textarea', icon: AlignLeft, color: '#6b7280' },\n { value: 'number', label: 'Number', icon: Hash, color: '#3b82f6' },\n { value: 'email', label: 'Email', icon: Globe, color: 'var(--z-accent)' },\n { value: 'password', label: 'Password', icon: Lock, color: '#ef4444' },\n { value: 'checkbox', label: 'Checkbox / Boolean', icon: ToggleLeft, color: 'var(--z-accent)' },\n { value: 'date', label: 'Date', icon: Calendar, color: '#f59e0b' },\n { value: 'select', label: 'Select / Enum', icon: List, color: '#f97316' },\n { value: 'media', label: 'Media / Image', icon: Image, color: '#06b6d4' },\n { value: 'richtext', label: 'Rich Text', icon: FileText, color: '#84cc16' },\n { value: 'relation', label: 'Relation', icon: Link2, color: '#ec4899' },\n { value: 'json', label: 'JSON Object', icon: Braces, color: '#6366f1' },\n { value: 'slug', label: 'Slug', icon: Tag, color: 'var(--z-accent)' },\n { value: 'array', label: 'Array / Repeater', icon: Layers, color: '#f59e0b' },\n { value: 'blocks', label: 'Dynamic Blocks', icon: Box, color: 'var(--z-accent)' },\n { value: 'group', label: 'Field Group', icon: Settings, color: '#3b82f6' },\n { value: 'code', label: 'Code Editor', icon: Code, color: '#6b7280' },\n { value: 'color', label: 'Color Picker', icon: Eye, color: '#f97316' },\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 index?: boolean\n hidden?: boolean\n readOnly?: boolean\n placeholder?: string\n description?: string\n defaultValue?: any\n min?: number\n max?: number\n regex?: string\n width?: string\n // select options\n options?: { label: string; value: string }[]\n // relation\n relationTo?: string\n hasMany?: boolean\n // array sub-fields\n fields?: FieldConfig[]\n}\n\ninterface CollectionSettings {\n drafts: boolean\n timestamps: boolean\n versions: boolean\n publicRead: boolean\n singleton: boolean\n auth: boolean\n softDelete: boolean\n}\n\ninterface SavedSchema {\n _id?: string\n id?: string\n slug: string\n singular?: string\n plural?: string\n fields?: FieldConfig[]\n settings?: CollectionSettings\n createdAt?: string\n isCodeFirst?: boolean\n}\n\nconst DEFAULT_SETTINGS: CollectionSettings = {\n drafts: true,\n timestamps: true,\n versions: false,\n publicRead: false,\n singleton: false,\n auth: false,\n softDelete: false,\n}\n\n// ── Helper ────────────────────────────────────────────────────────────────────\nfunction makeSlug(name: string): string {\n return name.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '')\n}\n\n// ── Field Type Picker ─────────────────────────────────────────────────────────\nfunction FieldTypePicker({ value, onChange, theme }: { value: FieldType; onChange: (t: FieldType) => void; theme: string }) {\n const [open, setOpen] = useState(false)\n const current = FIELD_TYPES.find(t => t.value === value)\n const Icon = current?.icon || FileText\n return (\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className={cn(\n 'flex items-center gap-2 px-3 py-2 border text-sm font-semibold transition-all w-full shadow-sm rounded-none',\n 'z-card-interactive'\n )}\n >\n <Icon size={12} style={{ color: current?.color }} />\n <span className=\"flex-1 text-left\">{current?.label || 'Select type'}</span>\n <ChevronDown size={10} className=\"text-z-secondary\" />\n </button>\n <AnimatePresence>\n {open && (\n <motion.div\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 4 }}\n className={cn(\n 'absolute z-50 top-full left-0 mt-1 w-64 border shadow-sm max-h-72 overflow-y-auto rounded-none',\n theme === 'dark' ? 'bg-z-popover backdrop-blur-xl border-z-border' : 'bg-z-panel border-z-border'\n )}\n >\n {FIELD_TYPES.map(ft => {\n const FtIcon = ft.icon\n return (\n <button\n key={ft.value}\n type=\"button\"\n onClick={() => { onChange(ft.value); setOpen(false) }}\n className={cn(\n 'w-full flex items-center gap-3 px-4 py-2.5 text-sm font-semibold transition-all rounded-none',\n value === ft.value\n ? 'bg-z-accent text-z-logo-text'\n : theme === 'dark' ? 'text-z-muted hover:bg-z-hover hover:text-z-primary' : 'text-z-secondary hover:bg-[var(--z-bg-input)]'\n )}\n >\n <FtIcon size={12} style={{ color: value === ft.value ? 'white' : ft.color }} />\n {ft.label}\n </button>\n )\n })}\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n\n\n\n// ── Nested Fields Editor ──────────────────────────────────────────────────────\nfunction NestedFieldsEditor({\n fields, onUpdate, theme, availableCollections\n}: {\n fields: FieldConfig[]\n onUpdate: (fields: FieldConfig[]) => void\n theme: string\n availableCollections: string[]\n}) {\n const addField = () => {\n onUpdate([...fields, { name: `nestedField${fields.length + 1}`, type: 'text', label: `Nested Field ${fields.length + 1}` }])\n }\n \n const removeField = (index: number) => {\n onUpdate(fields.filter((_, i) => i !== index))\n }\n\n const updateField = (index: number, key: string, value: any) => {\n const next = [...fields]\n next[index] = { ...next[index], [key]: value }\n onUpdate(next)\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 px-3 rounded-none shadow-sm',\n 'z-input'\n )\n\n return (\n <div className=\"mt-4 border-l-2 border-z-accent/50 pl-4 space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h4 className=\"text-sm font-bold text-z-primary\">Nested Fields ({fields.length})</h4>\n <button\n onClick={addField}\n type=\"button\"\n className=\"flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border border-z-border text-z-secondary text-sm font-semibold rounded-none transition-all\"\n >\n <Plus size={12} /> Add Field\n </button>\n </div>\n \n {fields.length === 0 ? (\n <div className=\"p-4 border border-dashed border-z-border text-center text-z-secondary text-sm\">\n No nested fields added yet.\n </div>\n ) : (\n <div className=\"space-y-4\">\n {fields.map((field, i) => (\n <div key={i} className=\"p-4 relative group border border-z-border bg-z-panel\">\n <button\n type=\"button\"\n onClick={() => removeField(i)}\n className=\"absolute top-2 right-2 opacity-0 group-hover:opacity-100 p-1 text-red-500/50 hover:text-red-500 transition-all rounded-none hover:bg-red-500/10 z-10\"\n >\n <Trash2 size={12} />\n </button>\n \n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 pr-6\">\n <div>\n <label className=\"text-xs font-semibold text-z-secondary block mb-1\">Field Name (key)</label>\n <input\n type=\"text\"\n value={field.name}\n onChange={e => updateField(i, 'name', e.target.value.replace(/\\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, ''))}\n className={cn(inputClass, 'w-full rounded-none font-mono text-xs')}\n placeholder=\"fieldName\"\n />\n </div>\n <div>\n <label className=\"text-xs font-semibold text-z-secondary block mb-1\">Field Type</label>\n <FieldTypePicker\n value={field.type}\n onChange={v => updateField(i, 'type', v)}\n theme={theme}\n />\n </div>\n <div>\n <label className=\"text-xs font-semibold text-z-secondary block mb-1\">Display Label</label>\n <input\n type=\"text\"\n value={field.label || ''}\n onChange={e => updateField(i, 'label', e.target.value)}\n className={cn(inputClass, 'w-full rounded-none text-xs')}\n placeholder=\"Human readable label\"\n />\n </div>\n </div>\n \n <FieldAdvancedPanel\n field={field}\n onUpdate={(key, value) => updateField(i, key, value)}\n theme={theme}\n availableCollections={availableCollections}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// ── Advanced Field Panel ──────────────────────────────────────────────────────\nfunction FieldAdvancedPanel({\n field, onUpdate, theme, availableCollections\n}: {\n field: FieldConfig\n onUpdate: (key: string, value: any) => void\n theme: string\n availableCollections: string[]\n}) {\n const [open, setOpen] = useState(false)\n const inputClass = cn(\n 'w-full border p-2 text-sm font-mono outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-colors rounded-none shadow-sm',\n 'z-input'\n )\n const checkClass = 'accent-gray-500 w-3.5 h-3.5'\n const labelClass = 'text-sm font-semibold text-z-secondary'\n\n return (\n <div className=\"mt-2\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className=\"flex items-center gap-1.5 text-sm font-semibold text-z-secondary hover:text-z-secondary transition-colors\"\n >\n {open ? <ChevronDown size={10} /> : <ChevronRight size={10} />}\n Advanced Options\n </button>\n <AnimatePresence>\n {open && (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: 'auto', opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n className=\"overflow-hidden\"\n >\n <div className={cn('mt-3 p-4 border space-y-4 rounded-none shadow-sm', 'z-panel shadow-sm')}>\n {/* Flags */}\n <div className=\"flex flex-wrap gap-x-6 gap-y-2\">\n {[\n ['required', 'Required'],\n ['unique', 'Unique'],\n ['index', 'Index'],\n ['hidden', 'Hidden'],\n ['readOnly', 'Read Only'],\n ].map(([key, lbl]) => (\n <label key={key} className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={!!(field as any)[key]}\n onChange={e => onUpdate(key, e.target.checked)}\n className={checkClass}\n />\n <span className={labelClass}>{lbl}</span>\n </label>\n ))}\n </div>\n\n {/* Text inputs */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Placeholder</label>\n <input type=\"text\" value={field.placeholder || ''} onChange={e => onUpdate('placeholder', e.target.value)} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Default Value</label>\n <input type=\"text\" value={field.defaultValue ?? ''} onChange={e => onUpdate('defaultValue', e.target.value)} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Description</label>\n <input type=\"text\" value={field.description || ''} onChange={e => onUpdate('description', e.target.value)} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Width (e.g. 50%)</label>\n <input type=\"text\" value={field.width || ''} onChange={e => onUpdate('width', e.target.value)} className={inputClass} />\n </div>\n {(field.type === 'text' || field.type === 'textarea') && (\n <>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Min Length</label>\n <input type=\"number\" value={field.min ?? ''} onChange={e => onUpdate('min', Number(e.target.value))} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Max Length</label>\n <input type=\"number\" value={field.max ?? ''} onChange={e => onUpdate('max', Number(e.target.value))} className={inputClass} />\n </div>\n <div className=\"col-span-2\">\n <label className={cn(labelClass, 'block mb-1')}>Regex Pattern</label>\n <input type=\"text\" value={field.regex || ''} onChange={e => onUpdate('regex', e.target.value)} className={inputClass} placeholder=\"^[a-z]+$\" />\n </div>\n </>\n )}\n {field.type === 'number' && (\n <>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Min</label>\n <input type=\"number\" value={field.min ?? ''} onChange={e => onUpdate('min', Number(e.target.value))} className={inputClass} />\n </div>\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Max</label>\n <input type=\"number\" value={field.max ?? ''} onChange={e => onUpdate('max', Number(e.target.value))} className={inputClass} />\n </div>\n </>\n )}\n </div>\n\n {/* Relation options */}\n {field.type === 'relation' && (\n <div className=\"space-y-3\">\n <div>\n <label className={cn(labelClass, 'block mb-1')}>Relates To Collection</label>\n <select\n value={field.relationTo || ''}\n onChange={e => onUpdate('relationTo', e.target.value)}\n className={cn(inputClass, 'cursor-pointer')}\n >\n <option value=\"\">-- Select Collection --</option>\n {availableCollections.map(col => (\n <option key={col} value={col}>{col}</option>\n ))}\n </select>\n </div>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={!!field.hasMany}\n onChange={e => onUpdate('hasMany', e.target.checked)}\n className={checkClass}\n />\n <span className={labelClass}>Has Many (array of references)</span>\n </label>\n </div>\n )}\n\n {/* Nested fields for array/group */}\n {(field.type === 'array' || field.type === 'group') && (\n <NestedFieldsEditor\n fields={field.fields || []}\n onUpdate={newFields => onUpdate('fields', newFields)}\n theme={theme}\n availableCollections={availableCollections}\n />\n )}\n\n {/* Select options editor */}\n {field.type === 'select' && (\n <div>\n <label className={cn(labelClass, 'block mb-2')}>Options</label>\n <div className=\"space-y-2\">\n {(field.options || []).map((opt, oi) => (\n <div key={oi} className=\"flex gap-2\">\n <input\n type=\"text\"\n value={opt.label}\n onChange={e => {\n const newOpts = [...(field.options || [])]\n newOpts[oi] = { ...newOpts[oi], label: e.target.value }\n onUpdate('options', newOpts)\n }}\n placeholder=\"Label\"\n className={cn(inputClass, 'flex-1')}\n />\n <input\n type=\"text\"\n value={opt.value}\n onChange={e => {\n const newOpts = [...(field.options || [])]\n newOpts[oi] = { ...newOpts[oi], value: e.target.value }\n onUpdate('options', newOpts)\n }}\n placeholder=\"value\"\n className={cn(inputClass, 'flex-1 font-mono')}\n />\n <button\n type=\"button\"\n onClick={() => onUpdate('options', (field.options || []).filter((_, i) => i !== oi))}\n className=\"p-2 text-red-500/60 hover:text-red-500 transition-colors\"\n >\n <X size={12} />\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={() => onUpdate('options', [...(field.options || []), { label: '', value: '' }])}\n className=\"flex items-center gap-1 text-sm font-semibold text-z-secondary hover:text-z-secondary\"\n >\n <Plus size={10} /> Add Option\n </button>\n </div>\n </div>\n )}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n\n// ── Main Schema Builder Page ──────────────────────────────────────────────────\nexport default function SchemaBuilderPage() {\n const { theme } = useTheme()\n const dark = theme === 'dark'\n\n // Schema being edited\n const [collectionName, setCollectionName] = useState('New Collection')\n const [slug, setSlug] = useState('new-collection')\n const [fields, setFields] = useState<FieldConfig[]>([])\n const [settings, setSettings] = useState<CollectionSettings>(DEFAULT_SETTINGS)\n\n // Saved schemas list\n const [savedSchemas, setSavedSchemas] = useState<SavedSchema[]>([])\n const [loadingSchemas, setLoadingSchemas] = useState(true)\n const [activeSchemaId, setActiveSchemaId] = useState<string | null>(null)\n\n const activeSchemaObj = savedSchemas.find(s => (s._id || s.id) === activeSchemaId)\n const isCodeFirst = activeSchemaObj?.isCodeFirst\n\n // UI state\n const [saving, setSaving] = useState(false)\n const [showCode, setShowCode] = useState(false)\n const [copied, setCopied] = useState(false)\n const [showIntrospect, setShowIntrospect] = useState(false)\n const [dbUri, setDbUri] = useState('')\n const [isIntrospecting, setIsIntrospecting] = useState(false)\n const [aiPrompt, setAiPrompt] = useState('')\n const [isAIGenerating, setIsAIGenerating] = useState(false)\n const [showAI, setShowAI] = useState(false)\n const [availableCollections, setAvailableCollections] = useState<string[]>([])\n\n // Track unsaved changes\n const [isDirty, setIsDirty] = useState(false)\n useEffect(() => {\n const currentStr = JSON.stringify({ slug, collectionName, fields, settings })\n if (activeSchemaObj) {\n const activeStr = JSON.stringify({\n slug: activeSchemaObj.slug,\n collectionName: activeSchemaObj.plural || activeSchemaObj.slug,\n fields: activeSchemaObj.fields || [],\n settings: { ...DEFAULT_SETTINGS, ...(activeSchemaObj.settings || {}) }\n })\n setIsDirty(currentStr !== activeStr)\n } else {\n const defaultStr = JSON.stringify({\n slug: 'new-collection',\n collectionName: 'New Collection',\n fields: [],\n settings: DEFAULT_SETTINGS\n })\n setIsDirty(currentStr !== defaultStr)\n }\n }, [slug, collectionName, fields, settings, activeSchemaObj])\n\n useUnsavedGuard({ hasUnsavedChanges: isDirty })\n\n // Load saved schemas and collections list\n const loadSchemas = useCallback(async () => {\n try {\n // Fetch both Dynamic UI Schemas and Code-First JSON Schemas\n const [dbRes, systemRes] = await Promise.all([\n api.get('/schemas').catch(() => ({ data: { data: [] } })),\n api.get('/system/schemas').catch(() => ({ data: { data: { collections: [] } } }))\n ])\n\n const rawDb = dbRes.data?.data\n const dbList: SavedSchema[] = Array.isArray(rawDb) ? rawDb : Array.isArray(rawDb?.schemas) ? rawDb.schemas : []\n \n const rawSystem = systemRes.data?.data?.collections || []\n const systemList: SavedSchema[] = Array.isArray(rawSystem) \n ? rawSystem.map(c => ({\n ...c,\n id: c.slug, // Code-First schemas use slug as ID\n isCodeFirst: true\n }))\n : []\n\n // Combine and deduplicate (System Code-First schemas override DB schemas)\n const schemaMap = new Map<string, SavedSchema>()\n for (const s of [...dbList, ...systemList]) {\n schemaMap.set(s.slug, s)\n }\n const combined = Array.from(schemaMap.values()).sort((a, b) => a.slug.localeCompare(b.slug))\n setSavedSchemas(combined)\n } catch {\n setSavedSchemas([])\n } finally {\n setLoadingSchemas(false)\n }\n }, [])\n\n useEffect(() => {\n loadSchemas()\n // Load live collection slugs for relation field picker\n api.get('/schemas').then(res => {\n const d = res.data?.data\n const cols: any[] = Array.isArray(d?.collections) ? d.collections\n : Array.isArray(d) ? d : []\n setAvailableCollections(cols.map((c: any) => c.slug).filter(Boolean))\n }).catch(() => {})\n }, [loadSchemas])\n\n // Load a saved schema into the editor\n const loadSchema = (schema: SavedSchema) => {\n setActiveSchemaId(schema._id || schema.id || null)\n setCollectionName(schema.plural || schema.slug)\n setSlug(schema.slug)\n setFields(schema.fields || [])\n setSettings({ ...DEFAULT_SETTINGS, ...(schema.settings || {}) })\n toast.success(`Loaded schema: ${schema.slug}`)\n }\n\n const resetEditor = () => {\n setActiveSchemaId(null)\n setCollectionName('New Collection')\n setSlug('new-collection')\n setFields([])\n setSettings(DEFAULT_SETTINGS)\n }\n\n const addField = () => {\n setFields(prev => [...prev, { name: `field${prev.length + 1}`, type: 'text', label: `Field ${prev.length + 1}` }])\n }\n\n const removeField = (index: number) => {\n setFields(prev => prev.filter((_, i) => i !== index))\n }\n\n const updateField = (index: number, key: string, value: any) => {\n setFields(prev => {\n const next = [...prev]\n next[index] = { ...next[index], [key]: value }\n return next\n })\n }\n\n // Save schema to backend\n const handleSave = async () => {\n if (!slug || !collectionName) return toast.error('Name and slug required')\n setSaving(true)\n try {\n const payload = {\n slug,\n singular: collectionName,\n plural: collectionName,\n fields,\n settings,\n }\n if (activeSchemaId) {\n await api.put(`/schemas/${activeSchemaId}`, payload)\n toast.success('Schema updated!')\n } else {\n const res = await api.post('/schemas', payload)\n const id = res.data?.data?._id || res.data?.data?.id\n if (id) setActiveSchemaId(id)\n toast.success('Schema created!')\n }\n await loadSchemas()\n // Hot-reload backend routes\n await api.post('/system/schema/reload').catch(() => {})\n } catch (err: any) {\n toast.error(err.response?.data?.error?.message || 'Failed to save schema')\n } finally {\n setSaving(false)\n }\n }\n\n // Delete schema\n const handleDeleteSchema = async (id: string, slug: string) => {\n try {\n await api.delete(`/schemas/${id}`)\n toast.success(`Schema \"${slug}\" deleted`)\n if (activeSchemaId === id) resetEditor()\n await loadSchemas()\n } catch { toast.error('Failed to delete schema') }\n }\n\n // Introspect DB\n const handleIntrospect = async () => {\n if (!dbUri) return toast.error('Please provide a connection string')\n setIsIntrospecting(true)\n try {\n const res = await api.post('/system/introspect', { connectionString: dbUri })\n const collections = res.data.data\n if (collections?.length > 0) {\n const col = collections[0]\n setCollectionName(col.name)\n setSlug(makeSlug(col.name))\n setFields(col.fields || [])\n toast.success(`Introspected: ${col.name}`)\n setShowIntrospect(false)\n } else {\n toast.error('No tables found')\n }\n } catch (err: any) {\n toast.error(err.response?.data?.error || 'Introspection failed')\n } finally {\n setIsIntrospecting(false)\n }\n }\n\n // AI Generate\n const handleAIGenerate = async () => {\n if (!aiPrompt) return toast.error('Enter a prompt first')\n setIsAIGenerating(true)\n try {\n const res = await api.post('/system/ai-architect', { prompt: aiPrompt })\n const schema = res.data?.data\n if (schema) {\n setCollectionName(schema.name || schema.slug || 'AI Collection')\n setSlug(schema.slug || makeSlug(schema.name || 'ai-collection'))\n setFields(schema.fields || [])\n toast.success('AI schema generated!')\n setShowAI(false)\n }\n } catch (err: any) {\n toast.error(err.response?.data?.error?.message || 'AI generation failed')\n } finally {\n setIsAIGenerating(false)\n }\n }\n\n // Generate TypeScript code\n const generateCode = () => {\n const fieldsCode = fields.map(f => {\n let props = ` name: '${f.name}',\\n type: '${f.type}',`\n if (f.label) props += `\\n label: '${f.label}',`\n if (f.required) props += `\\n required: true,`\n if (f.unique) props += `\\n unique: true,`\n if (f.relationTo) props += `\\n relationTo: '${f.relationTo}',`\n if (f.options?.length) props += `\\n options: ${JSON.stringify(f.options)},`\n return ` {\\n${props}\\n },`\n }).join('\\n')\n\n const settingsCode = Object.entries(settings)\n .filter(([, v]) => v === true)\n .map(([k]) => ` ${k}: true,`)\n .join('\\n')\n\n return `import { CollectionConfig } from '@zenith-open/zenithcms-types'\n\nexport const ${collectionName.replace(/\\s+/g, '')}: CollectionConfig = {\n name: '${collectionName}',\n slug: '${slug}',\n${settingsCode ? settingsCode + '\\n' : ''} fields: [\n${fieldsCode}\n ],\n}`\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 'z-input'\n )\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\n {/* ── Schemas Sidebar ─────────────────────────────────────────────── */}\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-bold text-z-primary\">\n Schemas\n </h2>\n <button\n onClick={resetEditor}\n className=\"p-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary rounded-none transition-colors\"\n title=\"New Schema\"\n >\n <Plus size={14} />\n </button>\n </div>\n <div className=\"flex-1 overflow-auto p-2 space-y-1\">\n {loadingSchemas ? (\n <div className=\"p-4 flex justify-center\"><Loader2 className=\"animate-spin text-z-muted\" size={16} /></div>\n ) : savedSchemas.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-z-secondary\">\n No schemas yet\n </div>\n ) : savedSchemas.map(schema => {\n const id = schema._id || schema.id || ''\n const isActive = activeSchemaId === id\n return (\n <div key={id} className=\"group flex items-center gap-1\">\n <button\n onClick={() => loadSchema(schema)}\n className={cn(\n 'flex-1 flex items-center justify-between text-left px-3 py-2.5 text-sm font-semibold transition-colors rounded-none truncate',\n isActive ? '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 )}\n >\n <span>{schema.slug}</span>\n {schema.isCodeFirst && <Lock size={10} className={isActive ? 'text-z-primary' : 'text-z-secondary'} />}\n </button>\n {!schema.isCodeFirst && (\n <button\n onClick={() => handleDeleteSchema(id, schema.slug)}\n className=\"opacity-0 group-hover:opacity-100 p-1.5 text-red-500/50 hover:text-red-500 transition-all\"\n >\n <Trash2 size={12} />\n </button>\n )}\n </div>\n )\n })}\n </div>\n </div>\n\n {/* ── Main Editor ─────────────────────────────────────────────────── */}\n <div className=\"flex-1 flex flex-col overflow-hidden\">\n {/* Header toolbar */}\n <PageHeader\n title=\"Schema Builder\"\n backLink={{ to: '/', label: 'Dashboard' }}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setShowAI(true)}\n className=\"px-4 py-2 bg-z-active-bg text-z-accent hover:opacity-80 text-sm font-bold rounded-none transition-all\"\n >\n AI Generate\n </button>\n <button\n onClick={() => setShowIntrospect(true)}\n className=\"px-4 py-2 text-sm font-bold border border-z-border hover:bg-z-hover rounded-none transition-all\"\n >\n Introspect DB\n </button>\n <button\n onClick={() => setShowCode(true)}\n className=\"px-4 py-2 text-sm font-bold border border-z-border hover:bg-z-hover rounded-none transition-all\"\n >\n View Code\n </button>\n <button\n onClick={handleSave}\n disabled={saving || isCodeFirst}\n className=\"px-4 py-2 bg-z-accent hover:bg-z-accent/90 text-z-primary text-sm font-bold rounded-none transition-all disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {saving ? 'Saving...' : isCodeFirst ? 'Locked' : 'Save'}\n </button>\n </div>\n }\n />\n\n <div className=\"flex-1 overflow-auto p-6 space-y-6 custom-editor-scrollbar\">\n {isCodeFirst && (\n <div className=\"px-4 py-3 border border-amber-500/30 bg-amber-500/10 text-amber-500 text-sm font-bold flex items-center justify-between\">\n <span>Code-First Schema (Read Only)</span>\n <Lock size={14} />\n </div>\n )}\n\n {/* Collection Meta */}\n <div className={cn('rounded-none border p-6 space-y-4 shadow-sm transition-all', 'z-panel')}>\n <h3 className=\"text-sm font-bold text-z-primary\">\n Collection Settings\n </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\n type=\"text\"\n value={collectionName}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n setCollectionName(e.target.value)\n setSlug(makeSlug(e.target.value))\n }}\n className={cn(inputClass, 'w-full rounded-none', isCodeFirst && 'opacity-70 cursor-not-allowed')}\n placeholder=\"e.g. Blog Posts\"\n />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Slug (API ID)</label>\n <input\n type=\"text\"\n value={slug}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n setSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))\n }}\n className={cn(inputClass, 'w-full rounded-none font-mono', isCodeFirst && 'opacity-70 cursor-not-allowed')}\n placeholder=\"e.g. blog-posts\"\n />\n </div>\n </div>\n\n {/* Settings toggles */}\n <div className=\"flex flex-wrap gap-x-6 gap-y-3 pt-2 border-t border-z-border\">\n {(Object.keys(DEFAULT_SETTINGS) as (keyof CollectionSettings)[]).map(key => (\n <label key={key} className=\"flex items-center gap-2 cursor-pointer group\">\n <div\n onClick={() => {\n if (isCodeFirst) return\n setSettings(prev => ({ ...prev, [key]: !prev[key] }))\n }}\n className={cn(\n 'w-8 h-4 rounded-full relative transition-all cursor-pointer border border-transparent shadow-inner',\n settings[key] ? (dark ? 'bg-z-accent' : 'bg-z-accent') : (dark ? 'bg-gray-700' : 'bg-gray-300'),\n isCodeFirst && 'opacity-50 cursor-not-allowed'\n )}\n >\n <div className={cn(\n 'absolute top-[1.5px] w-3 h-3 rounded-full bg-white shadow-sm transition-all',\n settings[key] ? 'left-[17px]' : 'left-[1.5px]'\n )} />\n </div>\n <span className=\"text-sm font-bold capitalize text-z-muted group-hover:text-z-primary transition-colors\">\n {key.replace(/([A-Z])/g, ' $1').trim()}\n </span>\n </label>\n ))}\n </div>\n </div>\n\n {/* Fields */}\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-bold text-z-primary\">\n Fields ({fields.length})\n </h3>\n {!isCodeFirst && (\n <button\n onClick={addField}\n 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 >\n <Plus size={12} /> Add Field\n </button>\n )}\n </div>\n\n <div className=\"p-4 space-y-3\">\n <AnimatePresence>\n {fields.map((field, i) => (\n <motion.div\n key={i}\n layout\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.97 }}\n className={cn('p-4 relative group z-panel', isCodeFirst && 'opacity-70')}\n >\n {/* Delete button */}\n {!isCodeFirst && (\n <button\n onClick={() => removeField(i)}\n className=\"absolute top-3 right-3 opacity-0 group-hover:opacity-100 p-1.5 text-red-500/50 hover:text-red-500 transition-all rounded-none hover:bg-red-500/10\"\n >\n <Trash2 size={14} />\n </button>\n )}\n\n {/* Main row */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 pr-8\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Field Name (key)</label>\n <input\n type=\"text\"\n value={field.name}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n updateField(i, 'name', e.target.value.replace(/\\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, ''))\n }}\n className={cn(inputClass, 'w-full rounded-none-none font-mono text-sm', isCodeFirst && 'cursor-not-allowed')}\n placeholder=\"fieldName\"\n />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Field Type</label>\n <div className={cn(isCodeFirst && 'opacity-70 pointer-events-none')}>\n <FieldTypePicker\n value={field.type}\n onChange={v => updateField(i, 'type', v)}\n theme={theme}\n />\n </div>\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Display Label</label>\n <input\n type=\"text\"\n value={field.label || ''}\n readOnly={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n updateField(i, 'label', e.target.value)\n }}\n className={cn(inputClass, 'w-full rounded-none-none', isCodeFirst && 'cursor-not-allowed')}\n placeholder=\"Human readable label\"\n />\n </div>\n </div>\n\n {/* Quick flags row */}\n <div className=\"flex items-center gap-5 mt-3 pt-2 border-t border-z-border\">\n {[['required', 'Required'], ['unique', 'Unique'], ['index', 'Index']].map(([k, l]) => (\n <label key={k} className=\"flex items-center gap-1.5 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={!!(field as any)[k]}\n disabled={isCodeFirst}\n onChange={e => {\n if (isCodeFirst) return\n updateField(i, k, e.target.checked)\n }}\n className=\"accent-gray-500 w-3 h-3 disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n <span className=\"text-sm font-semibold text-z-secondary\">{l}</span>\n </label>\n ))}\n </div>\n\n {/* Advanced panel */}\n {!isCodeFirst && (\n <FieldAdvancedPanel\n field={field}\n onUpdate={(key, value) => updateField(i, key, value)}\n theme={theme}\n availableCollections={availableCollections}\n />\n )}\n </motion.div>\n ))}\n </AnimatePresence>\n\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 <p className=\"text-sm text-z-secondary mt-1\">Click \"Add Field\" or use AI Generate to get started</p>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n\n {/* ── Code Modal ─────────────────────────────────────────────────── */}\n <AnimatePresence>\n {showCode && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95 }} animate={{ scale: 1 }} exit={{ scale: 0.95 }} className=\"w-full max-w-3xl border rounded-none-none shadow-2xl p-6 relative flex flex-col h-[80vh] bg-app border-z-border\">\n <button onClick={() => setShowCode(false)} className=\"absolute top-4 right-4 text-z-secondary hover:text-z-primary\"><X size={20} /></button>\n <h2 className=\"text-xl font-semibold mb-4 flex items-center gap-3\">\n <Code className=\"text-z-secondary \" /> Generated TypeScript\n </h2>\n <div className=\"flex-1 bg-[#1E1E1E] border border-z-border p-5 overflow-auto text-sm font-mono text-z-secondary relative rounded-none-none\">\n <button\n onClick={() => { navigator.clipboard.writeText(generateCode()); setCopied(true); setTimeout(() => setCopied(false), 2000) }}\n className=\"absolute top-3 right-3 p-2 bg-z-panel/10 hover:bg-z-panel/20 text-z-primary transition-colors rounded-none-none\"\n >\n {copied ? <Check size={14} /> : <Copy size={14} />}\n </button>\n <pre><code>{generateCode()}</code></pre>\n </div>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* ── AI Generate Modal ───────────────────────────────────────────── */}\n <AnimatePresence>\n {showAI && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95 }} animate={{ scale: 1 }} exit={{ scale: 0.95 }} className=\"w-full max-w-lg border rounded-none-none shadow-2xl p-6 relative bg-app border-z-border\">\n <button onClick={() => setShowAI(false)} className=\"absolute top-4 right-4 text-z-secondary hover:text-z-primary\"><X size={20} /></button>\n <h2 className=\"text-xl font-semibold mb-2 flex items-center gap-3\">\n <Sparkles className=\"text-purple-400\" /> AI Schema Architect\n </h2>\n <p className=\"text-sm text-z-muted mb-5 font-medium\">\n Describe what you need — the AI will generate a complete schema with fields, types, and relations.\n </p>\n <textarea\n rows={4}\n value={aiPrompt}\n onChange={e => setAiPrompt(e.target.value)}\n placeholder='e.g. \"A blog post collection with title, slug, content, featured image, author relation to users, published date, and category select field with options.\"'\n className=\"w-full bg-app border border-z-border focus:border-z-active-border/50 p-4 text-sm outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black rounded-none-none placeholder:text-z-secondary text-z-primary resize-none mb-4\"\n />\n <button\n disabled={isAIGenerating || !aiPrompt}\n onClick={handleAIGenerate}\n className=\"w-full py-3.5 bg-z-accent hover:opacity-80 text-z-logo-text text-sm font-semibold flex justify-center items-center gap-2 transition-all rounded-none-none disabled:opacity-50\"\n >\n {isAIGenerating ? <><Loader2 size={14} className=\"animate-spin\" /> Generating...</> : <><Sparkles size={14} /> Generate Schema</>}\n </button>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* ── Introspect Modal ─────────────────────────────────────────────── */}\n <AnimatePresence>\n {showIntrospect && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-app/70 backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95 }} animate={{ scale: 1 }} exit={{ scale: 0.95 }} className=\"w-full max-w-lg border rounded-none-none shadow-2xl p-6 relative bg-app border-z-border\">\n <button onClick={() => setShowIntrospect(false)} className=\"absolute top-4 right-4 text-z-secondary hover:text-z-primary\"><X size={20} /></button>\n <h2 className=\"text-xl font-semibold mb-2 flex items-center gap-3\">\n <Database className=\"text-z-secondary \" /> DB Introspection\n </h2>\n <p className=\"text-sm text-z-muted mb-5 font-medium\">\n Connect to a Postgres database to reverse-engineer tables into Zenith schema fields.\n </p>\n <input\n type=\"text\"\n placeholder=\"postgresql://user:password@localhost:5432/mydb\"\n value={dbUri}\n onChange={e => setDbUri(e.target.value)}\n className=\"w-full bg-app border border-z-border focus:border-z-border/50 p-3.5 text-sm outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black rounded-none-none placeholder:text-z-secondary text-z-primary mb-4 font-mono\"\n />\n <button\n disabled={isIntrospecting}\n onClick={handleIntrospect}\n className=\"w-full py-3.5 bg-z-border hover:bg-z-input text-z-primary text-sm font-semibold flex justify-center items-center gap-2 transition-all rounded-none-none\"\n >\n {isIntrospecting ? <><Loader2 size={14} className=\"animate-spin\" /> Scanning...</> : <><RefreshCw size={14} /> Analyze Database</>}\n </button>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{$t as t,B as n,Bt as r,C as i,Cn as a,E as o,En as s,Et as c,F as l,G as u,Gn as d,H as f,Hn as p,Ht as m,I as h,J as g,Jn as _,Jt as v,K as y,Kt as b,L as x,Ln as S,Lt as C,Mn as w,Mt as T,Pn as E,Q as D,R as O,Rn as k,S as A,St as j,T as M,Tt as N,U as P,Ut as F,V as I,Vt as L,W as R,Wt as z,Yt as B,Z as V,Zn as ee,_ as te,an as H,br as ne,cn as U,d as W,dt as re,et as ie,g as G,gt as K,h as q,hn as ae,in as oe,ir as se,it as ce,j as le,kt as ue,l as J,m as de,mn as fe,nt as pe,o as me,pr as he,pt as ge,qn as _e,rr as ve,sn as ye,tt as be,u as xe,un as Se,v as Ce,vr as we,w as Te,wn as Ee,x as De,xr as Oe,y as ke}from"./vendor-react-DQVTOTFO.js";import{a as Ae,o as Y,s as je,t as X}from"./utils-fgvbH6CB.js";import{_ as Me,g as Ne,h as Pe,m as Fe,p as Ie,y as Le}from"./index-ChcKY5Xe.js";import Re from"./ApiExplorerPage-UJpoKRI0.js";import{t as ze}from"./EmptyState-X_SXKpQY.js";var Z=e(Oe(),1),Be={view:`viewer`,create:`editor`,edit:`editor`,publish:`editor`,unpublish:`editor`,delete:`editor`,view_audit_log:`editor`,manage_redirects:`editor`,manage_schema:`admin`,manage_settings:`admin`,manage_plugins:`admin`,manage_users:`admin`,manage_api_keys:`admin`,download_backup:`admin`},Ve={viewer:0,editor:1,admin:2};function He(e,t){if(!e)return!1;let n=Ve[Be[t]]??999;return(Ve[e]??-1)>=n}function Ue(){let e=Le(e=>e.user)?.role??`viewer`;return{role:e,can:t=>He(e,t),isAdmin:e===`admin`,isEditor:Ve[e]>=Ve.editor}}var Q=we();function We({children:e,sidebar:t,sidebarPosition:n=`right`,sidebarWidth:r=`w-[320px]`,className:i,...a}){let{theme:o}=Ae();return(0,Q.jsxs)(`div`,{className:X(`flex flex-col lg:flex-row h-full min-h-[calc(100vh-65px)]`,i),...a,children:[n===`left`&&t&&(0,Q.jsx)(`div`,{className:X(`shrink-0 border-b lg:border-b-0 lg:border-r flex flex-col`,r,o===`dark`?`border-z-border bg-[#050505]`:`border-z-border bg-[var(--z-bg-input)]/30`),children:t}),(0,Q.jsx)(`div`,{className:`flex-1 flex flex-col min-w-0`,children:e}),n===`right`&&t&&(0,Q.jsx)(`div`,{className:X(`shrink-0 border-t lg:border-t-0 lg:border-l flex flex-col`,r,o===`dark`?`border-z-border bg-[#050505]`:`border-z-border bg-[var(--z-bg-input)]/30`),children:t})]})}var Ge=`UTC.America/New_York.America/Chicago.America/Denver.America/Los_Angeles.America/Anchorage.America/Honolulu.America/Sao_Paulo.America/Toronto.America/Vancouver.Europe/London.Europe/Paris.Europe/Berlin.Europe/Amsterdam.Europe/Rome.Europe/Madrid.Europe/Stockholm.Europe/Athens.Europe/Warsaw.Europe/Prague.Asia/Dubai.Asia/Kolkata.Asia/Singapore.Asia/Tokyo.Asia/Shanghai.Asia/Seoul.Asia/Bangkok.Asia/Jakarta.Asia/Karachi.Asia/Tehran.Africa/Cairo.Africa/Lagos.Africa/Johannesburg.Africa/Nairobi.Australia/Sydney.Australia/Melbourne.Pacific/Auckland`.split(`.`),Ke=[{value:`en`,label:`English (en)`},{value:`en-US`,label:`English US (en-US)`},{value:`en-GB`,label:`English UK (en-GB)`},{value:`fr`,label:`French (fr)`},{value:`de`,label:`German (de)`},{value:`es`,label:`Spanish (es)`},{value:`it`,label:`Italian (it)`},{value:`pt`,label:`Portuguese (pt)`},{value:`ar`,label:`Arabic (ar)`},{value:`zh`,label:`Chinese (zh)`},{value:`ja`,label:`Japanese (ja)`},{value:`ko`,label:`Korean (ko)`},{value:`hi`,label:`Hindi (hi)`},{value:`ru`,label:`Russian (ru)`},{value:`nl`,label:`Dutch (nl)`},{value:`pl`,label:`Polish (pl)`},{value:`tr`,label:`Turkish (tr)`}],qe=({settings:e,setSettings:t,theme:n})=>{let r=n===`dark`,[i,a]=(0,Z.useState)(!1),[o,s]=(0,Z.useState)(!1),[l,u]=(0,Z.useState)(!1),[d,f]=(0,Z.useState)(!1),p=localStorage.getItem(`activeSiteId`)||``,m=localStorage.getItem(`activeSiteName`)||`Unknown Site`,h=()=>{p&&navigator.clipboard.writeText(p).then(()=>{a(!0),setTimeout(()=>a(!1),2e3)})},g=async(n,r,i)=>{i(!0);try{let i=new FormData;i.append(`file`,n);let a=await Y.post(`/upload`,i,{headers:{"Content-Type":`multipart/form-data`}}),o=a.data?.data?.url||a.data?.url;o&&(t({...e,[r]:o}),J.success(`Image uploaded`))}catch{J.error(`Upload failed`)}finally{i(!1)}},_=X(`p-5 border rounded-none transition-all space-y-3`,r?`bg-z-panel backdrop-blur-md border-z-border shadow-sm`:`bg-[var(--z-bg-input)]/50 border-z-border shadow-sm`),y=X(`w-full border rounded-none py-2.5 px-4 text-sm transition-all outline-none focus:ring-1 focus:ring-z-active-border focus:border-z-accent`,r?`bg-app/80 border-z-border text-z-primary placeholder:text-z-primary`:`bg-z-panel border-z-border`),b=({field:n,label:i,value:a,uploading:o,setUploading:s})=>(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:i}),(0,Q.jsxs)(`div`,{className:`flex gap-3 items-start`,children:[(0,Q.jsx)(`div`,{className:X(`w-16 h-16 flex-shrink-0 border flex items-center justify-center overflow-hidden`,r?`bg-app/80 border-z-border`:`bg-[var(--z-bg-hover)] border-z-border`),children:a?(0,Q.jsx)(`img`,{src:a,alt:i,className:`w-full h-full object-contain`,onError:e=>{e.target.style.display=`none`}}):(0,Q.jsx)(c,{size:20,className:`text-z-secondary`})}),(0,Q.jsxs)(`div`,{className:`flex-1 space-y-2`,children:[(0,Q.jsx)(`input`,{type:`url`,value:a||``,onChange:r=>t({...e,[n]:r.target.value}),placeholder:`https://...`,className:y}),(0,Q.jsxs)(`label`,{className:X(`flex items-center gap-2 cursor-pointer text-sm font-semibold border px-3 py-2 w-fit transition-all`,r?`border-z-border text-z-muted hover:text-z-primary hover:border-z-border`:`border-z-border text-z-secondary hover:text-z-primary`),children:[o?(0,Q.jsx)(S,{size:12,className:`animate-spin`}):(0,Q.jsx)(ke,{size:12}),`Upload File`,(0,Q.jsx)(`input`,{type:`file`,accept:`image/*`,className:`hidden`,onChange:e=>{let t=e.target.files?.[0];t&&g(t,n,s)}})]})]})]})]});return(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsxs)(`div`,{className:X(`p-5 border space-y-3`,r?`bg-z-panel backdrop-blur-md border-z-border shadow-sm`:`bg-z-input border-z-border`),children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(K,{size:12,className:`text-z-secondary`}),(0,Q.jsx)(`span`,{className:`text-sm font-semibold text-z-secondary`,children:`Site Identifier`}),(0,Q.jsx)(`span`,{className:`ml-auto text-sm text-z-secondary`,children:m})]}),(0,Q.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,Q.jsx)(`code`,{className:X(`flex-1 font-mono text-sm px-3 py-2 border truncate`,`bg-z-panel border-z-border text-z-primary`),children:p||(0,Q.jsx)(`span`,{className:`opacity-40`,children:`No site selected`})}),(0,Q.jsxs)(`button`,{onClick:h,disabled:!p,className:X(`flex items-center gap-2 px-4 py-2 text-xs font-bold border transition-all`,p?r?`bg-z-accent hover:brightness-110 text-z-logo-text border-transparent shadow-sm`:`bg-z-base text-z-primary border-transparent hover:bg-z-base`:`bg-z-hover text-z-secondary cursor-not-allowed border-z-border`),children:[i?(0,Q.jsx)(U,{size:13}):(0,Q.jsx)(v,{size:13}),i?`Copied!`:`Copy`]})]}),(0,Q.jsxs)(`p`,{className:X(`text-sm leading-relaxed`,`text-z-secondary`),children:[`Use this as `,(0,Q.jsx)(`code`,{className:`px-1 py-0.5 bg-z-panel/10`,children:`VITE_CMS_SITE_ID`}),` in template `,(0,Q.jsx)(`code`,{className:`px-1 py-0.5 bg-z-panel/10`,children:`.env`}),` files to connect storefronts to this site.`]})]}),(0,Q.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Application Name`}),(0,Q.jsx)(`input`,{type:`text`,value:e.siteName||``,onChange:n=>t({...e,siteName:n.target.value}),className:y,placeholder:`My CMS`})]}),(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Support Email`}),(0,Q.jsx)(`input`,{type:`email`,value:e.supportEmail||``,onChange:n=>t({...e,supportEmail:n.target.value}),className:y,placeholder:`support@company.com`})]})]}),(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Site Description`}),(0,Q.jsx)(`textarea`,{value:e.siteDescription||``,onChange:n=>t({...e,siteDescription:n.target.value}),rows:3,className:X(y,`resize-none`),placeholder:`A short description of your platform...`})]}),(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Public API Endpoint`}),(0,Q.jsx)(`input`,{type:`url`,value:e.publicUrl||``,onChange:n=>t({...e,publicUrl:n.target.value}),className:y,placeholder:`https://api.yoursite.com`}),(0,Q.jsx)(`p`,{className:`text-sm text-z-secondary`,children:`The publicly-accessible URL where your CMS API is hosted.`})]}),(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary px-1`,children:`Branding Assets`}),(0,Q.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-4`,children:[(0,Q.jsx)(b,{field:`logoUrl`,label:`Site Logo`,value:e.logoUrl,uploading:o,setUploading:s}),(0,Q.jsx)(b,{field:`faviconUrl`,label:`Favicon`,value:e.faviconUrl,uploading:l,setUploading:u}),(0,Q.jsx)(b,{field:`ogImageUrl`,label:`OG Share Image`,value:e.ogImageUrl||``,uploading:d,setUploading:f})]})]}),(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary px-1`,children:`Localization`}),(0,Q.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-4`,children:[(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Default Locale`}),(0,Q.jsx)(`select`,{value:e.defaultLocale||`en`,onChange:n=>t({...e,defaultLocale:n.target.value}),className:y,children:Ke.map(e=>(0,Q.jsx)(`option`,{value:e.value,children:e.label},e.value))})]}),(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Timezone`}),(0,Q.jsx)(`select`,{value:e.timezone||`UTC`,onChange:n=>t({...e,timezone:n.target.value}),className:y,children:Ge.map(e=>(0,Q.jsx)(`option`,{value:e,children:e},e))})]}),(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Date Format`}),(0,Q.jsx)(`select`,{value:e.dateFormat||`MM/DD/YYYY`,onChange:n=>t({...e,dateFormat:n.target.value}),className:y,children:[`MM/DD/YYYY`,`DD/MM/YYYY`,`YYYY-MM-DD`,`MMMM D, YYYY`,`D MMMM YYYY`].map(e=>(0,Q.jsx)(`option`,{value:e,children:e},e))})]})]})]}),(0,Q.jsxs)(`div`,{className:X(`p-5 border flex items-center justify-between transition-all group rounded-lg`,e.maintenanceMode?r?`bg-red-950/20 border-red-900/50 shadow-[0_0_15px_rgba(220,38,38,0.15)]`:`bg-red-50 border-red-200 shadow-sm`:r?`bg-z-panel backdrop-blur-md border-z-border shadow-sm`:`bg-[var(--z-bg-input)]/50 border-z-border shadow-sm`),children:[(0,Q.jsxs)(`div`,{children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`span`,{className:X(`text-sm font-bold`,e.maintenanceMode?`text-red-500`:`text-z-primary`),children:`Maintenance Protocol`}),e.maintenanceMode&&(0,Q.jsx)(`span`,{className:`px-2 py-0.5 rounded text-[10px] font-bold uppercase tracking-wider bg-red-500 text-white animate-pulse`,children:`Active`})]}),(0,Q.jsx)(`p`,{className:X(`text-sm mt-1`,e.maintenanceMode?`text-red-500/80`:`text-z-secondary`),children:`Restrict public access to the system while active. Admins can still log in.`})]}),(0,Q.jsxs)(`label`,{className:`relative inline-flex items-center cursor-pointer flex-shrink-0`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:e.maintenanceMode,onChange:n=>t({...e,maintenanceMode:n.target.checked}),className:`sr-only peer`}),(0,Q.jsx)(`div`,{className:X(`w-11 h-6 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all shadow-inner`,r?`bg-gray-700 peer-checked:bg-red-600`:`bg-gray-300 peer-checked:bg-red-500`)})]})]}),(0,Q.jsxs)(`div`,{className:`pt-6 mt-6 border-t border-red-900/30`,children:[(0,Q.jsx)(`h4`,{className:`text-sm font-bold text-red-500 uppercase tracking-wider mb-4`,children:`Danger Zone`}),(0,Q.jsxs)(`div`,{className:X(`p-5 border flex items-center justify-between transition-all border-red-500/20`,r?`bg-red-950/10`:`bg-red-50`),children:[(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`span`,{className:`text-sm font-semibold text-red-500`,children:`Delete Site Workspace`}),(0,Q.jsx)(`p`,{className:`text-sm text-red-400/80 mt-1`,children:`Permanently delete this site and all its content, media, and configurations. This action cannot be undone.`})]}),(0,Q.jsx)(`button`,{onClick:()=>{window.confirm(`Are you absolutely sure you want to permanently delete this site? This action cannot be undone.`)&&Y.delete(`/sites/${p}`).then(()=>{J.success(`Site deleted`),window.location.href=`/`}).catch(e=>{J.error(e.response?.data?.error?.message||`Failed to delete site`)})},className:`px-4 py-2 border border-red-500 text-red-500 hover:bg-red-500 hover:text-z-logo-text transition-colors text-sm font-medium`,children:`Delete Site`})]})]})]})},Je=({settings:e,setSettings:r,theme:i})=>{let a=i===`dark`,{user:o}=Le(me(e=>({user:e.user}))),[s,c]=(0,Z.useState)(`idle`),[l,u]=(0,Z.useState)(null),[f,p]=(0,Z.useState)(``),[m,v]=(0,Z.useState)(!1),[y,b]=(0,Z.useState)(o?.twoFactorEnabled||!1),[C,w]=(0,Z.useState)(!1),[E,D]=(0,Z.useState)([]),[O,k]=(0,Z.useState)(!1),[A,j]=(0,Z.useState)(null),M=async()=>{k(!0);try{let e=await Y.get(`/auth/sessions`),t=e.data?.data||e.data;D(Array.isArray(t)?t:[])}catch{D([])}finally{k(!1)}};(0,Z.useEffect)(()=>{M()},[]);let P=async()=>{c(`loading`);try{u((await Y.post(`/auth/2fa/setup`)).data.data.qrCodeImage),c(`qrcode`)}catch{J.error(`Failed to initiate 2FA setup`),c(`idle`)}},F=async()=>{if(!f)return J.error(`Enter the 6-digit code`);v(!0);try{await Y.post(`/auth/2fa/verify-setup`,{token:f}),J.success(`2FA successfully enabled`),b(!0),c(`idle`)}catch{J.error(`Invalid token`)}finally{v(!1)}},I=async e=>{j(e);try{await Y.delete(`/auth/sessions/${e}`),D(t=>t.filter(t=>t.id!==e)),J.success(`Session revoked`)}catch{J.error(`Failed to revoke session`)}finally{j(null)}},L=X(`p-5 border rounded-none transition-all space-y-3`,a?`bg-z-panel backdrop-blur-md border-z-border shadow-sm`:`bg-[var(--z-bg-input)]/50 border-z-border shadow-sm`),R=X(`w-full border rounded-none py-2.5 px-4 text-sm font-mono outline-none transition-all focus:ring-1 focus:ring-z-active-border focus:border-z-accent`,a?`bg-app/80 border-z-border text-z-primary placeholder:text-z-primary`:`bg-z-panel border-z-border`);return(0,Q.jsxs)(`div`,{className:`space-y-5`,children:[(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary px-1`,children:`Authentication`}),(0,Q.jsxs)(`div`,{className:X(`border rounded-none divide-y`,`border-z-border divide-z-border`),children:[(0,Q.jsxs)(`div`,{className:X(`flex items-center justify-between p-5`,a?`bg-z-panel backdrop-blur-md`:`bg-z-panel`),children:[(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`p`,{className:X(`text-sm font-semibold `,`text-z-primary`),children:`Open Registration`}),(0,Q.jsx)(`p`,{className:`text-sm text-z-secondary mt-1`,children:`Allow anyone to sign up. When off, users must be explicitly invited.`})]}),(0,Q.jsx)(({checked:e,onChange:t})=>(0,Q.jsxs)(`label`,{className:`relative inline-flex items-center cursor-pointer flex-shrink-0`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:e,onChange:e=>t(e.target.checked),className:`sr-only peer`}),(0,Q.jsx)(`div`,{className:X(`w-11 h-6 rounded-none peer peer-checked:after:translate-x-full after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-[var(--z-bg-hover)] after:rounded-none after:h-5 after:w-5 after:transition-all border shadow-inner`,`bg-[var(--z-border-strong)] peer-checked:bg-z-accent border-transparent`)})]}),{checked:e.allowRegistration,onChange:t=>r({...e,allowRegistration:t})})]}),(0,Q.jsxs)(`div`,{className:`p-5 space-y-2`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(t,{size:13,className:`text-z-secondary`}),(0,Q.jsx)(`label`,{className:X(`text-sm font-semibold `,`text-z-primary`),children:`Session Token Lifetime`})]}),(0,Q.jsxs)(`div`,{className:`flex gap-2`,children:[[`1h`,`12h`,`24h`,`7d`,`30d`].map(t=>(0,Q.jsx)(`button`,{onClick:()=>r({...e,jwtExpiresIn:t}),className:X(`px-3 py-2 text-sm font-semibold border transition-all`,e.jwtExpiresIn===t?a?`bg-z-accent/20 border-z-active-border text-z-active-text`:`bg-z-active-bg border-z-active-border text-z-accent`:a?`bg-z-hover border-z-border text-z-secondary hover:text-z-secondary`:`bg-z-input border-z-border text-z-secondary`),children:t},t)),(0,Q.jsx)(`input`,{type:`text`,value:e.jwtExpiresIn,onChange:t=>r({...e,jwtExpiresIn:t.target.value}),placeholder:`Custom (e.g. 2d)`,className:X(R,`max-w-32 py-2`)})]}),(0,Q.jsx)(`p`,{className:`text-sm text-z-secondary`,children:`Format: 1h, 7d, 30m etc. Tokens will expire after this duration.`})]}),(0,Q.jsxs)(`div`,{className:`p-5 space-y-2`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(ge,{size:13,className:`text-z-secondary`}),(0,Q.jsx)(`label`,{className:X(`text-sm font-semibold `,`text-z-primary`),children:`Minimum Password Length`})]}),(0,Q.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,Q.jsx)(`input`,{type:`range`,min:6,max:32,value:e.passwordMinLength||8,onChange:t=>r({...e,passwordMinLength:Number(t.target.value)}),className:`flex-1 accent-z-accent`}),(0,Q.jsx)(`span`,{className:X(`text-lg font-semibold min-w-[3ch] text-right`,a?`text-z-active-text`:`text-z-accent`),children:e.passwordMinLength||8})]})]})]})]}),(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary px-1`,children:`Rate Limiting`}),(0,Q.jsxs)(`div`,{className:X(`border rounded-none`,`z-panel`),children:[(0,Q.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 p-5`,children:[(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Window (minutes)`}),(0,Q.jsx)(`input`,{type:`number`,value:e.rateLimitWindow||15,onChange:t=>r({...e,rateLimitWindow:parseInt(t.target.value)||15}),className:R,placeholder:`15`})]}),(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Max Requests / Window`}),(0,Q.jsx)(`input`,{type:`number`,value:e.rateLimitMax||100,onChange:t=>r({...e,rateLimitMax:parseInt(t.target.value)||100}),className:R,placeholder:`100`})]})]}),(0,Q.jsxs)(`div`,{className:X(`px-5 pb-4 text-sm text-z-secondary flex items-center gap-2 border-t`,`border-z-border`),children:[(0,Q.jsx)(N,{size:11,className:`text-z-active-text mt-0.5 shrink-0`}),(0,Q.jsxs)(`p`,{className:`mt-3`,children:[`Requests exceeding `,e.rateLimitMax||100,` per `,e.rateLimitWindow||15,` minutes will receive a 429 Too Many Requests error. Applies per IP address.`]})]})]})]}),(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary px-1`,children:`CORS & Origins`}),(0,Q.jsxs)(`div`,{className:X(L),children:[(0,Q.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(T,{size:13,className:`text-z-secondary`}),(0,Q.jsx)(`label`,{className:X(`text-sm font-semibold `,`text-z-primary`),children:`Allowed Origins`})]}),(0,Q.jsx)(`button`,{onClick:()=>w(!C),className:`text-sm text-z-active-text hover:text-z-active-text font-semibold`,children:C?`Collapse`:`Configure`})]}),C&&(0,Q.jsxs)(`div`,{className:`space-y-2 pt-2`,children:[(0,Q.jsx)(`textarea`,{value:(e.corsOrigins||[]).join(`
|
|
1
|
+
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{$t as t,B as n,Bt as r,C as i,Cn as a,E as o,En as s,Et as c,F as l,G as u,Gn as d,H as f,Hn as p,Ht as m,I as h,J as g,Jn as _,Jt as v,K as y,Kt as b,L as x,Ln as S,Lt as C,Mn as w,Mt as T,Pn as E,Q as D,R as O,Rn as k,S as A,St as j,T as M,Tt as N,U as P,Ut as F,V as I,Vt as L,W as R,Wt as z,Yt as B,Z as V,Zn as ee,_ as te,an as H,br as ne,cn as U,d as W,dt as re,et as ie,g as G,gt as K,h as q,hn as ae,in as oe,ir as se,it as ce,j as le,kt as ue,l as J,m as de,mn as fe,nt as pe,o as me,pr as he,pt as ge,qn as _e,rr as ve,sn as ye,tt as be,u as xe,un as Se,v as Ce,vr as we,w as Te,wn as Ee,x as De,xr as Oe,y as ke}from"./vendor-react-DQVTOTFO.js";import{a as Ae,o as Y,s as je,t as X}from"./utils-fgvbH6CB.js";import{_ as Me,g as Ne,h as Pe,m as Fe,p as Ie,y as Le}from"./index-yE_3fruG.js";import Re from"./ApiExplorerPage-85UWt1EW.js";import{t as ze}from"./EmptyState-X_SXKpQY.js";var Z=e(Oe(),1),Be={view:`viewer`,create:`editor`,edit:`editor`,publish:`editor`,unpublish:`editor`,delete:`editor`,view_audit_log:`editor`,manage_redirects:`editor`,manage_schema:`admin`,manage_settings:`admin`,manage_plugins:`admin`,manage_users:`admin`,manage_api_keys:`admin`,download_backup:`admin`},Ve={viewer:0,editor:1,admin:2};function He(e,t){if(!e)return!1;let n=Ve[Be[t]]??999;return(Ve[e]??-1)>=n}function Ue(){let e=Le(e=>e.user)?.role??`viewer`;return{role:e,can:t=>He(e,t),isAdmin:e===`admin`,isEditor:Ve[e]>=Ve.editor}}var Q=we();function We({children:e,sidebar:t,sidebarPosition:n=`right`,sidebarWidth:r=`w-[320px]`,className:i,...a}){let{theme:o}=Ae();return(0,Q.jsxs)(`div`,{className:X(`flex flex-col lg:flex-row h-full min-h-[calc(100vh-65px)]`,i),...a,children:[n===`left`&&t&&(0,Q.jsx)(`div`,{className:X(`shrink-0 border-b lg:border-b-0 lg:border-r flex flex-col`,r,o===`dark`?`border-z-border bg-[#050505]`:`border-z-border bg-[var(--z-bg-input)]/30`),children:t}),(0,Q.jsx)(`div`,{className:`flex-1 flex flex-col min-w-0`,children:e}),n===`right`&&t&&(0,Q.jsx)(`div`,{className:X(`shrink-0 border-t lg:border-t-0 lg:border-l flex flex-col`,r,o===`dark`?`border-z-border bg-[#050505]`:`border-z-border bg-[var(--z-bg-input)]/30`),children:t})]})}var Ge=`UTC.America/New_York.America/Chicago.America/Denver.America/Los_Angeles.America/Anchorage.America/Honolulu.America/Sao_Paulo.America/Toronto.America/Vancouver.Europe/London.Europe/Paris.Europe/Berlin.Europe/Amsterdam.Europe/Rome.Europe/Madrid.Europe/Stockholm.Europe/Athens.Europe/Warsaw.Europe/Prague.Asia/Dubai.Asia/Kolkata.Asia/Singapore.Asia/Tokyo.Asia/Shanghai.Asia/Seoul.Asia/Bangkok.Asia/Jakarta.Asia/Karachi.Asia/Tehran.Africa/Cairo.Africa/Lagos.Africa/Johannesburg.Africa/Nairobi.Australia/Sydney.Australia/Melbourne.Pacific/Auckland`.split(`.`),Ke=[{value:`en`,label:`English (en)`},{value:`en-US`,label:`English US (en-US)`},{value:`en-GB`,label:`English UK (en-GB)`},{value:`fr`,label:`French (fr)`},{value:`de`,label:`German (de)`},{value:`es`,label:`Spanish (es)`},{value:`it`,label:`Italian (it)`},{value:`pt`,label:`Portuguese (pt)`},{value:`ar`,label:`Arabic (ar)`},{value:`zh`,label:`Chinese (zh)`},{value:`ja`,label:`Japanese (ja)`},{value:`ko`,label:`Korean (ko)`},{value:`hi`,label:`Hindi (hi)`},{value:`ru`,label:`Russian (ru)`},{value:`nl`,label:`Dutch (nl)`},{value:`pl`,label:`Polish (pl)`},{value:`tr`,label:`Turkish (tr)`}],qe=({settings:e,setSettings:t,theme:n})=>{let r=n===`dark`,[i,a]=(0,Z.useState)(!1),[o,s]=(0,Z.useState)(!1),[l,u]=(0,Z.useState)(!1),[d,f]=(0,Z.useState)(!1),p=localStorage.getItem(`activeSiteId`)||``,m=localStorage.getItem(`activeSiteName`)||`Unknown Site`,h=()=>{p&&navigator.clipboard.writeText(p).then(()=>{a(!0),setTimeout(()=>a(!1),2e3)})},g=async(n,r,i)=>{i(!0);try{let i=new FormData;i.append(`file`,n);let a=await Y.post(`/upload`,i,{headers:{"Content-Type":`multipart/form-data`}}),o=a.data?.data?.url||a.data?.url;o&&(t({...e,[r]:o}),J.success(`Image uploaded`))}catch{J.error(`Upload failed`)}finally{i(!1)}},_=X(`p-5 border rounded-none transition-all space-y-3`,r?`bg-z-panel backdrop-blur-md border-z-border shadow-sm`:`bg-[var(--z-bg-input)]/50 border-z-border shadow-sm`),y=X(`w-full border rounded-none py-2.5 px-4 text-sm transition-all outline-none focus:ring-1 focus:ring-z-active-border focus:border-z-accent`,r?`bg-app/80 border-z-border text-z-primary placeholder:text-z-primary`:`bg-z-panel border-z-border`),b=({field:n,label:i,value:a,uploading:o,setUploading:s})=>(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:i}),(0,Q.jsxs)(`div`,{className:`flex gap-3 items-start`,children:[(0,Q.jsx)(`div`,{className:X(`w-16 h-16 flex-shrink-0 border flex items-center justify-center overflow-hidden`,r?`bg-app/80 border-z-border`:`bg-[var(--z-bg-hover)] border-z-border`),children:a?(0,Q.jsx)(`img`,{src:a,alt:i,className:`w-full h-full object-contain`,onError:e=>{e.target.style.display=`none`}}):(0,Q.jsx)(c,{size:20,className:`text-z-secondary`})}),(0,Q.jsxs)(`div`,{className:`flex-1 space-y-2`,children:[(0,Q.jsx)(`input`,{type:`url`,value:a||``,onChange:r=>t({...e,[n]:r.target.value}),placeholder:`https://...`,className:y}),(0,Q.jsxs)(`label`,{className:X(`flex items-center gap-2 cursor-pointer text-sm font-semibold border px-3 py-2 w-fit transition-all`,r?`border-z-border text-z-muted hover:text-z-primary hover:border-z-border`:`border-z-border text-z-secondary hover:text-z-primary`),children:[o?(0,Q.jsx)(S,{size:12,className:`animate-spin`}):(0,Q.jsx)(ke,{size:12}),`Upload File`,(0,Q.jsx)(`input`,{type:`file`,accept:`image/*`,className:`hidden`,onChange:e=>{let t=e.target.files?.[0];t&&g(t,n,s)}})]})]})]})]});return(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsxs)(`div`,{className:X(`p-5 border space-y-3`,r?`bg-z-panel backdrop-blur-md border-z-border shadow-sm`:`bg-z-input border-z-border`),children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(K,{size:12,className:`text-z-secondary`}),(0,Q.jsx)(`span`,{className:`text-sm font-semibold text-z-secondary`,children:`Site Identifier`}),(0,Q.jsx)(`span`,{className:`ml-auto text-sm text-z-secondary`,children:m})]}),(0,Q.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,Q.jsx)(`code`,{className:X(`flex-1 font-mono text-sm px-3 py-2 border truncate`,`bg-z-panel border-z-border text-z-primary`),children:p||(0,Q.jsx)(`span`,{className:`opacity-40`,children:`No site selected`})}),(0,Q.jsxs)(`button`,{onClick:h,disabled:!p,className:X(`flex items-center gap-2 px-4 py-2 text-xs font-bold border transition-all`,p?r?`bg-z-accent hover:brightness-110 text-z-logo-text border-transparent shadow-sm`:`bg-z-base text-z-primary border-transparent hover:bg-z-base`:`bg-z-hover text-z-secondary cursor-not-allowed border-z-border`),children:[i?(0,Q.jsx)(U,{size:13}):(0,Q.jsx)(v,{size:13}),i?`Copied!`:`Copy`]})]}),(0,Q.jsxs)(`p`,{className:X(`text-sm leading-relaxed`,`text-z-secondary`),children:[`Use this as `,(0,Q.jsx)(`code`,{className:`px-1 py-0.5 bg-z-panel/10`,children:`VITE_CMS_SITE_ID`}),` in template `,(0,Q.jsx)(`code`,{className:`px-1 py-0.5 bg-z-panel/10`,children:`.env`}),` files to connect storefronts to this site.`]})]}),(0,Q.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Application Name`}),(0,Q.jsx)(`input`,{type:`text`,value:e.siteName||``,onChange:n=>t({...e,siteName:n.target.value}),className:y,placeholder:`My CMS`})]}),(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Support Email`}),(0,Q.jsx)(`input`,{type:`email`,value:e.supportEmail||``,onChange:n=>t({...e,supportEmail:n.target.value}),className:y,placeholder:`support@company.com`})]})]}),(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Site Description`}),(0,Q.jsx)(`textarea`,{value:e.siteDescription||``,onChange:n=>t({...e,siteDescription:n.target.value}),rows:3,className:X(y,`resize-none`),placeholder:`A short description of your platform...`})]}),(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Public API Endpoint`}),(0,Q.jsx)(`input`,{type:`url`,value:e.publicUrl||``,onChange:n=>t({...e,publicUrl:n.target.value}),className:y,placeholder:`https://api.yoursite.com`}),(0,Q.jsx)(`p`,{className:`text-sm text-z-secondary`,children:`The publicly-accessible URL where your CMS API is hosted.`})]}),(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary px-1`,children:`Branding Assets`}),(0,Q.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-4`,children:[(0,Q.jsx)(b,{field:`logoUrl`,label:`Site Logo`,value:e.logoUrl,uploading:o,setUploading:s}),(0,Q.jsx)(b,{field:`faviconUrl`,label:`Favicon`,value:e.faviconUrl,uploading:l,setUploading:u}),(0,Q.jsx)(b,{field:`ogImageUrl`,label:`OG Share Image`,value:e.ogImageUrl||``,uploading:d,setUploading:f})]})]}),(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary px-1`,children:`Localization`}),(0,Q.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-4`,children:[(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Default Locale`}),(0,Q.jsx)(`select`,{value:e.defaultLocale||`en`,onChange:n=>t({...e,defaultLocale:n.target.value}),className:y,children:Ke.map(e=>(0,Q.jsx)(`option`,{value:e.value,children:e.label},e.value))})]}),(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Timezone`}),(0,Q.jsx)(`select`,{value:e.timezone||`UTC`,onChange:n=>t({...e,timezone:n.target.value}),className:y,children:Ge.map(e=>(0,Q.jsx)(`option`,{value:e,children:e},e))})]}),(0,Q.jsxs)(`div`,{className:_,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Date Format`}),(0,Q.jsx)(`select`,{value:e.dateFormat||`MM/DD/YYYY`,onChange:n=>t({...e,dateFormat:n.target.value}),className:y,children:[`MM/DD/YYYY`,`DD/MM/YYYY`,`YYYY-MM-DD`,`MMMM D, YYYY`,`D MMMM YYYY`].map(e=>(0,Q.jsx)(`option`,{value:e,children:e},e))})]})]})]}),(0,Q.jsxs)(`div`,{className:X(`p-5 border flex items-center justify-between transition-all group rounded-lg`,e.maintenanceMode?r?`bg-red-950/20 border-red-900/50 shadow-[0_0_15px_rgba(220,38,38,0.15)]`:`bg-red-50 border-red-200 shadow-sm`:r?`bg-z-panel backdrop-blur-md border-z-border shadow-sm`:`bg-[var(--z-bg-input)]/50 border-z-border shadow-sm`),children:[(0,Q.jsxs)(`div`,{children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`span`,{className:X(`text-sm font-bold`,e.maintenanceMode?`text-red-500`:`text-z-primary`),children:`Maintenance Protocol`}),e.maintenanceMode&&(0,Q.jsx)(`span`,{className:`px-2 py-0.5 rounded text-[10px] font-bold uppercase tracking-wider bg-red-500 text-white animate-pulse`,children:`Active`})]}),(0,Q.jsx)(`p`,{className:X(`text-sm mt-1`,e.maintenanceMode?`text-red-500/80`:`text-z-secondary`),children:`Restrict public access to the system while active. Admins can still log in.`})]}),(0,Q.jsxs)(`label`,{className:`relative inline-flex items-center cursor-pointer flex-shrink-0`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:e.maintenanceMode,onChange:n=>t({...e,maintenanceMode:n.target.checked}),className:`sr-only peer`}),(0,Q.jsx)(`div`,{className:X(`w-11 h-6 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all shadow-inner`,r?`bg-gray-700 peer-checked:bg-red-600`:`bg-gray-300 peer-checked:bg-red-500`)})]})]}),(0,Q.jsxs)(`div`,{className:`pt-6 mt-6 border-t border-red-900/30`,children:[(0,Q.jsx)(`h4`,{className:`text-sm font-bold text-red-500 uppercase tracking-wider mb-4`,children:`Danger Zone`}),(0,Q.jsxs)(`div`,{className:X(`p-5 border flex items-center justify-between transition-all border-red-500/20`,r?`bg-red-950/10`:`bg-red-50`),children:[(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`span`,{className:`text-sm font-semibold text-red-500`,children:`Delete Site Workspace`}),(0,Q.jsx)(`p`,{className:`text-sm text-red-400/80 mt-1`,children:`Permanently delete this site and all its content, media, and configurations. This action cannot be undone.`})]}),(0,Q.jsx)(`button`,{onClick:()=>{window.confirm(`Are you absolutely sure you want to permanently delete this site? This action cannot be undone.`)&&Y.delete(`/sites/${p}`).then(()=>{J.success(`Site deleted`),window.location.href=`/`}).catch(e=>{J.error(e.response?.data?.error?.message||`Failed to delete site`)})},className:`px-4 py-2 border border-red-500 text-red-500 hover:bg-red-500 hover:text-z-logo-text transition-colors text-sm font-medium`,children:`Delete Site`})]})]})]})},Je=({settings:e,setSettings:r,theme:i})=>{let a=i===`dark`,{user:o}=Le(me(e=>({user:e.user}))),[s,c]=(0,Z.useState)(`idle`),[l,u]=(0,Z.useState)(null),[f,p]=(0,Z.useState)(``),[m,v]=(0,Z.useState)(!1),[y,b]=(0,Z.useState)(o?.twoFactorEnabled||!1),[C,w]=(0,Z.useState)(!1),[E,D]=(0,Z.useState)([]),[O,k]=(0,Z.useState)(!1),[A,j]=(0,Z.useState)(null),M=async()=>{k(!0);try{let e=await Y.get(`/auth/sessions`),t=e.data?.data||e.data;D(Array.isArray(t)?t:[])}catch{D([])}finally{k(!1)}};(0,Z.useEffect)(()=>{M()},[]);let P=async()=>{c(`loading`);try{u((await Y.post(`/auth/2fa/setup`)).data.data.qrCodeImage),c(`qrcode`)}catch{J.error(`Failed to initiate 2FA setup`),c(`idle`)}},F=async()=>{if(!f)return J.error(`Enter the 6-digit code`);v(!0);try{await Y.post(`/auth/2fa/verify-setup`,{token:f}),J.success(`2FA successfully enabled`),b(!0),c(`idle`)}catch{J.error(`Invalid token`)}finally{v(!1)}},I=async e=>{j(e);try{await Y.delete(`/auth/sessions/${e}`),D(t=>t.filter(t=>t.id!==e)),J.success(`Session revoked`)}catch{J.error(`Failed to revoke session`)}finally{j(null)}},L=X(`p-5 border rounded-none transition-all space-y-3`,a?`bg-z-panel backdrop-blur-md border-z-border shadow-sm`:`bg-[var(--z-bg-input)]/50 border-z-border shadow-sm`),R=X(`w-full border rounded-none py-2.5 px-4 text-sm font-mono outline-none transition-all focus:ring-1 focus:ring-z-active-border focus:border-z-accent`,a?`bg-app/80 border-z-border text-z-primary placeholder:text-z-primary`:`bg-z-panel border-z-border`);return(0,Q.jsxs)(`div`,{className:`space-y-5`,children:[(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary px-1`,children:`Authentication`}),(0,Q.jsxs)(`div`,{className:X(`border rounded-none divide-y`,`border-z-border divide-z-border`),children:[(0,Q.jsxs)(`div`,{className:X(`flex items-center justify-between p-5`,a?`bg-z-panel backdrop-blur-md`:`bg-z-panel`),children:[(0,Q.jsxs)(`div`,{children:[(0,Q.jsx)(`p`,{className:X(`text-sm font-semibold `,`text-z-primary`),children:`Open Registration`}),(0,Q.jsx)(`p`,{className:`text-sm text-z-secondary mt-1`,children:`Allow anyone to sign up. When off, users must be explicitly invited.`})]}),(0,Q.jsx)(({checked:e,onChange:t})=>(0,Q.jsxs)(`label`,{className:`relative inline-flex items-center cursor-pointer flex-shrink-0`,children:[(0,Q.jsx)(`input`,{type:`checkbox`,checked:e,onChange:e=>t(e.target.checked),className:`sr-only peer`}),(0,Q.jsx)(`div`,{className:X(`w-11 h-6 rounded-none peer peer-checked:after:translate-x-full after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-[var(--z-bg-hover)] after:rounded-none after:h-5 after:w-5 after:transition-all border shadow-inner`,`bg-[var(--z-border-strong)] peer-checked:bg-z-accent border-transparent`)})]}),{checked:e.allowRegistration,onChange:t=>r({...e,allowRegistration:t})})]}),(0,Q.jsxs)(`div`,{className:`p-5 space-y-2`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(t,{size:13,className:`text-z-secondary`}),(0,Q.jsx)(`label`,{className:X(`text-sm font-semibold `,`text-z-primary`),children:`Session Token Lifetime`})]}),(0,Q.jsxs)(`div`,{className:`flex gap-2`,children:[[`1h`,`12h`,`24h`,`7d`,`30d`].map(t=>(0,Q.jsx)(`button`,{onClick:()=>r({...e,jwtExpiresIn:t}),className:X(`px-3 py-2 text-sm font-semibold border transition-all`,e.jwtExpiresIn===t?a?`bg-z-accent/20 border-z-active-border text-z-active-text`:`bg-z-active-bg border-z-active-border text-z-accent`:a?`bg-z-hover border-z-border text-z-secondary hover:text-z-secondary`:`bg-z-input border-z-border text-z-secondary`),children:t},t)),(0,Q.jsx)(`input`,{type:`text`,value:e.jwtExpiresIn,onChange:t=>r({...e,jwtExpiresIn:t.target.value}),placeholder:`Custom (e.g. 2d)`,className:X(R,`max-w-32 py-2`)})]}),(0,Q.jsx)(`p`,{className:`text-sm text-z-secondary`,children:`Format: 1h, 7d, 30m etc. Tokens will expire after this duration.`})]}),(0,Q.jsxs)(`div`,{className:`p-5 space-y-2`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(ge,{size:13,className:`text-z-secondary`}),(0,Q.jsx)(`label`,{className:X(`text-sm font-semibold `,`text-z-primary`),children:`Minimum Password Length`})]}),(0,Q.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,Q.jsx)(`input`,{type:`range`,min:6,max:32,value:e.passwordMinLength||8,onChange:t=>r({...e,passwordMinLength:Number(t.target.value)}),className:`flex-1 accent-z-accent`}),(0,Q.jsx)(`span`,{className:X(`text-lg font-semibold min-w-[3ch] text-right`,a?`text-z-active-text`:`text-z-accent`),children:e.passwordMinLength||8})]})]})]})]}),(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary px-1`,children:`Rate Limiting`}),(0,Q.jsxs)(`div`,{className:X(`border rounded-none`,`z-panel`),children:[(0,Q.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 p-5`,children:[(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Window (minutes)`}),(0,Q.jsx)(`input`,{type:`number`,value:e.rateLimitWindow||15,onChange:t=>r({...e,rateLimitWindow:parseInt(t.target.value)||15}),className:R,placeholder:`15`})]}),(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary`,children:`Max Requests / Window`}),(0,Q.jsx)(`input`,{type:`number`,value:e.rateLimitMax||100,onChange:t=>r({...e,rateLimitMax:parseInt(t.target.value)||100}),className:R,placeholder:`100`})]})]}),(0,Q.jsxs)(`div`,{className:X(`px-5 pb-4 text-sm text-z-secondary flex items-center gap-2 border-t`,`border-z-border`),children:[(0,Q.jsx)(N,{size:11,className:`text-z-active-text mt-0.5 shrink-0`}),(0,Q.jsxs)(`p`,{className:`mt-3`,children:[`Requests exceeding `,e.rateLimitMax||100,` per `,e.rateLimitWindow||15,` minutes will receive a 429 Too Many Requests error. Applies per IP address.`]})]})]})]}),(0,Q.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,Q.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary px-1`,children:`CORS & Origins`}),(0,Q.jsxs)(`div`,{className:X(L),children:[(0,Q.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(T,{size:13,className:`text-z-secondary`}),(0,Q.jsx)(`label`,{className:X(`text-sm font-semibold `,`text-z-primary`),children:`Allowed Origins`})]}),(0,Q.jsx)(`button`,{onClick:()=>w(!C),className:`text-sm text-z-active-text hover:text-z-active-text font-semibold`,children:C?`Collapse`:`Configure`})]}),C&&(0,Q.jsxs)(`div`,{className:`space-y-2 pt-2`,children:[(0,Q.jsx)(`textarea`,{value:(e.corsOrigins||[]).join(`
|
|
2
2
|
`),onChange:t=>r({...e,corsOrigins:t.target.value.split(`
|
|
3
3
|
`).map(e=>e.trim()).filter(Boolean)}),rows:4,placeholder:`https://yoursite.com
|
|
4
4
|
https://app.yoursite.com
|