@zenith-open/zenithcms-admin 1.0.0-beta.5 → 1.0.0-beta.9
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-CLsHG-Ke.js → ApiExplorerPage-85UWt1EW.js} +1 -1
- package/dist/assets/{ApiExplorerPage-CLsHG-Ke.js.map → ApiExplorerPage-85UWt1EW.js.map} +1 -1
- package/dist/assets/{AuditLogPage-Bp2Nvabr.js → AuditLogPage-CwULx1tr.js} +1 -1
- package/dist/assets/{AuditLogPage-Bp2Nvabr.js.map → AuditLogPage-CwULx1tr.js.map} +1 -1
- package/dist/assets/{BlockBuilderPage-CeVMk5Ns.js → BlockBuilderPage-XD1IjOgx.js} +1 -1
- package/dist/assets/{BlockBuilderPage-CeVMk5Ns.js.map → BlockBuilderPage-XD1IjOgx.js.map} +1 -1
- package/dist/assets/{CollectionHooksPage-EFkVZNrc.js → CollectionHooksPage-DIaSrKDj.js} +1 -1
- package/dist/assets/{CollectionHooksPage-EFkVZNrc.js.map → CollectionHooksPage-DIaSrKDj.js.map} +1 -1
- package/dist/assets/{CollectionsPage-D-N_ykJz.js → CollectionsPage-CL_t5JRI.js} +1 -1
- package/dist/assets/{CollectionsPage-D-N_ykJz.js.map → CollectionsPage-CL_t5JRI.js.map} +1 -1
- package/dist/assets/{ComponentBuilderPage-C3mhOLPs.js → ComponentBuilderPage-C58Rr1cu.js} +1 -1
- package/dist/assets/{ComponentBuilderPage-C3mhOLPs.js.map → ComponentBuilderPage-C58Rr1cu.js.map} +1 -1
- package/dist/assets/{DashboardBuilder-Beiurp0v.js → DashboardBuilder-Chjyqyb7.js} +1 -1
- package/dist/assets/{DashboardBuilder-Beiurp0v.js.map → DashboardBuilder-Chjyqyb7.js.map} +1 -1
- package/dist/assets/{PluginsPage-BjPoOvBl.js → PluginsPage-DAR4Fsz-.js} +1 -1
- package/dist/assets/{PluginsPage-BjPoOvBl.js.map → PluginsPage-DAR4Fsz-.js.map} +1 -1
- package/dist/assets/{RedirectsPage-GIZCbEll.js → RedirectsPage-DfMTJsac.js} +1 -1
- package/dist/assets/{RedirectsPage-GIZCbEll.js.map → RedirectsPage-DfMTJsac.js.map} +1 -1
- package/dist/assets/{SchemaBuilderPage-3CDbJi28.js → SchemaBuilderPage-BYprOkEv.js} +1 -1
- package/dist/assets/{SchemaBuilderPage-3CDbJi28.js.map → SchemaBuilderPage-BYprOkEv.js.map} +1 -1
- package/dist/assets/{SettingsPage-DYYNnxkV.js → SettingsPage-B2r_uNVc.js} +1 -1
- package/dist/assets/{SettingsPage-DYYNnxkV.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-DfeCDCe_.js → TemplatesPage-BplB2ksb.js} +1 -1
- package/dist/assets/{TemplatesPage-DfeCDCe_.js.map → TemplatesPage-BplB2ksb.js.map} +1 -1
- package/dist/assets/{TrashPage-DGi-7RPl.js → TrashPage-BIhKrs5x.js} +1 -1
- package/dist/assets/{TrashPage-DGi-7RPl.js.map → TrashPage-BIhKrs5x.js.map} +1 -1
- package/dist/assets/{index-C4J6QNLn.js → index-yE_3fruG.js} +3 -3
- package/dist/assets/index-yE_3fruG.js.map +1 -0
- package/dist/index.html +1 -1
- package/dist/sw.js +1 -1
- package/dist/sw.js.map +1 -1
- 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-DlyP5PPa.js +0 -3
- package/dist/assets/SpatialEditor-DlyP5PPa.js.map +0 -1
- package/dist/assets/index-C4J6QNLn.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockBuilderPage-CeVMk5Ns.js","names":[],"sources":["../../src/pages/BlockBuilderPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react'\nimport {\n Plus, Database, Code, Check, Trash2, Box, Settings, X,\n Save, Loader2, FileText, Hash, Globe, Lock, Calendar,\n Image, Link2, ToggleLeft, AlignLeft, Braces, Tag, Layers, Eye,\n LayoutTemplate, ArrowDownToLine, Folders\n} from 'lucide-react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { cn } from '../lib/utils'\nimport { useTheme } from '../context/ThemeContext'\nimport toast from 'react-hot-toast'\nimport { clearBlockCache } from '../hooks/useBlockLibrary'\nimport api from '../lib/api'\nimport { PageHeader } from '../components/ui/PageHeader'\n\n// ── Full field type catalogue ────────────────────────────────────────────────\nconst FIELD_TYPES = [\n // Basic\n { value: 'text', label: 'Text', icon: FileText, color: '#6b7280', desc: 'Small or long text like title or description' },\n { value: 'textarea', label: 'Textarea', icon: AlignLeft, color: '#6b7280', desc: 'Multi-line text for longer descriptions' },\n { value: 'number', label: 'Number', icon: Hash, color: '#3b82f6', desc: 'Numbers (integer, float, decimal)' },\n { value: 'email', label: 'Email', icon: Globe, color: 'var(--z-accent)', desc: 'Email field with validation format' },\n { value: 'password', label: 'Password', icon: Lock, color: '#ef4444', desc: 'Password field with encryption' },\n { value: 'checkbox', label: 'Boolean', icon: ToggleLeft, color: 'var(--z-accent)', desc: 'Yes/No, 1/0, True/False' },\n { value: 'date', label: 'Date', icon: Calendar, color: '#f59e0b', desc: 'A date picker with hours, minutes and seconds' },\n { value: 'media', label: 'Media', icon: Image, color: '#06b6d4', desc: 'Files like images, videos, etc' },\n { value: 'richtext', label: 'Rich Text', icon: FileText, color: '#84cc16', desc: 'A rich text editor with formatting options' },\n { value: 'relation', label: 'Relation', icon: Link2, color: '#ec4899', desc: 'Refers to another collection' },\n { value: 'json', label: 'JSON', icon: Braces, color: '#6366f1', desc: 'Data in JSON format' },\n { value: 'array', label: 'Array', icon: Layers, color: '#f59e0b', desc: 'A repeating group of fields' },\n // Structural (Payload-style)\n { value: 'row', label: 'Row', icon: LayoutTemplate, color: '#ec4899', desc: 'Group fields side-by-side' },\n { value: 'collapsible', label: 'Collapsible', icon: ArrowDownToLine, color: 'var(--z-accent)', desc: 'Wrap fields in an accordion' },\n { value: 'tabs', label: 'Tabs', icon: Folders, color: '#3b82f6', desc: 'Organize fields into tabs' },\n] as const\n\ntype FieldType = typeof FIELD_TYPES[number]['value']\n\ninterface FieldConfig {\n name?: string\n type: FieldType\n label?: string\n required?: boolean\n unique?: boolean\n description?: string\n defaultValue?: any\n relationTo?: string\n hasMany?: boolean\n options?: { label: string; value: string }[]\n fields?: FieldConfig[]\n \n // Validation\n min?: number\n max?: number\n minLength?: number\n maxLength?: number\n regex?: string\n dateFormat?: string\n \n i18n?: boolean\n \n // Admin & Layout\n admin?: {\n width?: string\n placeholder?: string\n hidden?: boolean\n readOnly?: boolean\n condition?: any\n }\n}\n\ninterface SavedBlock {\n slug: string\n labels?: { singular?: string; plural?: string }\n fields?: FieldConfig[]\n admin?: { category?: string; icon?: string; description?: string }\n isGenerated?: boolean\n}\n\n// ── Main Block Builder Page ─────────────────────────────────────────────────\nexport default function BlockBuilderPage() {\n const { theme } = useTheme()\n const dark = theme === 'dark'\n\n // Block being edited\n const [title, setTitle] = useState('New Block')\n const [slug, setSlug] = useState('new-block')\n const [category, setCategory] = useState('General')\n const [icon, setIcon] = useState('Box')\n const [description, setDescription] = useState('')\n const [fields, setFields] = useState<FieldConfig[]>([])\n\n // Saved blocks list\n const [savedBlocks, setSavedBlocks] = useState<SavedBlock[]>([])\n const [loadingBlocks, setLoadingBlocks] = useState(true)\n\n // Collections for relations\n const [availableCollections, setAvailableCollections] = useState<string[]>([])\n\n // UI state\n const [saving, setSaving] = useState(false)\n \n // Modal State\n const [isFieldModalOpen, setIsFieldModalOpen] = useState(false)\n const [modalStep, setModalStep] = useState<'TYPE' | 'SETTINGS'>('TYPE')\n const [settingsTab, setSettingsTab] = useState<'BASIC' | 'VALIDATION' | 'ADMIN'>('BASIC')\n \n const [activeField, setActiveField] = useState<Partial<FieldConfig> | null>(null)\n \n // To handle nested fields, we need a path array. [0, 'fields', 1] means fields[0].fields[1]\n // But for this simple implementation, let's keep it flat first, and then allow nesting arrays/rows if needed.\n // We'll support editing a flat list for now, and allow structural fields to just be defined.\n // Actually, for a fully deep UX, we would have a recursive editor. For this page, we'll keep the list top-level but allow recursive config inside the advanced JSON or just as a flat list if row.\n const [editingFieldIndex, setEditingFieldIndex] = useState<number | null>(null)\n\n const loadBlocks = useCallback(async () => {\n try {\n const res = await api.get('/blocks')\n const raw = res.data?.data\n setSavedBlocks(Array.isArray(raw) ? raw : [])\n } catch {\n setSavedBlocks([])\n } finally {\n setLoadingBlocks(false)\n }\n }, [])\n\n useEffect(() => {\n loadBlocks()\n // Mocking collections for relation dropdown. \n // Usually this hits /api/collections or introspect.\n setAvailableCollections(['users', 'pages', 'media', 'categories'])\n }, [loadBlocks])\n\n const loadBlock = (block: SavedBlock) => {\n setTitle(block.labels?.singular || block.slug)\n setSlug(block.slug)\n setCategory(block.admin?.category || 'General')\n setIcon(block.admin?.icon || 'Box')\n setDescription(block.admin?.description || '')\n setFields(block.fields || [])\n toast.success(`Loaded block: ${block.slug}`)\n }\n\n const resetEditor = () => {\n setTitle('New Block')\n setSlug('new-block')\n setCategory('General')\n setIcon('Box')\n setDescription('')\n setFields([])\n }\n\n const handleSave = async () => {\n if (!slug || !title) return toast.error('Name and slug required')\n setSaving(true)\n try {\n const payload = { slug, title, description, category, icon, fields }\n const res = await api.post('/blocks/generate', payload)\n clearBlockCache()\n toast.success(res.data.message || 'Block generated as JSON!')\n await loadBlocks()\n } catch (err: any) {\n toast.error(err.response?.data?.error?.message || 'Failed to generate block')\n } finally {\n setSaving(false)\n }\n }\n\n const handleFieldSubmit = () => {\n if (!activeField?.type) return toast.error('Field type required')\n if (activeField.type !== 'row' && activeField.type !== 'tabs' && !activeField.name) return toast.error('Field name is required')\n \n if (editingFieldIndex !== null) {\n const next = [...fields]\n next[editingFieldIndex] = activeField as FieldConfig\n setFields(next)\n } else {\n setFields(prev => [...prev, activeField as FieldConfig])\n }\n \n setIsFieldModalOpen(false)\n }\n\n const removeField = (index: number) => {\n setFields(prev => prev.filter((_, i) => i !== index))\n }\n\n const inputClass = cn(\n 'border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black text-sm font-bold transition-colors py-2.5 px-3 rounded-none shadow-sm',\n dark ? 'bg-z-panel backdrop-blur-md border-z-border focus:border-z-accent text-z-primary placeholder:text-z-muted' : 'bg-z-panel border-z-border focus:border-z-accent text-z-primary placeholder:text-z-muted'\n )\n \n const blocksByCategory = savedBlocks.reduce((acc, block) => {\n const cat = block.admin?.category || 'General'\n if (!acc[cat]) acc[cat] = []\n acc[cat].push(block)\n return acc\n }, {} as Record<string, SavedBlock[]>)\n\n return (\n <div className={cn('flex h-[calc(100vh-4rem)] overflow-hidden', dark ? 'bg-app text-z-primary' : 'bg-[var(--z-bg-input)] text-z-primary')}>\n <div className={cn('w-64 flex-shrink-0 border-r flex flex-col', 'border-z-border bg-z-panel')}>\n <div className=\"p-4 border-b border-inherit flex items-center justify-between\">\n <h2 className=\"text-sm font-semibold flex items-center gap-2\">\n <Database size={14} className=\"text-z-secondary \" /> Blocks\n </h2>\n <button onClick={resetEditor} className=\"p-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary rounded-none transition-colors\" title=\"New Block\">\n <Plus size={14} />\n </button>\n </div>\n <div className=\"flex-1 overflow-auto p-4 space-y-4\">\n {loadingBlocks ? (\n <div className=\"flex justify-center\"><Loader2 className=\"animate-spin text-z-muted\" size={16} /></div>\n ) : Object.keys(blocksByCategory).length === 0 ? (\n <div className=\"text-center text-sm text-z-secondary\">No blocks yet</div>\n ) : (\n Object.entries(blocksByCategory).map(([cat, blocks]) => (\n <div key={cat} className=\"space-y-1.5\">\n <h3 className=\"text-sm font-semibold text-z-secondary\">{cat}</h3>\n <div className=\"space-y-0.5\">\n {blocks.map(block => (\n <button key={block.slug} onClick={() => loadBlock(block)} className={cn('w-full flex items-center gap-2 text-left px-3 py-2 text-sm font-semibold transition-colors rounded-none truncate', slug === block.slug ? 'bg-z-accent text-z-logo-text shadow-sm' : dark ? 'text-z-muted hover:bg-z-hover hover:text-z-primary' : 'text-z-secondary hover:bg-[var(--z-bg-input)]')}>\n {block.isGenerated ? <Code size={12} className={slug === block.slug ? 'text-z-primary' : 'text-z-secondary/50'} /> : <Box size={12} />}\n {block.labels?.singular || block.slug}\n </button>\n ))}\n </div>\n </div>\n ))\n )}\n </div>\n </div>\n\n <div className=\"flex-1 flex flex-col overflow-hidden relative\">\n <PageHeader\n title=\"Component Builder\"\n description={`${fields.length} fields · Generating to config/blocks/${slug}.json`}\n icon={<Layers size={24} />}\n backLink={{ to: '/', label: 'Dashboard' }}\n actions={\n <div className=\"flex items-center gap-2\">\n <button onClick={handleSave} disabled={saving} className=\"flex items-center gap-2 px-6 py-2.5 bg-z-accent hover:brightness-110 text-z-logo-text text-sm font-semibold rounded-none transition-all shadow-sm disabled:opacity-50\">\n {saving ? <Loader2 size={14} className=\"animate-spin\" /> : <Save size={14} />} Save Code\n </button>\n </div>\n }\n />\n\n <div className=\"flex-1 overflow-auto p-6 space-y-6\">\n <div className={cn('rounded-none border p-6 space-y-4 shadow-sm transition-all', 'z-panel')}>\n <h3 className=\"text-sm font-semibold text-z-secondary flex items-center gap-2\"><Settings size={12} /> Component Settings</h3>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Display Name</label>\n <input type=\"text\" value={title} onChange={e => { setTitle(e.target.value); setSlug(e.target.value.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '')) }} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Hero Banner\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">API Slug (filename)</label>\n <input type=\"text\" value={slug} onChange={e => setSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder=\"e.g. hero-banner\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Category</label>\n <input type=\"text\" value={category} onChange={e => setCategory(e.target.value)} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Layout, Content, Media\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Description</label>\n <input type=\"text\" value={description} onChange={e => setDescription(e.target.value)} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"Brief description for editors\" />\n </div>\n </div>\n </div>\n\n <div className={cn('rounded-none border shadow-sm transition-all', 'z-panel')}>\n <div className=\"px-6 py-4 border-b border-inherit flex items-center justify-between\">\n <h3 className=\"text-sm font-semibold text-z-secondary flex items-center gap-2\"><Layers size={12} /> Fields ({fields.length})</h3>\n <button onClick={() => { setModalStep('TYPE'); setActiveField({}); setEditingFieldIndex(null); setSettingsTab('BASIC'); setIsFieldModalOpen(true) }} className=\"flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary text-sm font-semibold rounded-none transition-all\">\n <Plus size={12} /> Add new field\n </button>\n </div>\n <div className=\"p-0\">\n {fields.length === 0 ? (\n <div className=\"py-16 text-center\">\n <Layers size={40} className=\"mx-auto text-z-primary mb-4\" strokeWidth={1} />\n <p className=\"text-sm font-semibold text-z-secondary\">No fields yet</p>\n </div>\n ) : (\n <div className=\"divide-y divide-z-border dark:divide-z-border\">\n {fields.map((field, i) => (\n <div key={i} className=\"flex items-center justify-between px-6 py-4 hover:bg-z-hover transition-colors group cursor-pointer\"\n onClick={() => { setActiveField(field); setEditingFieldIndex(i); setModalStep('SETTINGS'); setSettingsTab('BASIC'); setIsFieldModalOpen(true) }}>\n <div className=\"flex items-center gap-4\">\n <div className=\"w-8 h-8 rounded-none bg-z-panel flex items-center justify-center\">\n {(() => { const ft = FIELD_TYPES.find(t => t.value === field.type); const Icon = ft ? ft.icon : Box; return <Icon size={14} className=\"text-z-secondary \" /> })()}\n </div>\n <div>\n <div className=\"text-sm font-bold text-z-primary dark:text-z-primary flex items-center gap-2\">\n {field.name || `[${field.type}]`}\n {field.required && <span className=\"text-sm text-red-500\">*</span>}\n {field.i18n && <Globe size={10} className=\"text-z-active-text\" />}\n </div>\n <div className=\"text-sm font-bold text-z-secondary mt-0.5\">{field.type} {field.label ? `· ${field.label}` : ''}</div>\n </div>\n </div>\n <button onClick={(e) => { e.stopPropagation(); removeField(i) }} className=\"opacity-0 group-hover:opacity-100 p-2 text-red-500 hover:bg-red-500/10 rounded-none transition-all\"><Trash2 size={14} /></button>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n\n <AnimatePresence>\n {isFieldModalOpen && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95, y: 10 }} animate={{ scale: 1, y: 0 }} exit={{ scale: 0.95, y: 10 }} className=\"w-full max-w-4xl border rounded-none shadow-sm flex flex-col max-h-[85vh] bg-app border-z-border overflow-hidden\">\n <div className=\"px-6 py-4 border-b border-z-border flex items-center justify-between bg-app/50\">\n <h2 className=\"text-sm font-semibold text-z-primary flex items-center gap-2\">\n {modalStep === 'TYPE' ? 'Select a field for your Component' : `Configure ${activeField?.type} field`}\n </h2>\n <button onClick={() => setIsFieldModalOpen(false)} className=\"text-z-secondary hover:text-z-primary p-1\"><X size={18} /></button>\n </div>\n\n {modalStep === 'TYPE' && (\n <div className=\"flex-1 overflow-auto p-6 grid grid-cols-2 lg:grid-cols-3 gap-4\">\n {FIELD_TYPES.map((ft) => {\n const Icon = ft.icon\n return (\n <button key={ft.value} onClick={() => { setActiveField({ type: ft.value, admin: {} }); setModalStep('SETTINGS') }} className=\"flex items-start gap-4 p-4 rounded-none border border-z-border bg-z-hover hover:border-z-accent/50 hover:opacity-90/5 transition-all text-left\">\n <div className=\"mt-1 p-2 rounded-none bg-app/50 border border-z-border\"><Icon size={18} style={{ color: ft.color }} /></div>\n <div>\n <div className=\"text-sm font-semibold text-z-primary mb-1\">{ft.label}</div>\n <div className=\"text-sm text-z-muted leading-relaxed font-bold\">{ft.desc}</div>\n </div>\n </button>\n )\n })}\n </div>\n )}\n\n {modalStep === 'SETTINGS' && (\n <div className=\"flex flex-col flex-1 overflow-hidden\">\n <div className=\"flex border-b border-z-border px-6 pt-4 gap-6 bg-app/20\">\n {['BASIC', 'VALIDATION', 'ADMIN'].map(tab => (\n <button key={tab} onClick={() => setSettingsTab(tab as any)} className={cn(\"pb-3 text-sm font-semibold transition-colors relative\", settingsTab === tab ? \"text-z-secondary \" : \"text-z-secondary hover:text-z-primary\")}>\n {tab}\n {settingsTab === tab && <motion.div layoutId=\"tab-indicator\" className=\"absolute bottom-0 left-0 right-0 h-0.5 bg-z-border\" />}\n </button>\n ))}\n </div>\n <div className=\"flex-1 overflow-auto p-6 max-w-3xl mx-auto w-full\">\n {settingsTab === 'BASIC' && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div className=\"col-span-2 sm:col-span-1\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Name (Key in JSON)*</label>\n <input type=\"text\" value={activeField?.name || ''} onChange={e => setActiveField(prev => ({ ...prev, name: e.target.value.replace(/\\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, '') }))} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder=\"e.g. heroTitle\" />\n </div>\n <div className=\"col-span-2 sm:col-span-1\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Display Label</label>\n <input type=\"text\" value={activeField?.label || ''} onChange={e => setActiveField(prev => ({ ...prev, label: e.target.value }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Hero Title\" />\n </div>\n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Description</label>\n <input type=\"text\" value={activeField?.description || ''} onChange={e => setActiveField(prev => ({ ...prev, description: e.target.value }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"Help text for content editors\" />\n </div>\n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Default Value</label>\n <input type=\"text\" value={activeField?.defaultValue || ''} onChange={e => setActiveField(prev => ({ ...prev, defaultValue: e.target.value }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Welcome\" />\n </div>\n \n {activeField?.type === 'relation' && (\n <div className=\"col-span-2 pt-4 border-t border-z-border space-y-4\">\n <label className=\"text-sm font-semibold text-z-secondary block\">Relation Options</label>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Relates To</label>\n <select value={activeField.relationTo || ''} onChange={e => setActiveField(prev => ({ ...prev, relationTo: e.target.value }))} className={cn(inputClass, 'w-full rounded-none cursor-pointer')}>\n <option value=\"\">-- Select Collection --</option>\n {availableCollections.map(c => <option key={c} value={c}>{c}</option>)}\n </select>\n </div>\n <div className=\"flex items-center\">\n <label className=\"flex items-center gap-2 cursor-pointer mt-4\">\n <input type=\"checkbox\" checked={!!activeField?.hasMany} onChange={e => setActiveField(prev => ({ ...prev, hasMany: e.target.checked }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Has Many (Array of references)</span>\n </label>\n </div>\n </div>\n </div>\n )}\n </div>\n )}\n\n {settingsTab === 'VALIDATION' && (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 bg-z-hover p-4 rounded-none border border-z-border\">\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.required} onChange={e => setActiveField(prev => ({ ...prev, required: e.target.checked }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Required field</span>\n </label>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.unique} onChange={e => setActiveField(prev => ({ ...prev, unique: e.target.checked }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Unique field</span>\n </label>\n </div>\n \n {(activeField?.type === 'text' || activeField?.type === 'textarea') && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Min Length</label>\n <input type=\"number\" value={activeField?.minLength || ''} onChange={e => setActiveField(prev => ({ ...prev, minLength: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 5\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Max Length</label>\n <input type=\"number\" value={activeField?.maxLength || ''} onChange={e => setActiveField(prev => ({ ...prev, maxLength: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 100\" />\n </div>\n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Regex Pattern</label>\n <input type=\"text\" value={activeField?.regex || ''} onChange={e => setActiveField(prev => ({ ...prev, regex: e.target.value }))} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder=\"^[A-Za-z]+$\" />\n </div>\n </div>\n )}\n \n {activeField?.type === 'number' && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Minimum Value</label>\n <input type=\"number\" value={activeField?.min || ''} onChange={e => setActiveField(prev => ({ ...prev, min: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 0\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Maximum Value</label>\n <input type=\"number\" value={activeField?.max || ''} onChange={e => setActiveField(prev => ({ ...prev, max: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 100\" />\n </div>\n </div>\n )}\n \n {activeField?.type === 'date' && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Date Mode</label>\n <select value={activeField?.dateFormat || 'date'} onChange={e => setActiveField(prev => ({ ...prev, dateFormat: e.target.value }))} className={cn(inputClass, 'w-full rounded-none cursor-pointer')}>\n <option value=\"date\">Date Only</option>\n <option value=\"datetime\">Date & Time</option>\n <option value=\"time\">Time Only</option>\n </select>\n </div>\n </div>\n )}\n </div>\n )}\n\n {settingsTab === 'ADMIN' && (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 bg-z-hover p-4 rounded-none border border-z-border\">\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.i18n} onChange={e => setActiveField(prev => ({ ...prev, i18n: e.target.checked }))} className=\"accent-z-accent w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Enable Localization (i18n)</span>\n </label>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.admin?.hidden} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, hidden: e.target.checked } }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Hidden in UI</span>\n </label>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.admin?.readOnly} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, readOnly: e.target.checked } }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Read-Only</span>\n </label>\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Field Width</label>\n <select value={activeField?.admin?.width || '100%'} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, width: e.target.value } }))} className={cn(inputClass, 'w-full rounded-none cursor-pointer')}>\n <option value=\"100%\">100% (Full Width)</option>\n <option value=\"50%\">50% (Half Width)</option>\n <option value=\"33%\">33% (One Third)</option>\n <option value=\"25%\">25% (One Quarter)</option>\n </select>\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Placeholder</label>\n <input type=\"text\" value={activeField?.admin?.placeholder || ''} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, placeholder: e.target.value } }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Enter a value...\" />\n </div>\n \n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Conditional Visibility JSON</label>\n <textarea rows={3} value={activeField?.admin?.condition ? JSON.stringify(activeField.admin.condition) : ''} onChange={e => {\n try {\n const parsed = e.target.value ? JSON.parse(e.target.value) : undefined;\n setActiveField(prev => ({ ...prev, admin: { ...prev.admin, condition: parsed } }))\n } catch { /* invalid JSON */ }\n }} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder='{\"field\": \"theme\", \"equals\": \"dark\"}' />\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n\n <div className=\"px-6 py-4 border-t border-z-border bg-app/50 flex justify-between\">\n {modalStep === 'SETTINGS' ? (\n <button onClick={() => setModalStep('TYPE')} className=\"px-4 py-2 text-sm font-bold text-z-muted hover:text-z-primary transition-colors\">\n ← Back to Types\n </button>\n ) : <div />}\n {modalStep === 'SETTINGS' && (\n <button onClick={handleFieldSubmit} className=\"px-6 py-2 bg-z-accent hover:brightness-110 text-z-logo-text text-sm font-semibold rounded-none transition-all shadow-sm\">\n {editingFieldIndex !== null ? 'Update Field' : 'Add Field'}\n </button>\n )}\n </div>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BlockBuilderPage-XD1IjOgx.js","names":[],"sources":["../../src/pages/BlockBuilderPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react'\nimport {\n Plus, Database, Code, Check, Trash2, Box, Settings, X,\n Save, Loader2, FileText, Hash, Globe, Lock, Calendar,\n Image, Link2, ToggleLeft, AlignLeft, Braces, Tag, Layers, Eye,\n LayoutTemplate, ArrowDownToLine, Folders\n} from 'lucide-react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { cn } from '../lib/utils'\nimport { useTheme } from '../context/ThemeContext'\nimport toast from 'react-hot-toast'\nimport { clearBlockCache } from '../hooks/useBlockLibrary'\nimport api from '../lib/api'\nimport { PageHeader } from '../components/ui/PageHeader'\n\n// ── Full field type catalogue ────────────────────────────────────────────────\nconst FIELD_TYPES = [\n // Basic\n { value: 'text', label: 'Text', icon: FileText, color: '#6b7280', desc: 'Small or long text like title or description' },\n { value: 'textarea', label: 'Textarea', icon: AlignLeft, color: '#6b7280', desc: 'Multi-line text for longer descriptions' },\n { value: 'number', label: 'Number', icon: Hash, color: '#3b82f6', desc: 'Numbers (integer, float, decimal)' },\n { value: 'email', label: 'Email', icon: Globe, color: 'var(--z-accent)', desc: 'Email field with validation format' },\n { value: 'password', label: 'Password', icon: Lock, color: '#ef4444', desc: 'Password field with encryption' },\n { value: 'checkbox', label: 'Boolean', icon: ToggleLeft, color: 'var(--z-accent)', desc: 'Yes/No, 1/0, True/False' },\n { value: 'date', label: 'Date', icon: Calendar, color: '#f59e0b', desc: 'A date picker with hours, minutes and seconds' },\n { value: 'media', label: 'Media', icon: Image, color: '#06b6d4', desc: 'Files like images, videos, etc' },\n { value: 'richtext', label: 'Rich Text', icon: FileText, color: '#84cc16', desc: 'A rich text editor with formatting options' },\n { value: 'relation', label: 'Relation', icon: Link2, color: '#ec4899', desc: 'Refers to another collection' },\n { value: 'json', label: 'JSON', icon: Braces, color: '#6366f1', desc: 'Data in JSON format' },\n { value: 'array', label: 'Array', icon: Layers, color: '#f59e0b', desc: 'A repeating group of fields' },\n // Structural (Payload-style)\n { value: 'row', label: 'Row', icon: LayoutTemplate, color: '#ec4899', desc: 'Group fields side-by-side' },\n { value: 'collapsible', label: 'Collapsible', icon: ArrowDownToLine, color: 'var(--z-accent)', desc: 'Wrap fields in an accordion' },\n { value: 'tabs', label: 'Tabs', icon: Folders, color: '#3b82f6', desc: 'Organize fields into tabs' },\n] as const\n\ntype FieldType = typeof FIELD_TYPES[number]['value']\n\ninterface FieldConfig {\n name?: string\n type: FieldType\n label?: string\n required?: boolean\n unique?: boolean\n description?: string\n defaultValue?: any\n relationTo?: string\n hasMany?: boolean\n options?: { label: string; value: string }[]\n fields?: FieldConfig[]\n \n // Validation\n min?: number\n max?: number\n minLength?: number\n maxLength?: number\n regex?: string\n dateFormat?: string\n \n i18n?: boolean\n \n // Admin & Layout\n admin?: {\n width?: string\n placeholder?: string\n hidden?: boolean\n readOnly?: boolean\n condition?: any\n }\n}\n\ninterface SavedBlock {\n slug: string\n labels?: { singular?: string; plural?: string }\n fields?: FieldConfig[]\n admin?: { category?: string; icon?: string; description?: string }\n isGenerated?: boolean\n}\n\n// ── Main Block Builder Page ─────────────────────────────────────────────────\nexport default function BlockBuilderPage() {\n const { theme } = useTheme()\n const dark = theme === 'dark'\n\n // Block being edited\n const [title, setTitle] = useState('New Block')\n const [slug, setSlug] = useState('new-block')\n const [category, setCategory] = useState('General')\n const [icon, setIcon] = useState('Box')\n const [description, setDescription] = useState('')\n const [fields, setFields] = useState<FieldConfig[]>([])\n\n // Saved blocks list\n const [savedBlocks, setSavedBlocks] = useState<SavedBlock[]>([])\n const [loadingBlocks, setLoadingBlocks] = useState(true)\n\n // Collections for relations\n const [availableCollections, setAvailableCollections] = useState<string[]>([])\n\n // UI state\n const [saving, setSaving] = useState(false)\n \n // Modal State\n const [isFieldModalOpen, setIsFieldModalOpen] = useState(false)\n const [modalStep, setModalStep] = useState<'TYPE' | 'SETTINGS'>('TYPE')\n const [settingsTab, setSettingsTab] = useState<'BASIC' | 'VALIDATION' | 'ADMIN'>('BASIC')\n \n const [activeField, setActiveField] = useState<Partial<FieldConfig> | null>(null)\n \n // To handle nested fields, we need a path array. [0, 'fields', 1] means fields[0].fields[1]\n // But for this simple implementation, let's keep it flat first, and then allow nesting arrays/rows if needed.\n // We'll support editing a flat list for now, and allow structural fields to just be defined.\n // Actually, for a fully deep UX, we would have a recursive editor. For this page, we'll keep the list top-level but allow recursive config inside the advanced JSON or just as a flat list if row.\n const [editingFieldIndex, setEditingFieldIndex] = useState<number | null>(null)\n\n const loadBlocks = useCallback(async () => {\n try {\n const res = await api.get('/blocks')\n const raw = res.data?.data\n setSavedBlocks(Array.isArray(raw) ? raw : [])\n } catch {\n setSavedBlocks([])\n } finally {\n setLoadingBlocks(false)\n }\n }, [])\n\n useEffect(() => {\n loadBlocks()\n // Mocking collections for relation dropdown. \n // Usually this hits /api/collections or introspect.\n setAvailableCollections(['users', 'pages', 'media', 'categories'])\n }, [loadBlocks])\n\n const loadBlock = (block: SavedBlock) => {\n setTitle(block.labels?.singular || block.slug)\n setSlug(block.slug)\n setCategory(block.admin?.category || 'General')\n setIcon(block.admin?.icon || 'Box')\n setDescription(block.admin?.description || '')\n setFields(block.fields || [])\n toast.success(`Loaded block: ${block.slug}`)\n }\n\n const resetEditor = () => {\n setTitle('New Block')\n setSlug('new-block')\n setCategory('General')\n setIcon('Box')\n setDescription('')\n setFields([])\n }\n\n const handleSave = async () => {\n if (!slug || !title) return toast.error('Name and slug required')\n setSaving(true)\n try {\n const payload = { slug, title, description, category, icon, fields }\n const res = await api.post('/blocks/generate', payload)\n clearBlockCache()\n toast.success(res.data.message || 'Block generated as JSON!')\n await loadBlocks()\n } catch (err: any) {\n toast.error(err.response?.data?.error?.message || 'Failed to generate block')\n } finally {\n setSaving(false)\n }\n }\n\n const handleFieldSubmit = () => {\n if (!activeField?.type) return toast.error('Field type required')\n if (activeField.type !== 'row' && activeField.type !== 'tabs' && !activeField.name) return toast.error('Field name is required')\n \n if (editingFieldIndex !== null) {\n const next = [...fields]\n next[editingFieldIndex] = activeField as FieldConfig\n setFields(next)\n } else {\n setFields(prev => [...prev, activeField as FieldConfig])\n }\n \n setIsFieldModalOpen(false)\n }\n\n const removeField = (index: number) => {\n setFields(prev => prev.filter((_, i) => i !== index))\n }\n\n const inputClass = cn(\n 'border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black text-sm font-bold transition-colors py-2.5 px-3 rounded-none shadow-sm',\n dark ? 'bg-z-panel backdrop-blur-md border-z-border focus:border-z-accent text-z-primary placeholder:text-z-muted' : 'bg-z-panel border-z-border focus:border-z-accent text-z-primary placeholder:text-z-muted'\n )\n \n const blocksByCategory = savedBlocks.reduce((acc, block) => {\n const cat = block.admin?.category || 'General'\n if (!acc[cat]) acc[cat] = []\n acc[cat].push(block)\n return acc\n }, {} as Record<string, SavedBlock[]>)\n\n return (\n <div className={cn('flex h-[calc(100vh-4rem)] overflow-hidden', dark ? 'bg-app text-z-primary' : 'bg-[var(--z-bg-input)] text-z-primary')}>\n <div className={cn('w-64 flex-shrink-0 border-r flex flex-col', 'border-z-border bg-z-panel')}>\n <div className=\"p-4 border-b border-inherit flex items-center justify-between\">\n <h2 className=\"text-sm font-semibold flex items-center gap-2\">\n <Database size={14} className=\"text-z-secondary \" /> Blocks\n </h2>\n <button onClick={resetEditor} className=\"p-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary rounded-none transition-colors\" title=\"New Block\">\n <Plus size={14} />\n </button>\n </div>\n <div className=\"flex-1 overflow-auto p-4 space-y-4\">\n {loadingBlocks ? (\n <div className=\"flex justify-center\"><Loader2 className=\"animate-spin text-z-muted\" size={16} /></div>\n ) : Object.keys(blocksByCategory).length === 0 ? (\n <div className=\"text-center text-sm text-z-secondary\">No blocks yet</div>\n ) : (\n Object.entries(blocksByCategory).map(([cat, blocks]) => (\n <div key={cat} className=\"space-y-1.5\">\n <h3 className=\"text-sm font-semibold text-z-secondary\">{cat}</h3>\n <div className=\"space-y-0.5\">\n {blocks.map(block => (\n <button key={block.slug} onClick={() => loadBlock(block)} className={cn('w-full flex items-center gap-2 text-left px-3 py-2 text-sm font-semibold transition-colors rounded-none truncate', slug === block.slug ? 'bg-z-accent text-z-logo-text shadow-sm' : dark ? 'text-z-muted hover:bg-z-hover hover:text-z-primary' : 'text-z-secondary hover:bg-[var(--z-bg-input)]')}>\n {block.isGenerated ? <Code size={12} className={slug === block.slug ? 'text-z-primary' : 'text-z-secondary/50'} /> : <Box size={12} />}\n {block.labels?.singular || block.slug}\n </button>\n ))}\n </div>\n </div>\n ))\n )}\n </div>\n </div>\n\n <div className=\"flex-1 flex flex-col overflow-hidden relative\">\n <PageHeader\n title=\"Component Builder\"\n description={`${fields.length} fields · Generating to config/blocks/${slug}.json`}\n icon={<Layers size={24} />}\n backLink={{ to: '/', label: 'Dashboard' }}\n actions={\n <div className=\"flex items-center gap-2\">\n <button onClick={handleSave} disabled={saving} className=\"flex items-center gap-2 px-6 py-2.5 bg-z-accent hover:brightness-110 text-z-logo-text text-sm font-semibold rounded-none transition-all shadow-sm disabled:opacity-50\">\n {saving ? <Loader2 size={14} className=\"animate-spin\" /> : <Save size={14} />} Save Code\n </button>\n </div>\n }\n />\n\n <div className=\"flex-1 overflow-auto p-6 space-y-6\">\n <div className={cn('rounded-none border p-6 space-y-4 shadow-sm transition-all', 'z-panel')}>\n <h3 className=\"text-sm font-semibold text-z-secondary flex items-center gap-2\"><Settings size={12} /> Component Settings</h3>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Display Name</label>\n <input type=\"text\" value={title} onChange={e => { setTitle(e.target.value); setSlug(e.target.value.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '')) }} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Hero Banner\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">API Slug (filename)</label>\n <input type=\"text\" value={slug} onChange={e => setSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder=\"e.g. hero-banner\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Category</label>\n <input type=\"text\" value={category} onChange={e => setCategory(e.target.value)} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Layout, Content, Media\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Description</label>\n <input type=\"text\" value={description} onChange={e => setDescription(e.target.value)} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"Brief description for editors\" />\n </div>\n </div>\n </div>\n\n <div className={cn('rounded-none border shadow-sm transition-all', 'z-panel')}>\n <div className=\"px-6 py-4 border-b border-inherit flex items-center justify-between\">\n <h3 className=\"text-sm font-semibold text-z-secondary flex items-center gap-2\"><Layers size={12} /> Fields ({fields.length})</h3>\n <button onClick={() => { setModalStep('TYPE'); setActiveField({}); setEditingFieldIndex(null); setSettingsTab('BASIC'); setIsFieldModalOpen(true) }} className=\"flex items-center gap-1.5 px-3 py-1.5 bg-z-panel hover:bg-z-hover border-z-border-strong text-z-secondary text-sm font-semibold rounded-none transition-all\">\n <Plus size={12} /> Add new field\n </button>\n </div>\n <div className=\"p-0\">\n {fields.length === 0 ? (\n <div className=\"py-16 text-center\">\n <Layers size={40} className=\"mx-auto text-z-primary mb-4\" strokeWidth={1} />\n <p className=\"text-sm font-semibold text-z-secondary\">No fields yet</p>\n </div>\n ) : (\n <div className=\"divide-y divide-z-border dark:divide-z-border\">\n {fields.map((field, i) => (\n <div key={i} className=\"flex items-center justify-between px-6 py-4 hover:bg-z-hover transition-colors group cursor-pointer\"\n onClick={() => { setActiveField(field); setEditingFieldIndex(i); setModalStep('SETTINGS'); setSettingsTab('BASIC'); setIsFieldModalOpen(true) }}>\n <div className=\"flex items-center gap-4\">\n <div className=\"w-8 h-8 rounded-none bg-z-panel flex items-center justify-center\">\n {(() => { const ft = FIELD_TYPES.find(t => t.value === field.type); const Icon = ft ? ft.icon : Box; return <Icon size={14} className=\"text-z-secondary \" /> })()}\n </div>\n <div>\n <div className=\"text-sm font-bold text-z-primary dark:text-z-primary flex items-center gap-2\">\n {field.name || `[${field.type}]`}\n {field.required && <span className=\"text-sm text-red-500\">*</span>}\n {field.i18n && <Globe size={10} className=\"text-z-active-text\" />}\n </div>\n <div className=\"text-sm font-bold text-z-secondary mt-0.5\">{field.type} {field.label ? `· ${field.label}` : ''}</div>\n </div>\n </div>\n <button onClick={(e) => { e.stopPropagation(); removeField(i) }} className=\"opacity-0 group-hover:opacity-100 p-2 text-red-500 hover:bg-red-500/10 rounded-none transition-all\"><Trash2 size={14} /></button>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n\n <AnimatePresence>\n {isFieldModalOpen && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4\">\n <motion.div initial={{ scale: 0.95, y: 10 }} animate={{ scale: 1, y: 0 }} exit={{ scale: 0.95, y: 10 }} className=\"w-full max-w-4xl border rounded-none shadow-sm flex flex-col max-h-[85vh] bg-app border-z-border overflow-hidden\">\n <div className=\"px-6 py-4 border-b border-z-border flex items-center justify-between bg-app/50\">\n <h2 className=\"text-sm font-semibold text-z-primary flex items-center gap-2\">\n {modalStep === 'TYPE' ? 'Select a field for your Component' : `Configure ${activeField?.type} field`}\n </h2>\n <button onClick={() => setIsFieldModalOpen(false)} className=\"text-z-secondary hover:text-z-primary p-1\"><X size={18} /></button>\n </div>\n\n {modalStep === 'TYPE' && (\n <div className=\"flex-1 overflow-auto p-6 grid grid-cols-2 lg:grid-cols-3 gap-4\">\n {FIELD_TYPES.map((ft) => {\n const Icon = ft.icon\n return (\n <button key={ft.value} onClick={() => { setActiveField({ type: ft.value, admin: {} }); setModalStep('SETTINGS') }} className=\"flex items-start gap-4 p-4 rounded-none border border-z-border bg-z-hover hover:border-z-accent/50 hover:opacity-90/5 transition-all text-left\">\n <div className=\"mt-1 p-2 rounded-none bg-app/50 border border-z-border\"><Icon size={18} style={{ color: ft.color }} /></div>\n <div>\n <div className=\"text-sm font-semibold text-z-primary mb-1\">{ft.label}</div>\n <div className=\"text-sm text-z-muted leading-relaxed font-bold\">{ft.desc}</div>\n </div>\n </button>\n )\n })}\n </div>\n )}\n\n {modalStep === 'SETTINGS' && (\n <div className=\"flex flex-col flex-1 overflow-hidden\">\n <div className=\"flex border-b border-z-border px-6 pt-4 gap-6 bg-app/20\">\n {['BASIC', 'VALIDATION', 'ADMIN'].map(tab => (\n <button key={tab} onClick={() => setSettingsTab(tab as any)} className={cn(\"pb-3 text-sm font-semibold transition-colors relative\", settingsTab === tab ? \"text-z-secondary \" : \"text-z-secondary hover:text-z-primary\")}>\n {tab}\n {settingsTab === tab && <motion.div layoutId=\"tab-indicator\" className=\"absolute bottom-0 left-0 right-0 h-0.5 bg-z-border\" />}\n </button>\n ))}\n </div>\n <div className=\"flex-1 overflow-auto p-6 max-w-3xl mx-auto w-full\">\n {settingsTab === 'BASIC' && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div className=\"col-span-2 sm:col-span-1\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Name (Key in JSON)*</label>\n <input type=\"text\" value={activeField?.name || ''} onChange={e => setActiveField(prev => ({ ...prev, name: e.target.value.replace(/\\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, '') }))} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder=\"e.g. heroTitle\" />\n </div>\n <div className=\"col-span-2 sm:col-span-1\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Display Label</label>\n <input type=\"text\" value={activeField?.label || ''} onChange={e => setActiveField(prev => ({ ...prev, label: e.target.value }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Hero Title\" />\n </div>\n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Description</label>\n <input type=\"text\" value={activeField?.description || ''} onChange={e => setActiveField(prev => ({ ...prev, description: e.target.value }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"Help text for content editors\" />\n </div>\n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Default Value</label>\n <input type=\"text\" value={activeField?.defaultValue || ''} onChange={e => setActiveField(prev => ({ ...prev, defaultValue: e.target.value }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Welcome\" />\n </div>\n \n {activeField?.type === 'relation' && (\n <div className=\"col-span-2 pt-4 border-t border-z-border space-y-4\">\n <label className=\"text-sm font-semibold text-z-secondary block\">Relation Options</label>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Relates To</label>\n <select value={activeField.relationTo || ''} onChange={e => setActiveField(prev => ({ ...prev, relationTo: e.target.value }))} className={cn(inputClass, 'w-full rounded-none cursor-pointer')}>\n <option value=\"\">-- Select Collection --</option>\n {availableCollections.map(c => <option key={c} value={c}>{c}</option>)}\n </select>\n </div>\n <div className=\"flex items-center\">\n <label className=\"flex items-center gap-2 cursor-pointer mt-4\">\n <input type=\"checkbox\" checked={!!activeField?.hasMany} onChange={e => setActiveField(prev => ({ ...prev, hasMany: e.target.checked }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Has Many (Array of references)</span>\n </label>\n </div>\n </div>\n </div>\n )}\n </div>\n )}\n\n {settingsTab === 'VALIDATION' && (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 bg-z-hover p-4 rounded-none border border-z-border\">\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.required} onChange={e => setActiveField(prev => ({ ...prev, required: e.target.checked }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Required field</span>\n </label>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.unique} onChange={e => setActiveField(prev => ({ ...prev, unique: e.target.checked }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Unique field</span>\n </label>\n </div>\n \n {(activeField?.type === 'text' || activeField?.type === 'textarea') && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Min Length</label>\n <input type=\"number\" value={activeField?.minLength || ''} onChange={e => setActiveField(prev => ({ ...prev, minLength: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 5\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Max Length</label>\n <input type=\"number\" value={activeField?.maxLength || ''} onChange={e => setActiveField(prev => ({ ...prev, maxLength: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 100\" />\n </div>\n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Regex Pattern</label>\n <input type=\"text\" value={activeField?.regex || ''} onChange={e => setActiveField(prev => ({ ...prev, regex: e.target.value }))} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder=\"^[A-Za-z]+$\" />\n </div>\n </div>\n )}\n \n {activeField?.type === 'number' && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Minimum Value</label>\n <input type=\"number\" value={activeField?.min || ''} onChange={e => setActiveField(prev => ({ ...prev, min: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 0\" />\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Maximum Value</label>\n <input type=\"number\" value={activeField?.max || ''} onChange={e => setActiveField(prev => ({ ...prev, max: parseInt(e.target.value) || undefined }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. 100\" />\n </div>\n </div>\n )}\n \n {activeField?.type === 'date' && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Date Mode</label>\n <select value={activeField?.dateFormat || 'date'} onChange={e => setActiveField(prev => ({ ...prev, dateFormat: e.target.value }))} className={cn(inputClass, 'w-full rounded-none cursor-pointer')}>\n <option value=\"date\">Date Only</option>\n <option value=\"datetime\">Date & Time</option>\n <option value=\"time\">Time Only</option>\n </select>\n </div>\n </div>\n )}\n </div>\n )}\n\n {settingsTab === 'ADMIN' && (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 bg-z-hover p-4 rounded-none border border-z-border\">\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.i18n} onChange={e => setActiveField(prev => ({ ...prev, i18n: e.target.checked }))} className=\"accent-z-accent w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Enable Localization (i18n)</span>\n </label>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.admin?.hidden} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, hidden: e.target.checked } }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Hidden in UI</span>\n </label>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={!!activeField?.admin?.readOnly} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, readOnly: e.target.checked } }))} className=\"accent-gray-500 w-4 h-4\" />\n <span className=\"text-xs font-bold text-z-secondary\">Read-Only</span>\n </label>\n </div>\n\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Field Width</label>\n <select value={activeField?.admin?.width || '100%'} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, width: e.target.value } }))} className={cn(inputClass, 'w-full rounded-none cursor-pointer')}>\n <option value=\"100%\">100% (Full Width)</option>\n <option value=\"50%\">50% (Half Width)</option>\n <option value=\"33%\">33% (One Third)</option>\n <option value=\"25%\">25% (One Quarter)</option>\n </select>\n </div>\n <div>\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Placeholder</label>\n <input type=\"text\" value={activeField?.admin?.placeholder || ''} onChange={e => setActiveField(prev => ({ ...prev, admin: { ...prev.admin, placeholder: e.target.value } }))} className={cn(inputClass, 'w-full rounded-none')} placeholder=\"e.g. Enter a value...\" />\n </div>\n \n <div className=\"col-span-2\">\n <label className=\"text-sm font-semibold text-z-secondary block mb-1.5\">Conditional Visibility JSON</label>\n <textarea rows={3} value={activeField?.admin?.condition ? JSON.stringify(activeField.admin.condition) : ''} onChange={e => {\n try {\n const parsed = e.target.value ? JSON.parse(e.target.value) : undefined;\n setActiveField(prev => ({ ...prev, admin: { ...prev.admin, condition: parsed } }))\n } catch { /* invalid JSON */ }\n }} className={cn(inputClass, 'w-full rounded-none font-mono')} placeholder='{\"field\": \"theme\", \"equals\": \"dark\"}' />\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n\n <div className=\"px-6 py-4 border-t border-z-border bg-app/50 flex justify-between\">\n {modalStep === 'SETTINGS' ? (\n <button onClick={() => setModalStep('TYPE')} className=\"px-4 py-2 text-sm font-bold text-z-muted hover:text-z-primary transition-colors\">\n ← Back to Types\n </button>\n ) : <div />}\n {modalStep === 'SETTINGS' && (\n <button onClick={handleFieldSubmit} className=\"px-6 py-2 bg-z-accent hover:brightness-110 text-z-logo-text text-sm font-semibold rounded-none transition-all shadow-sm\">\n {editingFieldIndex !== null ? 'Update Field' : 'Add Field'}\n </button>\n )}\n </div>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{C as t,E as n,F as r,G as i,Hn as a,Ln as o,Mt as s,Q as c,T as l,an as u,hr as d,ir as ee,l as f,mr as p,rr as m,sn as h,u as g,vr as _,w as te,xr as v,zt as ne}from"./vendor-react-DQVTOTFO.js";import{a as y,o as b,t as x}from"./utils-fgvbH6CB.js";import{_ as re,p as S}from"./index-
|
|
1
|
+
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{C as t,E as n,F as r,G as i,Hn as a,Ln as o,Mt as s,Q as c,T as l,an as u,hr as d,ir as ee,l as f,mr as p,rr as m,sn as h,u as g,vr as _,w as te,xr as v,zt as ne}from"./vendor-react-DQVTOTFO.js";import{a as y,o as b,t as x}from"./utils-fgvbH6CB.js";import{_ as re,p as S}from"./index-yE_3fruG.js";var C=e(v(),1),w=_(),T=[{name:`beforeValidate`,label:`Before Validate`,description:`Runs before document validation. Use to sanitize or enrich input data.`,event:`beforeValidate`,hasReturn:!0},{name:`beforeCreate`,label:`Before Create`,description:`Runs after validation, before document is saved. Use to set computed fields.`,event:`beforeCreate`,hasReturn:!0},{name:`afterCreate`,label:`After Create`,description:`Runs after document is created. Use for side effects like notifications.`,event:`afterCreate`,hasReturn:!1},{name:`beforeUpdate`,label:`Before Update`,description:`Runs after validation, before document is updated.`,event:`beforeUpdate`,hasReturn:!0},{name:`afterUpdate`,label:`After Update`,description:`Runs after document is updated. Use for cache invalidation, sync.`,event:`afterUpdate`,hasReturn:!1},{name:`beforeDelete`,label:`Before Delete`,description:`Runs before document deletion. Use to prevent deletion or cascade.`,event:`beforeDelete`,hasReturn:!1},{name:`afterDelete`,label:`After Delete`,description:`Runs after document is deleted. Use for cleanup.`,event:`afterDelete`,hasReturn:!1},{name:`afterRead`,label:`After Read`,description:`Runs after document is read. Use to transform output data.`,event:`afterRead`,hasReturn:!0},{name:`afterError`,label:`After Error`,description:`Runs when an error occurs during any lifecycle event.`,event:`afterError`,hasReturn:!1}],E=[`get`,`post`,`put`,`patch`,`delete`],D=`(data, user, context) => {
|
|
2
2
|
// Your hook logic here
|
|
3
3
|
// data: the document data being processed
|
|
4
4
|
// user: the authenticated user performing the action
|
package/dist/assets/{CollectionHooksPage-EFkVZNrc.js.map → CollectionHooksPage-DIaSrKDj.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollectionHooksPage-EFkVZNrc.js","names":[],"sources":["../../src/pages/CollectionHooksPage.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback } from 'react'\nimport { useParams, useNavigate, Link } from 'react-router-dom'\nimport {\n ArrowLeft,\n Save,\n Loader2,\n Code2,\n Plus,\n Trash2,\n Shield,\n Globe,\n Zap,\n ChevronDown,\n ChevronRight,\n FileCode,\n Terminal,\n ToggleLeft,\n ToggleRight,\n} from 'lucide-react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { cn } from '../lib/utils'\nimport api from '../lib/api'\nimport toast from 'react-hot-toast'\nimport { useTheme } from '../context/ThemeContext'\nimport { useSystemMetadata } from '../hooks/useQueries'\nimport { PageHeader } from '../components/ui/PageHeader'\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\ninterface HookEntry {\n name: string\n label: string\n description: string\n event: string\n hasReturn: boolean\n}\n\ninterface EndpointEntry {\n path: string\n method: 'get' | 'post' | 'put' | 'patch' | 'delete'\n description: string\n}\n\ninterface CollectionConfig {\n slug: string\n name: string\n hooks?: Record<string, string>\n endpoints?: EndpointEntry[]\n access?: Record<string, string>\n publicRead?: boolean\n}\n\n// ── Available hooks ───────────────────────────────────────────────────────────\n\nconst COLLECTION_HOOKS: HookEntry[] = [\n { name: 'beforeValidate', label: 'Before Validate', description: 'Runs before document validation. Use to sanitize or enrich input data.', event: 'beforeValidate', hasReturn: true },\n { name: 'beforeCreate', label: 'Before Create', description: 'Runs after validation, before document is saved. Use to set computed fields.', event: 'beforeCreate', hasReturn: true },\n { name: 'afterCreate', label: 'After Create', description: 'Runs after document is created. Use for side effects like notifications.', event: 'afterCreate', hasReturn: false },\n { name: 'beforeUpdate', label: 'Before Update', description: 'Runs after validation, before document is updated.', event: 'beforeUpdate', hasReturn: true },\n { name: 'afterUpdate', label: 'After Update', description: 'Runs after document is updated. Use for cache invalidation, sync.', event: 'afterUpdate', hasReturn: false },\n { name: 'beforeDelete', label: 'Before Delete', description: 'Runs before document deletion. Use to prevent deletion or cascade.', event: 'beforeDelete', hasReturn: false },\n { name: 'afterDelete', label: 'After Delete', description: 'Runs after document is deleted. Use for cleanup.', event: 'afterDelete', hasReturn: false },\n { name: 'afterRead', label: 'After Read', description: 'Runs after document is read. Use to transform output data.', event: 'afterRead', hasReturn: true },\n { name: 'afterError', label: 'After Error', description: 'Runs when an error occurs during any lifecycle event.', event: 'afterError', hasReturn: false },\n]\n\nconst HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete'] as const\n\nconst HOOK_TEMPLATE = `(data, user, context) => {\n // Your hook logic here\n // data: the document data being processed\n // user: the authenticated user performing the action\n // context: { hookType: string /* additional context */ }\n return data;\n}`\n\n// const ENDPOINT_TEMPLATE = `(req, res) => {\n// // Custom endpoint logic\n// // req: Express request object (includes zenith adapter via req.zenith.adapter)\n// // res: Express response object\n// res.json({ message: 'Hello from custom endpoint' });\n// }`\n\n// ── Code Editor Component ─────────────────────────────────────────────────────\n\ninterface CodeEditorProps {\n value: string\n onChange: (value: string) => void\n theme: 'light' | 'dark'\n height?: string\n}\n\nconst CodeEditor: React.FC<CodeEditorProps> = ({ value, onChange, theme, height = '160px' }) => {\n return (\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n spellCheck={false}\n className={cn(\n 'w-full border rounded-none-none px-4 py-3 font-mono text-sm leading-relaxed resize-y outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all',\n theme === 'dark'\n ? 'bg-app border-z-border text-z-secondary focus:border-z-border/50'\n : 'bg-z-accent border-z-border text-z-secondary focus:border-z-border'\n )}\n style={{ minHeight: height, fontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace' }}\n />\n )\n}\n\n// ── Main Component ────────────────────────────────────────────────────────────\n\nconst CollectionHooksPage: React.FC = () => {\n const { slug } = useParams<{ slug: string }>()\n const navigate = useNavigate()\n const { theme } = useTheme()\n\n const [collection, setCollection] = useState<CollectionConfig | null>(null)\n const [loading, setLoading] = useState(true)\n const [saving, setSaving] = useState(false)\n const [expandedHook, setExpandedHook] = useState<string | null>(null)\n\n // Local state for hooks and endpoints\n const [hooks, setHooks] = useState<Record<string, string>>({})\n const [endpoints, setEndpoints] = useState<EndpointEntry[]>([])\n const [publicRead, setPublicRead] = useState(false)\n\n // Dirty tracking\n const [originalHooks, setOriginalHooks] = useState<Record<string, string>>({})\n const [originalEndpoints, setOriginalEndpoints] = useState<EndpointEntry[]>([])\n const [originalPublicRead, setOriginalPublicRead] = useState(false)\n\n const isDirty = () => {\n return JSON.stringify(hooks) !== JSON.stringify(originalHooks) ||\n JSON.stringify(endpoints) !== JSON.stringify(originalEndpoints) ||\n publicRead !== originalPublicRead\n }\n\n // Field-level hooks state (unused, commented out to fix TS6133)\n // const [fieldHooks, setFieldHooks] = useState<Record<string, { beforeChange: string; afterRead: string; validate: string }>>({})\n // const [originalFieldHooks, setOriginalFieldHooks] = useState<Record<string, { beforeChange: string; afterRead: string; validate: string }>>({})\n\n const [fields, setFields] = useState<Array<{ name: string; type: string; label?: string }>>([])\n\n const { data: healthData, isLoading: healthLoading } = useSystemMetadata()\n\n const fetchCollectionConfig = useCallback(async () => {\n if (!healthData) return\n setLoading(true)\n try {\n // Use healthData which comes from the tenant-isolated useSystemMetadata hook\n const cols = healthData.collections || []\n const col = cols.find((c: any) => c.slug === slug)\n\n if (!col) {\n toast.error('Collection not found')\n navigate('/collections')\n return\n }\n\n const hooksConfig = col.hooks || {}\n const endpointsConfig = col.endpoints || []\n\n setCollection({ slug: col.slug, name: col.label || col.name || col.slug, hooks: hooksConfig, endpoints: endpointsConfig, access: col.access, publicRead: !!col.publicRead })\n setHooks(hooksConfig)\n setEndpoints(endpointsConfig)\n setPublicRead(!!col.publicRead)\n setOriginalHooks(hooksConfig)\n setOriginalEndpoints(endpointsConfig)\n setOriginalPublicRead(!!col.publicRead)\n\n // Extract fields and their hooks\n const colFields = (col.fields || []).filter((f: any) => !['row', 'tabs', 'ui', 'collapsible'].includes(f.type))\n setFields(colFields.map((f: any) => ({ name: f.name, type: f.type, label: f.label || f.name })))\n\n const fh: any = {}\n colFields.forEach((f: any) => {\n if (f.hooks) {\n fh[f.name] = {\n beforeChange: f.hooks.beforeChange || '',\n afterRead: f.hooks.afterRead || '',\n validate: f.hooks.validate || '',\n }\n }\n })\n // setFieldHooks(fh)\n // setOriginalFieldHooks(fh)\n } catch (err) {\n console.error('Failed to load collection config', err)\n toast.error('Failed to load collection configuration')\n } finally {\n setLoading(false)\n }\n }, [slug, navigate, healthData])\n\n useEffect(() => {\n if (!healthLoading) {\n fetchCollectionConfig()\n }\n }, [fetchCollectionConfig, healthData, healthLoading])\n\n const handleSave = async () => {\n if (!isDirty()) return\n setSaving(true)\n try {\n await api.patch(`/system/collections/${slug}`, {\n hooks,\n endpoints,\n publicRead,\n })\n setOriginalHooks(hooks)\n setOriginalEndpoints(endpoints)\n setOriginalPublicRead(publicRead)\n toast.success('Collection configuration saved')\n } catch (err: any) {\n toast.error(err?.response?.data?.error || 'Failed to save configuration')\n } finally {\n setSaving(false)\n }\n }\n\n const handleAddHook = (hookName: string) => {\n if (hooks[hookName]) return\n setHooks(prev => ({\n ...prev,\n [hookName]: HOOK_TEMPLATE,\n }))\n setExpandedHook(hookName)\n }\n\n const handleUpdateHook = (hookName: string, code: string) => {\n setHooks(prev => ({ ...prev, [hookName]: code }))\n }\n\n const handleRemoveHook = (hookName: string) => {\n setHooks(prev => {\n const next = { ...prev }\n delete next[hookName]\n return next\n })\n if (expandedHook === hookName) setExpandedHook(null)\n }\n\n const handleAddEndpoint = () => {\n setEndpoints(prev => [...prev, { path: '', method: 'get', description: '' }])\n }\n\n const handleUpdateEndpoint = (idx: number, key: keyof EndpointEntry, value: string) => {\n setEndpoints(prev => prev.map((e, i) => i === idx ? { ...e, [key]: value } : e))\n }\n\n const handleRemoveEndpoint = (idx: number) => {\n setEndpoints(prev => prev.filter((_, i) => i !== idx))\n }\n\n const activeHooks = COLLECTION_HOOKS.filter(h => hooks[h.name])\n\n if (loading) {\n return (\n <div className=\"min-h-[80vh] flex items-center justify-center\">\n <Loader2 size={32} className=\"text-z-secondary animate-spin\" />\n </div>\n )\n }\n\n return (\n <div className=\"flex flex-col h-[calc(100vh-64px)] overflow-hidden\">\n <PageHeader\n title={`${slug} hooks`}\n actions={\n <button\n onClick={handleSave}\n disabled={saving || !isDirty()}\n className=\"flex items-center justify-center gap-3 px-8 py-4 rounded-none-none text-sm font-semibold transition-all shadow-sm active:scale-95 disabled:opacity-50 bg-z-accent text-z-logo-text hover:bg-z-accent\"\n >\n {saving ? <Loader2 size={14} className=\"animate-spin\" /> : <Save size={14} />}\n Save Configuration\n </button>\n }\n />\n <div className={cn(\n 'flex-1 overflow-y-auto p-6 md:p-10 space-y-8 transition-colors duration-500',\n theme === 'dark' ? 'bg-app text-z-primary' : 'bg-[#fafafa] text-z-primary'\n )}>\n <div className=\"max-w-[1400px] mx-auto space-y-8\">\n <div className=\"grid grid-cols-1 xl:grid-cols-3 gap-8\">\n {/* Sidebar: Available hooks + Settings */}\n <div className=\"xl:col-span-1 space-y-6\">\n {/* Public Read Toggle */}\n <div className={cn(\n 'p-5 border rounded-none-none',\n theme === 'dark' ? 'bg-z-panel/5 border-z-border' : 'bg-z-panel border-z-border shadow-sm'\n )}>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Globe size={14} className=\"text-z-secondary\" />\n <span className=\"text-sm font-semibold\">Public Read Access</span>\n </div>\n <button\n onClick={() => setPublicRead(!publicRead)}\n className=\"text-z-secondary hover:text-z-secondary transition-colors\"\n >\n {publicRead ? <ToggleRight size={28} /> : <ToggleLeft size={28} className=\"text-z-secondary\" />}\n </button>\n </div>\n <p className=\"text-sm text-z-secondary font-bold mt-2\">\n Allow unauthenticated access to read this collection\n </p>\n </div>\n\n {/* Available hooks to add */}\n <div className={cn(\n 'border rounded-none-none overflow-hidden',\n theme === 'dark' ? 'bg-z-panel/5 border-z-border' : 'bg-z-panel border-z-border shadow-sm'\n )}>\n <div className=\"px-5 py-3 border-b border-z-border\">\n <span className=\"text-sm font-semibold text-z-muted\">Available Lifecycle Hooks</span>\n </div>\n <div className=\"divide-y divide-z-border\">\n {COLLECTION_HOOKS.map(hook => {\n const isActive = !!hooks[hook.name]\n return (\n <div\n key={hook.name}\n className={cn(\n 'px-5 py-3 flex items-center justify-between transition-colors',\n isActive\n ? 'bg-z-hover'\n : theme === 'dark' ? 'hover:bg-z-panel' : 'hover:bg-[var(--z-bg-input)]'\n )}\n >\n <div className=\"flex items-center gap-2\">\n {isActive && <div className=\"w-1.5 h-1.5 rounded-none-none bg-z-border\" />}\n <span className={cn(\n 'text-sm font-semibold ',\n isActive ? 'text-z-secondary' : 'text-z-secondary'\n )}>\n {hook.label}\n </span>\n </div>\n {!isActive && (\n <button\n onClick={() => handleAddHook(hook.name)}\n className=\"text-z-secondary hover:text-z-secondary transition-colors\"\n title={`Add ${hook.label} hook`}\n >\n <Plus size={14} />\n </button>\n )}\n </div>\n )\n })}\n </div>\n </div>\n\n {/* Quick info */}\n <div className={cn(\n 'p-5 border rounded-none-none space-y-3',\n theme === 'dark' ? 'bg-z-panel/5 border-z-border' : 'bg-z-panel border-z-border shadow-sm'\n )}>\n <div className=\"flex items-center gap-2\">\n <Terminal size={12} className=\"text-z-secondary\" />\n <span className=\"text-sm font-semibold text-z-muted\">Runtime Info</span>\n </div>\n <div className=\"space-y-2\">\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-z-secondary font-bold\">Active Hooks</span>\n <span className=\"text-sm text-z-secondary font-semibold\">{activeHooks.length}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-z-secondary font-bold\">Custom Endpoints</span>\n <span className=\"text-sm text-z-secondary font-semibold\">{endpoints.length}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-z-secondary font-bold\">Fields</span>\n <span className=\"text-sm text-z-secondary font-semibold\">{fields.length}</span>\n </div>\n </div>\n </div>\n </div>\n\n {/* Main content: Active hooks + Endpoints */}\n <div className=\"xl:col-span-2 space-y-8\">\n {/* Collection Lifecycle Hooks */}\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-3 border-b border-z-border pb-4\">\n <Zap size={16} className=\"text-z-secondary\" />\n <h2 className=\"text-sm font-semibold\">Collection Lifecycle Hooks</h2>\n <span className=\"text-sm text-z-secondary font-bold ml-auto\">\n {activeHooks.length} active\n </span>\n </div>\n\n {activeHooks.length === 0 ? (\n <div className={cn(\n 'p-8 border border-dashed rounded-none-none text-center space-y-3',\n 'border-z-border'\n )}>\n <Code2 size={32} className=\"mx-auto text-z-secondary\" />\n <p className=\"text-sm font-semibold text-z-secondary\">\n No hooks configured\n </p>\n <p className=\"text-sm text-z-secondary\">\n Click + in the sidebar to add lifecycle hooks\n </p>\n </div>\n ) : (\n <AnimatePresence>\n {activeHooks.map(hook => {\n const isOpen = expandedHook === hook.name\n return (\n <motion.div\n key={hook.name}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n className={cn(\n 'border rounded-none-none overflow-hidden',\n theme === 'dark' ? 'bg-z-panel/5 border-z-border' : 'bg-z-panel border-z-border shadow-sm'\n )}\n >\n <button\n onClick={() => setExpandedHook(isOpen ? null : hook.name)}\n className={cn(\n 'w-full px-5 py-4 flex items-center justify-between transition-colors',\n isOpen\n ? theme === 'dark' ? 'bg-z-hover' : 'bg-[var(--z-bg-input)]'\n : theme === 'dark' ? 'hover:bg-z-panel' : 'hover:bg-[var(--z-bg-input)]'\n )}\n >\n <div className=\"flex items-center gap-3\">\n {isOpen ? <ChevronDown size={14} className=\"text-z-secondary\" /> : <ChevronRight size={14} className=\"text-z-secondary\" />}\n <FileCode size={14} className=\"text-z-secondary\" />\n <div className=\"flex flex-col items-start\">\n <span className=\"text-sm font-semibold text-z-primary\">{hook.label}</span>\n <span className=\"text-sm text-z-secondary font-bold\">{hook.event}</span>\n </div>\n </div>\n <button\n onClick={(e) => { e.stopPropagation(); handleRemoveHook(hook.name) }}\n className=\"p-2 text-z-secondary hover:text-red-400 transition-colors\"\n title=\"Remove hook\"\n >\n <Trash2 size={14} />\n </button>\n </button>\n {isOpen && (\n <div className=\"px-5 pb-5 space-y-3\">\n <p className=\"text-sm text-z-muted font-bold\">\n {hook.description}\n </p>\n <CodeEditor\n value={hooks[hook.name]}\n onChange={(code) => handleUpdateHook(hook.name, code)}\n theme={theme}\n height=\"200px\"\n />\n </div>\n )}\n </motion.div>\n )\n })}\n </AnimatePresence>\n )}\n </div>\n\n {/* Custom Endpoints */}\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between border-b border-z-border pb-4\">\n <div className=\"flex items-center gap-3\">\n <Globe size={16} className=\"text-z-secondary\" />\n <h2 className=\"text-sm font-semibold\">Custom Endpoints</h2>\n <span className=\"text-sm text-z-secondary font-bold\">\n {endpoints.length} defined\n </span>\n </div>\n <button\n onClick={handleAddEndpoint}\n className=\"flex items-center gap-2 px-3 py-1.5 border border-z-border hover:border-z-active-border hover:bg-z-hover text-sm font-semibold transition-all text-z-secondary hover:text-z-primary\"\n >\n <Plus size={10} />\n Add Endpoint\n </button>\n </div>\n\n {endpoints.length === 0 ? (\n <div className={cn(\n 'p-8 border border-dashed rounded-none-none text-center space-y-3',\n 'border-z-border'\n )}>\n <Globe size={32} className=\"mx-auto text-z-secondary\" />\n <p className=\"text-sm font-semibold text-z-secondary\">\n No custom endpoints\n </p>\n <p className=\"text-sm text-z-secondary\">\n Add custom API endpoints for this collection\n </p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n {endpoints.map((ep, idx) => (\n <div\n key={idx}\n className={cn(\n 'p-5 border rounded-none-none space-y-4',\n theme === 'dark' ? 'bg-z-panel/5 border-z-border' : 'bg-z-panel border-z-border shadow-sm'\n )}\n >\n <div className=\"flex items-center gap-3\">\n <select\n value={ep.method}\n onChange={(e) => handleUpdateEndpoint(idx, 'method', e.target.value)}\n className={cn(\n 'bg-z-input border-z-border text-z-primary text-sm font-semibold outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black py-1.5 px-3 rounded-none-none focus:border-z-active-border',\n theme === 'dark' ? 'border-z-border text-z-secondary' : 'border-z-border text-z-secondary'\n )}\n >\n {HTTP_METHODS.map(m => (\n <option key={m} value={m}>{m}</option>\n ))}\n </select>\n <input\n type=\"text\"\n value={ep.path}\n onChange={(e) => handleUpdateEndpoint(idx, 'path', e.target.value)}\n placeholder=\"/custom-path\"\n className={cn(\n 'flex-1 border rounded-none-none py-2 px-3 text-sm font-mono transition-all outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black',\n 'bg-z-input border-z-border text-z-primary focus:border-z-active-border'\n )}\n />\n <button\n onClick={() => handleRemoveEndpoint(idx)}\n className=\"p-2 text-z-secondary hover:text-red-400 transition-colors\"\n >\n <Trash2 size={14} />\n </button>\n </div>\n <input\n type=\"text\"\n value={ep.description}\n onChange={(e) => handleUpdateEndpoint(idx, 'description', e.target.value)}\n placeholder=\"Brief description of this endpoint...\"\n className={cn(\n 'w-full border rounded-none-none py-2 px-3 text-sm transition-all outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black',\n 'bg-z-input border-z-border text-z-primary focus:border-z-active-border'\n )}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Info card */}\n <div className={cn(\n 'p-6 border rounded-none-none space-y-4',\n theme === 'dark' ? 'bg-z-hover border-z-border/10' : 'bg-[var(--z-bg-input)] border-z-border'\n )}>\n <div className=\"flex items-center gap-3\">\n <Shield size={14} className=\"text-z-secondary\" />\n <span className=\"text-sm font-semibold text-z-secondary\">Developer Notes</span>\n </div>\n <ul className=\"space-y-2 text-sm text-z-muted font-bold leading-relaxed\">\n <li>• Hooks are stored as JSON configuration and executed server-side</li>\n <li>• <code className=\"text-z-secondary font-mono\">before*</code> hooks can modify data by returning the modified value</li>\n <li>• <code className=\"text-z-secondary font-mono\">after*</code> hooks are for side effects (fire-and-forget)</li>\n <li>• Custom endpoints are mounted at <code className=\"text-z-secondary font-mono\">/api/v1/{slug}/your-path</code></li>\n <li>• Access <code className=\"text-z-secondary font-mono\">req.zenith.adapter</code> for database operations</li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport default CollectionHooksPage\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CollectionHooksPage-DIaSrKDj.js","names":[],"sources":["../../src/pages/CollectionHooksPage.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback } from 'react'\nimport { useParams, useNavigate, Link } from 'react-router-dom'\nimport {\n ArrowLeft,\n Save,\n Loader2,\n Code2,\n Plus,\n Trash2,\n Shield,\n Globe,\n Zap,\n ChevronDown,\n ChevronRight,\n FileCode,\n Terminal,\n ToggleLeft,\n ToggleRight,\n} from 'lucide-react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { cn } from '../lib/utils'\nimport api from '../lib/api'\nimport toast from 'react-hot-toast'\nimport { useTheme } from '../context/ThemeContext'\nimport { useSystemMetadata } from '../hooks/useQueries'\nimport { PageHeader } from '../components/ui/PageHeader'\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\ninterface HookEntry {\n name: string\n label: string\n description: string\n event: string\n hasReturn: boolean\n}\n\ninterface EndpointEntry {\n path: string\n method: 'get' | 'post' | 'put' | 'patch' | 'delete'\n description: string\n}\n\ninterface CollectionConfig {\n slug: string\n name: string\n hooks?: Record<string, string>\n endpoints?: EndpointEntry[]\n access?: Record<string, string>\n publicRead?: boolean\n}\n\n// ── Available hooks ───────────────────────────────────────────────────────────\n\nconst COLLECTION_HOOKS: HookEntry[] = [\n { name: 'beforeValidate', label: 'Before Validate', description: 'Runs before document validation. Use to sanitize or enrich input data.', event: 'beforeValidate', hasReturn: true },\n { name: 'beforeCreate', label: 'Before Create', description: 'Runs after validation, before document is saved. Use to set computed fields.', event: 'beforeCreate', hasReturn: true },\n { name: 'afterCreate', label: 'After Create', description: 'Runs after document is created. Use for side effects like notifications.', event: 'afterCreate', hasReturn: false },\n { name: 'beforeUpdate', label: 'Before Update', description: 'Runs after validation, before document is updated.', event: 'beforeUpdate', hasReturn: true },\n { name: 'afterUpdate', label: 'After Update', description: 'Runs after document is updated. Use for cache invalidation, sync.', event: 'afterUpdate', hasReturn: false },\n { name: 'beforeDelete', label: 'Before Delete', description: 'Runs before document deletion. Use to prevent deletion or cascade.', event: 'beforeDelete', hasReturn: false },\n { name: 'afterDelete', label: 'After Delete', description: 'Runs after document is deleted. Use for cleanup.', event: 'afterDelete', hasReturn: false },\n { name: 'afterRead', label: 'After Read', description: 'Runs after document is read. Use to transform output data.', event: 'afterRead', hasReturn: true },\n { name: 'afterError', label: 'After Error', description: 'Runs when an error occurs during any lifecycle event.', event: 'afterError', hasReturn: false },\n]\n\nconst HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete'] as const\n\nconst HOOK_TEMPLATE = `(data, user, context) => {\n // Your hook logic here\n // data: the document data being processed\n // user: the authenticated user performing the action\n // context: { hookType: string /* additional context */ }\n return data;\n}`\n\n// const ENDPOINT_TEMPLATE = `(req, res) => {\n// // Custom endpoint logic\n// // req: Express request object (includes zenith adapter via req.zenith.adapter)\n// // res: Express response object\n// res.json({ message: 'Hello from custom endpoint' });\n// }`\n\n// ── Code Editor Component ─────────────────────────────────────────────────────\n\ninterface CodeEditorProps {\n value: string\n onChange: (value: string) => void\n theme: 'light' | 'dark'\n height?: string\n}\n\nconst CodeEditor: React.FC<CodeEditorProps> = ({ value, onChange, theme, height = '160px' }) => {\n return (\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n spellCheck={false}\n className={cn(\n 'w-full border rounded-none-none px-4 py-3 font-mono text-sm leading-relaxed resize-y outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all',\n theme === 'dark'\n ? 'bg-app border-z-border text-z-secondary focus:border-z-border/50'\n : 'bg-z-accent border-z-border text-z-secondary focus:border-z-border'\n )}\n style={{ minHeight: height, fontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace' }}\n />\n )\n}\n\n// ── Main Component ────────────────────────────────────────────────────────────\n\nconst CollectionHooksPage: React.FC = () => {\n const { slug } = useParams<{ slug: string }>()\n const navigate = useNavigate()\n const { theme } = useTheme()\n\n const [collection, setCollection] = useState<CollectionConfig | null>(null)\n const [loading, setLoading] = useState(true)\n const [saving, setSaving] = useState(false)\n const [expandedHook, setExpandedHook] = useState<string | null>(null)\n\n // Local state for hooks and endpoints\n const [hooks, setHooks] = useState<Record<string, string>>({})\n const [endpoints, setEndpoints] = useState<EndpointEntry[]>([])\n const [publicRead, setPublicRead] = useState(false)\n\n // Dirty tracking\n const [originalHooks, setOriginalHooks] = useState<Record<string, string>>({})\n const [originalEndpoints, setOriginalEndpoints] = useState<EndpointEntry[]>([])\n const [originalPublicRead, setOriginalPublicRead] = useState(false)\n\n const isDirty = () => {\n return JSON.stringify(hooks) !== JSON.stringify(originalHooks) ||\n JSON.stringify(endpoints) !== JSON.stringify(originalEndpoints) ||\n publicRead !== originalPublicRead\n }\n\n // Field-level hooks state (unused, commented out to fix TS6133)\n // const [fieldHooks, setFieldHooks] = useState<Record<string, { beforeChange: string; afterRead: string; validate: string }>>({})\n // const [originalFieldHooks, setOriginalFieldHooks] = useState<Record<string, { beforeChange: string; afterRead: string; validate: string }>>({})\n\n const [fields, setFields] = useState<Array<{ name: string; type: string; label?: string }>>([])\n\n const { data: healthData, isLoading: healthLoading } = useSystemMetadata()\n\n const fetchCollectionConfig = useCallback(async () => {\n if (!healthData) return\n setLoading(true)\n try {\n // Use healthData which comes from the tenant-isolated useSystemMetadata hook\n const cols = healthData.collections || []\n const col = cols.find((c: any) => c.slug === slug)\n\n if (!col) {\n toast.error('Collection not found')\n navigate('/collections')\n return\n }\n\n const hooksConfig = col.hooks || {}\n const endpointsConfig = col.endpoints || []\n\n setCollection({ slug: col.slug, name: col.label || col.name || col.slug, hooks: hooksConfig, endpoints: endpointsConfig, access: col.access, publicRead: !!col.publicRead })\n setHooks(hooksConfig)\n setEndpoints(endpointsConfig)\n setPublicRead(!!col.publicRead)\n setOriginalHooks(hooksConfig)\n setOriginalEndpoints(endpointsConfig)\n setOriginalPublicRead(!!col.publicRead)\n\n // Extract fields and their hooks\n const colFields = (col.fields || []).filter((f: any) => !['row', 'tabs', 'ui', 'collapsible'].includes(f.type))\n setFields(colFields.map((f: any) => ({ name: f.name, type: f.type, label: f.label || f.name })))\n\n const fh: any = {}\n colFields.forEach((f: any) => {\n if (f.hooks) {\n fh[f.name] = {\n beforeChange: f.hooks.beforeChange || '',\n afterRead: f.hooks.afterRead || '',\n validate: f.hooks.validate || '',\n }\n }\n })\n // setFieldHooks(fh)\n // setOriginalFieldHooks(fh)\n } catch (err) {\n console.error('Failed to load collection config', err)\n toast.error('Failed to load collection configuration')\n } finally {\n setLoading(false)\n }\n }, [slug, navigate, healthData])\n\n useEffect(() => {\n if (!healthLoading) {\n fetchCollectionConfig()\n }\n }, [fetchCollectionConfig, healthData, healthLoading])\n\n const handleSave = async () => {\n if (!isDirty()) return\n setSaving(true)\n try {\n await api.patch(`/system/collections/${slug}`, {\n hooks,\n endpoints,\n publicRead,\n })\n setOriginalHooks(hooks)\n setOriginalEndpoints(endpoints)\n setOriginalPublicRead(publicRead)\n toast.success('Collection configuration saved')\n } catch (err: any) {\n toast.error(err?.response?.data?.error || 'Failed to save configuration')\n } finally {\n setSaving(false)\n }\n }\n\n const handleAddHook = (hookName: string) => {\n if (hooks[hookName]) return\n setHooks(prev => ({\n ...prev,\n [hookName]: HOOK_TEMPLATE,\n }))\n setExpandedHook(hookName)\n }\n\n const handleUpdateHook = (hookName: string, code: string) => {\n setHooks(prev => ({ ...prev, [hookName]: code }))\n }\n\n const handleRemoveHook = (hookName: string) => {\n setHooks(prev => {\n const next = { ...prev }\n delete next[hookName]\n return next\n })\n if (expandedHook === hookName) setExpandedHook(null)\n }\n\n const handleAddEndpoint = () => {\n setEndpoints(prev => [...prev, { path: '', method: 'get', description: '' }])\n }\n\n const handleUpdateEndpoint = (idx: number, key: keyof EndpointEntry, value: string) => {\n setEndpoints(prev => prev.map((e, i) => i === idx ? { ...e, [key]: value } : e))\n }\n\n const handleRemoveEndpoint = (idx: number) => {\n setEndpoints(prev => prev.filter((_, i) => i !== idx))\n }\n\n const activeHooks = COLLECTION_HOOKS.filter(h => hooks[h.name])\n\n if (loading) {\n return (\n <div className=\"min-h-[80vh] flex items-center justify-center\">\n <Loader2 size={32} className=\"text-z-secondary animate-spin\" />\n </div>\n )\n }\n\n return (\n <div className=\"flex flex-col h-[calc(100vh-64px)] overflow-hidden\">\n <PageHeader\n title={`${slug} hooks`}\n actions={\n <button\n onClick={handleSave}\n disabled={saving || !isDirty()}\n className=\"flex items-center justify-center gap-3 px-8 py-4 rounded-none-none text-sm font-semibold transition-all shadow-sm active:scale-95 disabled:opacity-50 bg-z-accent text-z-logo-text hover:bg-z-accent\"\n >\n {saving ? <Loader2 size={14} className=\"animate-spin\" /> : <Save size={14} />}\n Save Configuration\n </button>\n }\n />\n <div className={cn(\n 'flex-1 overflow-y-auto p-6 md:p-10 space-y-8 transition-colors duration-500',\n theme === 'dark' ? 'bg-app text-z-primary' : 'bg-[#fafafa] text-z-primary'\n )}>\n <div className=\"max-w-[1400px] mx-auto space-y-8\">\n <div className=\"grid grid-cols-1 xl:grid-cols-3 gap-8\">\n {/* Sidebar: Available hooks + Settings */}\n <div className=\"xl:col-span-1 space-y-6\">\n {/* Public Read Toggle */}\n <div className={cn(\n 'p-5 border rounded-none-none',\n theme === 'dark' ? 'bg-z-panel/5 border-z-border' : 'bg-z-panel border-z-border shadow-sm'\n )}>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Globe size={14} className=\"text-z-secondary\" />\n <span className=\"text-sm font-semibold\">Public Read Access</span>\n </div>\n <button\n onClick={() => setPublicRead(!publicRead)}\n className=\"text-z-secondary hover:text-z-secondary transition-colors\"\n >\n {publicRead ? <ToggleRight size={28} /> : <ToggleLeft size={28} className=\"text-z-secondary\" />}\n </button>\n </div>\n <p className=\"text-sm text-z-secondary font-bold mt-2\">\n Allow unauthenticated access to read this collection\n </p>\n </div>\n\n {/* Available hooks to add */}\n <div className={cn(\n 'border rounded-none-none overflow-hidden',\n theme === 'dark' ? 'bg-z-panel/5 border-z-border' : 'bg-z-panel border-z-border shadow-sm'\n )}>\n <div className=\"px-5 py-3 border-b border-z-border\">\n <span className=\"text-sm font-semibold text-z-muted\">Available Lifecycle Hooks</span>\n </div>\n <div className=\"divide-y divide-z-border\">\n {COLLECTION_HOOKS.map(hook => {\n const isActive = !!hooks[hook.name]\n return (\n <div\n key={hook.name}\n className={cn(\n 'px-5 py-3 flex items-center justify-between transition-colors',\n isActive\n ? 'bg-z-hover'\n : theme === 'dark' ? 'hover:bg-z-panel' : 'hover:bg-[var(--z-bg-input)]'\n )}\n >\n <div className=\"flex items-center gap-2\">\n {isActive && <div className=\"w-1.5 h-1.5 rounded-none-none bg-z-border\" />}\n <span className={cn(\n 'text-sm font-semibold ',\n isActive ? 'text-z-secondary' : 'text-z-secondary'\n )}>\n {hook.label}\n </span>\n </div>\n {!isActive && (\n <button\n onClick={() => handleAddHook(hook.name)}\n className=\"text-z-secondary hover:text-z-secondary transition-colors\"\n title={`Add ${hook.label} hook`}\n >\n <Plus size={14} />\n </button>\n )}\n </div>\n )\n })}\n </div>\n </div>\n\n {/* Quick info */}\n <div className={cn(\n 'p-5 border rounded-none-none space-y-3',\n theme === 'dark' ? 'bg-z-panel/5 border-z-border' : 'bg-z-panel border-z-border shadow-sm'\n )}>\n <div className=\"flex items-center gap-2\">\n <Terminal size={12} className=\"text-z-secondary\" />\n <span className=\"text-sm font-semibold text-z-muted\">Runtime Info</span>\n </div>\n <div className=\"space-y-2\">\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-z-secondary font-bold\">Active Hooks</span>\n <span className=\"text-sm text-z-secondary font-semibold\">{activeHooks.length}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-z-secondary font-bold\">Custom Endpoints</span>\n <span className=\"text-sm text-z-secondary font-semibold\">{endpoints.length}</span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-sm text-z-secondary font-bold\">Fields</span>\n <span className=\"text-sm text-z-secondary font-semibold\">{fields.length}</span>\n </div>\n </div>\n </div>\n </div>\n\n {/* Main content: Active hooks + Endpoints */}\n <div className=\"xl:col-span-2 space-y-8\">\n {/* Collection Lifecycle Hooks */}\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-3 border-b border-z-border pb-4\">\n <Zap size={16} className=\"text-z-secondary\" />\n <h2 className=\"text-sm font-semibold\">Collection Lifecycle Hooks</h2>\n <span className=\"text-sm text-z-secondary font-bold ml-auto\">\n {activeHooks.length} active\n </span>\n </div>\n\n {activeHooks.length === 0 ? (\n <div className={cn(\n 'p-8 border border-dashed rounded-none-none text-center space-y-3',\n 'border-z-border'\n )}>\n <Code2 size={32} className=\"mx-auto text-z-secondary\" />\n <p className=\"text-sm font-semibold text-z-secondary\">\n No hooks configured\n </p>\n <p className=\"text-sm text-z-secondary\">\n Click + in the sidebar to add lifecycle hooks\n </p>\n </div>\n ) : (\n <AnimatePresence>\n {activeHooks.map(hook => {\n const isOpen = expandedHook === hook.name\n return (\n <motion.div\n key={hook.name}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n className={cn(\n 'border rounded-none-none overflow-hidden',\n theme === 'dark' ? 'bg-z-panel/5 border-z-border' : 'bg-z-panel border-z-border shadow-sm'\n )}\n >\n <button\n onClick={() => setExpandedHook(isOpen ? null : hook.name)}\n className={cn(\n 'w-full px-5 py-4 flex items-center justify-between transition-colors',\n isOpen\n ? theme === 'dark' ? 'bg-z-hover' : 'bg-[var(--z-bg-input)]'\n : theme === 'dark' ? 'hover:bg-z-panel' : 'hover:bg-[var(--z-bg-input)]'\n )}\n >\n <div className=\"flex items-center gap-3\">\n {isOpen ? <ChevronDown size={14} className=\"text-z-secondary\" /> : <ChevronRight size={14} className=\"text-z-secondary\" />}\n <FileCode size={14} className=\"text-z-secondary\" />\n <div className=\"flex flex-col items-start\">\n <span className=\"text-sm font-semibold text-z-primary\">{hook.label}</span>\n <span className=\"text-sm text-z-secondary font-bold\">{hook.event}</span>\n </div>\n </div>\n <button\n onClick={(e) => { e.stopPropagation(); handleRemoveHook(hook.name) }}\n className=\"p-2 text-z-secondary hover:text-red-400 transition-colors\"\n title=\"Remove hook\"\n >\n <Trash2 size={14} />\n </button>\n </button>\n {isOpen && (\n <div className=\"px-5 pb-5 space-y-3\">\n <p className=\"text-sm text-z-muted font-bold\">\n {hook.description}\n </p>\n <CodeEditor\n value={hooks[hook.name]}\n onChange={(code) => handleUpdateHook(hook.name, code)}\n theme={theme}\n height=\"200px\"\n />\n </div>\n )}\n </motion.div>\n )\n })}\n </AnimatePresence>\n )}\n </div>\n\n {/* Custom Endpoints */}\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between border-b border-z-border pb-4\">\n <div className=\"flex items-center gap-3\">\n <Globe size={16} className=\"text-z-secondary\" />\n <h2 className=\"text-sm font-semibold\">Custom Endpoints</h2>\n <span className=\"text-sm text-z-secondary font-bold\">\n {endpoints.length} defined\n </span>\n </div>\n <button\n onClick={handleAddEndpoint}\n className=\"flex items-center gap-2 px-3 py-1.5 border border-z-border hover:border-z-active-border hover:bg-z-hover text-sm font-semibold transition-all text-z-secondary hover:text-z-primary\"\n >\n <Plus size={10} />\n Add Endpoint\n </button>\n </div>\n\n {endpoints.length === 0 ? (\n <div className={cn(\n 'p-8 border border-dashed rounded-none-none text-center space-y-3',\n 'border-z-border'\n )}>\n <Globe size={32} className=\"mx-auto text-z-secondary\" />\n <p className=\"text-sm font-semibold text-z-secondary\">\n No custom endpoints\n </p>\n <p className=\"text-sm text-z-secondary\">\n Add custom API endpoints for this collection\n </p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n {endpoints.map((ep, idx) => (\n <div\n key={idx}\n className={cn(\n 'p-5 border rounded-none-none space-y-4',\n theme === 'dark' ? 'bg-z-panel/5 border-z-border' : 'bg-z-panel border-z-border shadow-sm'\n )}\n >\n <div className=\"flex items-center gap-3\">\n <select\n value={ep.method}\n onChange={(e) => handleUpdateEndpoint(idx, 'method', e.target.value)}\n className={cn(\n 'bg-z-input border-z-border text-z-primary text-sm font-semibold outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black py-1.5 px-3 rounded-none-none focus:border-z-active-border',\n theme === 'dark' ? 'border-z-border text-z-secondary' : 'border-z-border text-z-secondary'\n )}\n >\n {HTTP_METHODS.map(m => (\n <option key={m} value={m}>{m}</option>\n ))}\n </select>\n <input\n type=\"text\"\n value={ep.path}\n onChange={(e) => handleUpdateEndpoint(idx, 'path', e.target.value)}\n placeholder=\"/custom-path\"\n className={cn(\n 'flex-1 border rounded-none-none py-2 px-3 text-sm font-mono transition-all outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black',\n 'bg-z-input border-z-border text-z-primary focus:border-z-active-border'\n )}\n />\n <button\n onClick={() => handleRemoveEndpoint(idx)}\n className=\"p-2 text-z-secondary hover:text-red-400 transition-colors\"\n >\n <Trash2 size={14} />\n </button>\n </div>\n <input\n type=\"text\"\n value={ep.description}\n onChange={(e) => handleUpdateEndpoint(idx, 'description', e.target.value)}\n placeholder=\"Brief description of this endpoint...\"\n className={cn(\n 'w-full border rounded-none-none py-2 px-3 text-sm transition-all outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black',\n 'bg-z-input border-z-border text-z-primary focus:border-z-active-border'\n )}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Info card */}\n <div className={cn(\n 'p-6 border rounded-none-none space-y-4',\n theme === 'dark' ? 'bg-z-hover border-z-border/10' : 'bg-[var(--z-bg-input)] border-z-border'\n )}>\n <div className=\"flex items-center gap-3\">\n <Shield size={14} className=\"text-z-secondary\" />\n <span className=\"text-sm font-semibold text-z-secondary\">Developer Notes</span>\n </div>\n <ul className=\"space-y-2 text-sm text-z-muted font-bold leading-relaxed\">\n <li>• Hooks are stored as JSON configuration and executed server-side</li>\n <li>• <code className=\"text-z-secondary font-mono\">before*</code> hooks can modify data by returning the modified value</li>\n <li>• <code className=\"text-z-secondary font-mono\">after*</code> hooks are for side effects (fire-and-forget)</li>\n <li>• Custom endpoints are mounted at <code className=\"text-z-secondary font-mono\">/api/v1/{slug}/your-path</code></li>\n <li>• Access <code className=\"text-z-secondary font-mono\">req.zenith.adapter</code> for database operations</li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport default CollectionHooksPage\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{C as t,F as n,H as r,Hn as i,Ln as a,Q as o,Rn as s,Wt as c,cn as l,cr as ee,l as u,mr as d,rr as f,u as p,vr as m,wn as h,xr as g}from"./vendor-react-DQVTOTFO.js";import{a as _,o as v,t as y}from"./utils-fgvbH6CB.js";import{_ as te,p as ne}from"./index-C4J6QNLn.js";var b=e(g(),1),x=m(),S=()=>{let{theme:e}=_(),m=d(),[g,S]=(0,b.useState)([]),[C,w]=(0,b.useState)(!0),[T,E]=(0,b.useState)(``),[D,O]=(0,b.useState)({}),{data:k,isLoading:A}=te();(0,b.useEffect)(()=>{A||(async()=>{if(k)try{let e=await v.get(`/system/counts`).catch(()=>null);S((k.collections||[]).map(e=>({...e,label:e.label||e.name||e.slug||`Unnamed Collection`}))),O(e?.data?.data||{})}catch(e){console.error(`Critical Registry Synchronization Failure`,e),u.error(`Failed to load collections`)}finally{w(!1)}})()},[k,A]);let j=g.filter(e=>{let t=(e.label||``).toLowerCase(),n=(e.slug||``).toLowerCase(),r=T.toLowerCase();return t.includes(r)||n.includes(r)}),[M,N]=(0,b.useState)(!1),[P,F]=(0,b.useState)(``),[I,L]=(0,b.useState)(!1),[R,z]=(0,b.useState)(null),B=async()=>{if(P){L(!0),z(null);try{z((await v.post(`/system/ai-architect`,{prompt:P})).data?.data?.schema||{error:`Failed to parse schema.`})}catch{z({error:`Failed to connect to AI Architect.`})}finally{L(!1)}}},[V,H]=(0,b.useState)(!1),[U,W]=(0,b.useState)(!1),[G,K]=(0,b.useState)(``),[q,J]=(0,b.useState)(``),[Y,X]=(0,b.useState)(!0),[Z,Q]=(0,b.useState)([{name:`title`,type:`text`,required:!0,options:``,relationTo:``}]),re=e=>{K(e),J(e.toLowerCase().trim().replace(/\s+/g,`-`).replace(/[^a-z0-9-]/g,``))},ie=()=>{Q([...Z,{name:``,type:`text`,required:!1,options:``,relationTo:``}])},ae=e=>{Q(Z.filter((t,n)=>n!==e))},$=(e,t,n)=>{Q(Z.map((r,i)=>i===e?{...r,[t]:n}:r))};return C?(0,x.jsx)(`div`,{className:`flex items-center justify-center min-h-screen`,children:(0,x.jsx)(a,{className:`animate-spin text-z-secondary `,size:32})}):(0,x.jsxs)(`div`,{className:`flex flex-col h-[calc(100vh-64px)] overflow-hidden`,children:[(0,x.jsx)(ne,{title:`Content Assets`,actions:(0,x.jsxs)(`div`,{className:`flex items-center gap-4 w-full md:w-auto flex-wrap`,children:[(0,x.jsxs)(`button`,{onClick:()=>H(!0),className:`flex items-center gap-2 px-6 py-4 bg-z-accent text-z-logo-text text-sm font-semibold hover:bg-z-accent transition-colors shadow-lg shadow-sm`,children:[(0,x.jsx)(o,{size:14}),`Create Collection`]}),(0,x.jsxs)(`button`,{onClick:()=>N(!0),className:y(`flex items-center gap-2 px-6 py-4 text-sm font-semibold transition-colors`,`bg-z-panel hover:bg-z-hover text-z-primary border-z-border`),children:[(0,x.jsx)(p,{size:14,className:`text-z-active-text`}),`AI Architect`]}),(0,x.jsxs)(`div`,{className:`relative w-full md:w-80`,children:[(0,x.jsx)(r,{className:`absolute left-4 top-1/2 -translate-y-1/2 text-z-secondary`,size:14}),(0,x.jsx)(`input`,{type:`text`,placeholder:`FILTER_COLLECTIONS...`,value:T,onChange:e=>E(e.target.value),className:y(`w-full border rounded-none-none py-4 pl-12 pr-4 text-sm font-semibold transition-all outline-none `,e===`dark`?`bg-z-hover border-z-border text-z-primary focus:border-z-accent/50 focus:bg-z-hover`:`bg-z-panel border-z-border focus:border-z-accent/50`)})]})]})}),(0,x.jsxs)(`div`,{className:y(`flex-1 overflow-y-auto p-6 md:p-10 space-y-10 transition-colors duration-500`,e===`dark`?`bg-app text-z-primary`:`bg-[#fafafa] text-z-primary`),children:[(0,x.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-6`,children:[{label:`Total Records`,value:String(Object.values(D).reduce((e,t)=>e+t,0)),icon:h,sub:`Global Synchronization`},{label:`Schema Health`,value:`100%`,icon:n,sub:`Optimal Performance`},{label:`Latency`,value:`14ms`,icon:p,sub:`Neural Processing`}].map((t,n)=>(0,x.jsxs)(`div`,{className:y(`p-8 border rounded-none-none flex flex-col gap-4 transition-all relative overflow-hidden group`,e===`dark`?`bg-z-panel border-z-border`:`bg-z-panel border-z-border shadow-sm shadow-sm`),children:[(0,x.jsx)(`div`,{className:`absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity`,children:(0,x.jsx)(t.icon,{size:80})}),(0,x.jsx)(`span`,{className:`text-sm font-semibold text-z-secondary`,children:t.label}),(0,x.jsxs)(`div`,{className:`flex items-baseline gap-3`,children:[(0,x.jsx)(`span`,{className:`text-4xl font-semibold`,children:t.value}),(0,x.jsx)(`span`,{className:`text-sm font-bold text-z-secondary `,children:t.sub})]})]},n))}),(0,x.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-6`,children:j.map((e,t)=>(0,x.jsx)(f.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},transition:{delay:t*.05},children:(0,x.jsxs)(`div`,{onClick:()=>m(`/collections/${e.slug}`),className:y(`group p-8 border flex flex-col items-center text-center gap-5 transition-all duration-500 relative overflow-hidden cursor-pointer`,`bg-z-panel backdrop-blur-xl border-z-border shadow-sm hover:scale-[1.02] hover:border-z-active-border hover:shadow-premium`),children:[(0,x.jsx)(`div`,{className:`absolute inset-0 bg-gradient-to-br from-z-accent/0 to-z-accent/0 group-hover:from-z-accent/5 group-hover:to-transparent transition-all duration-500`}),(0,x.jsx)(`div`,{className:y(`w-14 h-14 rounded-full flex items-center justify-center transition-all duration-500 relative z-10`,`bg-z-hover text-z-muted group-hover:bg-z-active-bg group-hover:text-z-active-text`),children:(0,x.jsx)(s,{size:24,strokeWidth:1.5})}),(0,x.jsxs)(`div`,{className:`relative z-10 flex flex-col items-center w-full`,children:[(0,x.jsx)(`h3`,{className:`text-xl font-black tracking-tight leading-none mb-3 group-hover:text-z-active-text transition-colors duration-500`,children:e.label.replace(/-/g,` `)}),(0,x.jsx)(`div`,{className:`flex items-center justify-center mb-4`,children:(0,x.jsxs)(`span`,{className:`px-2.5 py-1 rounded-full text-[9px] font-black uppercase tracking-widest bg-z-hover text-z-primary`,children:[D[e.slug]||0,` Entries`]})}),(0,x.jsxs)(`p`,{className:`text-[11px] font-medium text-z-secondary leading-relaxed max-w-[90%]`,children:[`Manage and organize your `,e.label.toLowerCase(),` documents.`]})]}),(0,x.jsx)(`div`,{className:`w-full flex items-center justify-center pt-5 mt-auto border-t border-z-border/50 relative z-10`,children:(0,x.jsxs)(ee,{to:`/collections/${e.slug}/hooks`,onClick:e=>e.stopPropagation(),className:`flex items-center gap-1.5 text-[10px] font-black uppercase tracking-widest text-z-secondary hover:text-z-active-text transition-colors duration-300`,children:[(0,x.jsx)(i,{size:12}),`Manage Hooks`]})})]})},e.slug))}),M&&(0,x.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4`,children:(0,x.jsxs)(`div`,{className:y(`w-full max-w-3xl p-8 border shadow-2xl relative`,`bg-z-panel border-z-border`),children:[(0,x.jsx)(`button`,{onClick:()=>N(!1),className:`absolute top-4 right-4 text-z-secondary hover:text-z-primary`}),(0,x.jsxs)(`h2`,{className:`text-2xl font-semibold mb-4 flex items-center gap-2`,children:[(0,x.jsx)(p,{className:`text-z-secondary `}),` AI Schema Architect`]}),(0,x.jsx)(`p`,{className:`text-sm font-bold text-z-secondary mb-6`,children:`Describe the collection you want to create and let AI build the schema configuration.`}),(0,x.jsx)(`textarea`,{value:P,onChange:e=>F(e.target.value),placeholder:`e.g., I need a blog post collection with title, content, cover image, seo metadata, and a category dropdown...`,className:y(`w-full h-32 p-4 mb-4 font-mono text-sm border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black focus:ring-2 focus:ring-z-active-border resize-none`,e===`dark`?`bg-app border-z-border`:`bg-z-input border-z-border`)}),(0,x.jsxs)(`button`,{onClick:B,disabled:I,className:`w-full py-4 bg-z-accent hover:bg-z-base text-z-primary font-semibold flex items-center justify-center gap-2`,children:[I?(0,x.jsx)(a,{className:`animate-spin`,size:16}):(0,x.jsx)(c,{size:16}),I?`Synthesizing Architecture...`:`Generate Schema`]}),R&&(0,x.jsxs)(`div`,{className:`mt-6 border-t border-z-border pt-6`,children:[(0,x.jsx)(`p`,{className:`text-sm font-bold text-z-muted mb-2`,children:`Generated Schema Configuration (Copy to cms.config.ts)`}),(0,x.jsxs)(`div`,{className:`relative`,children:[(0,x.jsx)(`pre`,{className:`p-4 bg-[var(--z-bg-code)] text-z-muted text-xs font-mono overflow-auto max-h-64 border border-z-border`,children:JSON.stringify(R,null,2)}),(0,x.jsx)(`button`,{onClick:()=>navigator.clipboard.writeText(JSON.stringify(R,null,2)),className:`absolute top-2 right-2 px-3 py-1 bg-z-hover hover:bg-z-panel border border-z-border text-sm font-semibold text-z-primary`,children:`Copy`})]})]})]})}),V&&(0,x.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-md p-4 overflow-y-auto`,children:(0,x.jsxs)(`div`,{className:y(`w-full max-w-4xl p-10 border shadow-2xl relative my-8`,`bg-z-panel border-z-border text-z-primary`),children:[(0,x.jsx)(`button`,{onClick:()=>H(!1),className:`absolute top-6 right-6 w-8 h-8 flex items-center justify-center bg-z-hover hover:bg-z-panel rounded-none-none border border-z-border transition-colors text-z-muted hover:text-z-primary`}),(0,x.jsxs)(`h2`,{className:`text-3xl font-semibold mb-4 flex items-center gap-3`,children:[(0,x.jsx)(c,{className:`text-z-secondary animate-pulse`}),` Visual Schema Builder`]}),(0,x.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary mb-8 border-b border-z-border pb-4`,children:`Define collection specifications, fields, types, and constraints visually without writing code.`}),(0,x.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6 mb-8`,children:[(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Collection Name`}),(0,x.jsx)(`input`,{type:`text`,name:`name`,value:G,onChange:e=>re(e.target.value),placeholder:`e.g. Review`,className:y(`w-full px-4 py-3 text-sm font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all `,`bg-z-input border-z-border text-z-primary`)})]}),(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Slug`}),(0,x.jsx)(`input`,{type:`text`,name:`slug`,value:q,onChange:e=>J(e.target.value),placeholder:`e.g. reviews`,className:y(`w-full px-4 py-3 text-sm font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all lowercase `,e===`dark`?`bg-app border-z-border text-z-muted`:`bg-z-input border-z-border text-z-secondary`)})]})]}),(0,x.jsxs)(`div`,{className:`flex items-center gap-3 mb-8 px-2`,children:[(0,x.jsx)(`input`,{type:`checkbox`,id:`enable-drafts-checkbox`,checked:Y,onChange:e=>X(e.target.checked),className:`w-4 h-4 text-z-secondary focus:ring-z-active-border border-z-border-strong rounded-none-none bg-app`}),(0,x.jsx)(`label`,{htmlFor:`enable-drafts-checkbox`,className:`text-sm font-semibold text-z-muted cursor-pointer select-none`,children:`Enable Draft/Publish Workflow`})]}),(0,x.jsxs)(`div`,{className:`space-y-6`,children:[(0,x.jsxs)(`div`,{className:`flex items-center justify-between border-b border-z-border pb-3`,children:[(0,x.jsx)(`h3`,{className:`text-xs font-semibold text-z-muted`,children:`Field Definitions`}),(0,x.jsxs)(`button`,{onClick:ie,className:`px-4 py-2 border border-dashed border-z-border/30 text-z-secondary hover:bg-z-hover text-sm font-semibold transition-all flex items-center gap-2`,children:[(0,x.jsx)(o,{size:12}),` Add Field`]})]}),(0,x.jsx)(`div`,{className:`space-y-4 max-h-[30vh] overflow-y-auto pr-2 custom-scrollbar`,children:Z.map((n,r)=>(0,x.jsxs)(`div`,{className:y(`p-5 border rounded-none-none grid grid-cols-1 md:grid-cols-4 gap-4 items-center relative group/field`,e===`dark`?`bg-app border-z-border`:`bg-z-input border-z-border shadow-sm`),children:[(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Field Name`}),(0,x.jsx)(`input`,{type:`text`,name:`field-name-${r}`,value:n.name,onChange:e=>$(r,`name`,e.target.value),placeholder:`e.g. rating`,className:y(`w-full px-3 py-2 text-xs font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all lowercase font-mono`,e===`dark`?`bg-app border-z-border text-z-primary`:`bg-z-panel border-z-border`)})]}),(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Type`}),(0,x.jsxs)(`select`,{value:n.type,onChange:e=>$(r,`type`,e.target.value),className:y(`w-full px-3 py-2 text-xs font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all`,e===`dark`?`bg-app border-z-border text-z-primary`:`bg-z-panel border-z-border`),children:[(0,x.jsx)(`option`,{value:`text`,children:`Text`}),(0,x.jsx)(`option`,{value:`number`,children:`Number`}),(0,x.jsx)(`option`,{value:`richtext`,children:`Rich Text`}),(0,x.jsx)(`option`,{value:`media`,children:`Media`}),(0,x.jsx)(`option`,{value:`checkbox`,children:`Boolean`}),(0,x.jsx)(`option`,{value:`select`,children:`Dropdown Select`}),(0,x.jsx)(`option`,{value:`relationship`,children:`Relationship`})]})]}),n.type===`select`?(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Options (Comma separated)`}),(0,x.jsx)(`input`,{type:`text`,value:n.options||``,onChange:e=>$(r,`options`,e.target.value),placeholder:`e.g. red, blue, green`,className:y(`w-full px-3 py-2 text-xs font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all`,e===`dark`?`bg-app border-z-border text-z-primary`:`bg-z-panel border-z-border`)})]}):n.type===`relationship`?(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Relate To Collection`}),(0,x.jsxs)(`select`,{value:n.relationTo||``,onChange:e=>$(r,`relationTo`,e.target.value),className:y(`w-full px-3 py-2 text-xs font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all`,e===`dark`?`bg-app border-z-border text-z-primary`:`bg-z-panel border-z-border`),children:[(0,x.jsx)(`option`,{value:``,children:`Select Target...`}),(0,x.jsx)(`option`,{value:`users`,children:`Users`}),g.map(e=>(0,x.jsx)(`option`,{value:e.slug,children:e.label},e.slug))]})]}):(0,x.jsxs)(`div`,{className:`flex items-center gap-3 pt-6`,children:[(0,x.jsx)(`input`,{type:`checkbox`,id:`required-checkbox-${r}`,checked:!!n.required,onChange:e=>$(r,`required`,e.target.checked),className:`w-3.5 h-3.5 text-z-secondary focus:ring-z-active-border border-z-border-strong rounded-none-none bg-app`}),(0,x.jsx)(`label`,{htmlFor:`required-checkbox-${r}`,className:`text-sm font-semibold text-z-muted cursor-pointer select-none`,children:`Required Field`})]}),(0,x.jsx)(`div`,{className:`flex justify-end pt-5 md:pt-0`,children:(0,x.jsx)(`button`,{onClick:()=>ae(r),disabled:Z.length===1,className:`p-2 border border-transparent hover:border-red-500/30 hover:bg-red-500/5 text-z-secondary hover:text-red-500 transition-colors disabled:opacity-20`,children:(0,x.jsx)(t,{size:14})})})]},r))})]}),(0,x.jsxs)(`div`,{className:`mt-10 pt-8 border-t border-z-border flex justify-end gap-4`,children:[(0,x.jsx)(`button`,{onClick:()=>H(!1),className:y(`px-6 py-3 font-semibold text-sm transition-all leading-none border`,e===`dark`?`bg-z-hover border-z-border text-z-muted hover:text-z-primary`:`bg-z-panel border-z-border text-z-muted hover:text-z-primary`),children:`Cancel`}),(0,x.jsxs)(`button`,{onClick:async()=>{if(!G||!q||Z.length===0){u.error(`Please enter a collection name and add at least one field.`);return}if(Z.some(e=>!e.name)){u.error(`All fields must have a name.`);return}W(!0);try{await v.post(`/system/collections`,{name:G,slug:q,drafts:Y,fields:Z.map(e=>({name:e.name.toLowerCase().trim().replace(/\s+/g,`_`).replace(/[^a-z0-9_]/g,``),type:e.type,required:!!e.required,...e.type===`select`&&e.options&&{options:e.options.split(`,`).map(e=>({label:e.trim(),value:e.trim()})).filter(e=>e.value)},...e.type===`relationship`&&e.relationTo&&{relationTo:e.relationTo}}))}),u.success(`Collection created successfully! Reloading...`),H(!1),setTimeout(()=>{window.location.reload()},1500)}catch(e){u.error(e.response?.data?.message||`Failed to create collection.`)}finally{W(!1)}},disabled:U,className:`px-8 py-3 bg-z-accent hover:bg-z-base text-z-primary rounded-none-none text-sm font-semibold shadow-xl shadow-[var(--z-border)] transition-all flex items-center gap-2 leading-none`,children:[U?(0,x.jsx)(a,{size:12,className:`animate-spin`}):(0,x.jsx)(l,{size:12}),`Create Content Type`]})]})]})})]})]})};export{S as default};
|
|
1
|
+
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{C as t,F as n,H as r,Hn as i,Ln as a,Q as o,Rn as s,Wt as c,cn as l,cr as ee,l as u,mr as d,rr as f,u as p,vr as m,wn as h,xr as g}from"./vendor-react-DQVTOTFO.js";import{a as _,o as v,t as y}from"./utils-fgvbH6CB.js";import{_ as te,p as ne}from"./index-yE_3fruG.js";var b=e(g(),1),x=m(),S=()=>{let{theme:e}=_(),m=d(),[g,S]=(0,b.useState)([]),[C,w]=(0,b.useState)(!0),[T,E]=(0,b.useState)(``),[D,O]=(0,b.useState)({}),{data:k,isLoading:A}=te();(0,b.useEffect)(()=>{A||(async()=>{if(k)try{let e=await v.get(`/system/counts`).catch(()=>null);S((k.collections||[]).map(e=>({...e,label:e.label||e.name||e.slug||`Unnamed Collection`}))),O(e?.data?.data||{})}catch(e){console.error(`Critical Registry Synchronization Failure`,e),u.error(`Failed to load collections`)}finally{w(!1)}})()},[k,A]);let j=g.filter(e=>{let t=(e.label||``).toLowerCase(),n=(e.slug||``).toLowerCase(),r=T.toLowerCase();return t.includes(r)||n.includes(r)}),[M,N]=(0,b.useState)(!1),[P,F]=(0,b.useState)(``),[I,L]=(0,b.useState)(!1),[R,z]=(0,b.useState)(null),B=async()=>{if(P){L(!0),z(null);try{z((await v.post(`/system/ai-architect`,{prompt:P})).data?.data?.schema||{error:`Failed to parse schema.`})}catch{z({error:`Failed to connect to AI Architect.`})}finally{L(!1)}}},[V,H]=(0,b.useState)(!1),[U,W]=(0,b.useState)(!1),[G,K]=(0,b.useState)(``),[q,J]=(0,b.useState)(``),[Y,X]=(0,b.useState)(!0),[Z,Q]=(0,b.useState)([{name:`title`,type:`text`,required:!0,options:``,relationTo:``}]),re=e=>{K(e),J(e.toLowerCase().trim().replace(/\s+/g,`-`).replace(/[^a-z0-9-]/g,``))},ie=()=>{Q([...Z,{name:``,type:`text`,required:!1,options:``,relationTo:``}])},ae=e=>{Q(Z.filter((t,n)=>n!==e))},$=(e,t,n)=>{Q(Z.map((r,i)=>i===e?{...r,[t]:n}:r))};return C?(0,x.jsx)(`div`,{className:`flex items-center justify-center min-h-screen`,children:(0,x.jsx)(a,{className:`animate-spin text-z-secondary `,size:32})}):(0,x.jsxs)(`div`,{className:`flex flex-col h-[calc(100vh-64px)] overflow-hidden`,children:[(0,x.jsx)(ne,{title:`Content Assets`,actions:(0,x.jsxs)(`div`,{className:`flex items-center gap-4 w-full md:w-auto flex-wrap`,children:[(0,x.jsxs)(`button`,{onClick:()=>H(!0),className:`flex items-center gap-2 px-6 py-4 bg-z-accent text-z-logo-text text-sm font-semibold hover:bg-z-accent transition-colors shadow-lg shadow-sm`,children:[(0,x.jsx)(o,{size:14}),`Create Collection`]}),(0,x.jsxs)(`button`,{onClick:()=>N(!0),className:y(`flex items-center gap-2 px-6 py-4 text-sm font-semibold transition-colors`,`bg-z-panel hover:bg-z-hover text-z-primary border-z-border`),children:[(0,x.jsx)(p,{size:14,className:`text-z-active-text`}),`AI Architect`]}),(0,x.jsxs)(`div`,{className:`relative w-full md:w-80`,children:[(0,x.jsx)(r,{className:`absolute left-4 top-1/2 -translate-y-1/2 text-z-secondary`,size:14}),(0,x.jsx)(`input`,{type:`text`,placeholder:`FILTER_COLLECTIONS...`,value:T,onChange:e=>E(e.target.value),className:y(`w-full border rounded-none-none py-4 pl-12 pr-4 text-sm font-semibold transition-all outline-none `,e===`dark`?`bg-z-hover border-z-border text-z-primary focus:border-z-accent/50 focus:bg-z-hover`:`bg-z-panel border-z-border focus:border-z-accent/50`)})]})]})}),(0,x.jsxs)(`div`,{className:y(`flex-1 overflow-y-auto p-6 md:p-10 space-y-10 transition-colors duration-500`,e===`dark`?`bg-app text-z-primary`:`bg-[#fafafa] text-z-primary`),children:[(0,x.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-6`,children:[{label:`Total Records`,value:String(Object.values(D).reduce((e,t)=>e+t,0)),icon:h,sub:`Global Synchronization`},{label:`Schema Health`,value:`100%`,icon:n,sub:`Optimal Performance`},{label:`Latency`,value:`14ms`,icon:p,sub:`Neural Processing`}].map((t,n)=>(0,x.jsxs)(`div`,{className:y(`p-8 border rounded-none-none flex flex-col gap-4 transition-all relative overflow-hidden group`,e===`dark`?`bg-z-panel border-z-border`:`bg-z-panel border-z-border shadow-sm shadow-sm`),children:[(0,x.jsx)(`div`,{className:`absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity`,children:(0,x.jsx)(t.icon,{size:80})}),(0,x.jsx)(`span`,{className:`text-sm font-semibold text-z-secondary`,children:t.label}),(0,x.jsxs)(`div`,{className:`flex items-baseline gap-3`,children:[(0,x.jsx)(`span`,{className:`text-4xl font-semibold`,children:t.value}),(0,x.jsx)(`span`,{className:`text-sm font-bold text-z-secondary `,children:t.sub})]})]},n))}),(0,x.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-6`,children:j.map((e,t)=>(0,x.jsx)(f.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},transition:{delay:t*.05},children:(0,x.jsxs)(`div`,{onClick:()=>m(`/collections/${e.slug}`),className:y(`group p-8 border flex flex-col items-center text-center gap-5 transition-all duration-500 relative overflow-hidden cursor-pointer`,`bg-z-panel backdrop-blur-xl border-z-border shadow-sm hover:scale-[1.02] hover:border-z-active-border hover:shadow-premium`),children:[(0,x.jsx)(`div`,{className:`absolute inset-0 bg-gradient-to-br from-z-accent/0 to-z-accent/0 group-hover:from-z-accent/5 group-hover:to-transparent transition-all duration-500`}),(0,x.jsx)(`div`,{className:y(`w-14 h-14 rounded-full flex items-center justify-center transition-all duration-500 relative z-10`,`bg-z-hover text-z-muted group-hover:bg-z-active-bg group-hover:text-z-active-text`),children:(0,x.jsx)(s,{size:24,strokeWidth:1.5})}),(0,x.jsxs)(`div`,{className:`relative z-10 flex flex-col items-center w-full`,children:[(0,x.jsx)(`h3`,{className:`text-xl font-black tracking-tight leading-none mb-3 group-hover:text-z-active-text transition-colors duration-500`,children:e.label.replace(/-/g,` `)}),(0,x.jsx)(`div`,{className:`flex items-center justify-center mb-4`,children:(0,x.jsxs)(`span`,{className:`px-2.5 py-1 rounded-full text-[9px] font-black uppercase tracking-widest bg-z-hover text-z-primary`,children:[D[e.slug]||0,` Entries`]})}),(0,x.jsxs)(`p`,{className:`text-[11px] font-medium text-z-secondary leading-relaxed max-w-[90%]`,children:[`Manage and organize your `,e.label.toLowerCase(),` documents.`]})]}),(0,x.jsx)(`div`,{className:`w-full flex items-center justify-center pt-5 mt-auto border-t border-z-border/50 relative z-10`,children:(0,x.jsxs)(ee,{to:`/collections/${e.slug}/hooks`,onClick:e=>e.stopPropagation(),className:`flex items-center gap-1.5 text-[10px] font-black uppercase tracking-widest text-z-secondary hover:text-z-active-text transition-colors duration-300`,children:[(0,x.jsx)(i,{size:12}),`Manage Hooks`]})})]})},e.slug))}),M&&(0,x.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-sm p-4`,children:(0,x.jsxs)(`div`,{className:y(`w-full max-w-3xl p-8 border shadow-2xl relative`,`bg-z-panel border-z-border`),children:[(0,x.jsx)(`button`,{onClick:()=>N(!1),className:`absolute top-4 right-4 text-z-secondary hover:text-z-primary`}),(0,x.jsxs)(`h2`,{className:`text-2xl font-semibold mb-4 flex items-center gap-2`,children:[(0,x.jsx)(p,{className:`text-z-secondary `}),` AI Schema Architect`]}),(0,x.jsx)(`p`,{className:`text-sm font-bold text-z-secondary mb-6`,children:`Describe the collection you want to create and let AI build the schema configuration.`}),(0,x.jsx)(`textarea`,{value:P,onChange:e=>F(e.target.value),placeholder:`e.g., I need a blog post collection with title, content, cover image, seo metadata, and a category dropdown...`,className:y(`w-full h-32 p-4 mb-4 font-mono text-sm border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black focus:ring-2 focus:ring-z-active-border resize-none`,e===`dark`?`bg-app border-z-border`:`bg-z-input border-z-border`)}),(0,x.jsxs)(`button`,{onClick:B,disabled:I,className:`w-full py-4 bg-z-accent hover:bg-z-base text-z-primary font-semibold flex items-center justify-center gap-2`,children:[I?(0,x.jsx)(a,{className:`animate-spin`,size:16}):(0,x.jsx)(c,{size:16}),I?`Synthesizing Architecture...`:`Generate Schema`]}),R&&(0,x.jsxs)(`div`,{className:`mt-6 border-t border-z-border pt-6`,children:[(0,x.jsx)(`p`,{className:`text-sm font-bold text-z-muted mb-2`,children:`Generated Schema Configuration (Copy to cms.config.ts)`}),(0,x.jsxs)(`div`,{className:`relative`,children:[(0,x.jsx)(`pre`,{className:`p-4 bg-[var(--z-bg-code)] text-z-muted text-xs font-mono overflow-auto max-h-64 border border-z-border`,children:JSON.stringify(R,null,2)}),(0,x.jsx)(`button`,{onClick:()=>navigator.clipboard.writeText(JSON.stringify(R,null,2)),className:`absolute top-2 right-2 px-3 py-1 bg-z-hover hover:bg-z-panel border border-z-border text-sm font-semibold text-z-primary`,children:`Copy`})]})]})]})}),V&&(0,x.jsx)(`div`,{className:`fixed inset-0 z-50 flex items-center justify-center bg-[var(--z-bg-modal)] backdrop-blur-md p-4 overflow-y-auto`,children:(0,x.jsxs)(`div`,{className:y(`w-full max-w-4xl p-10 border shadow-2xl relative my-8`,`bg-z-panel border-z-border text-z-primary`),children:[(0,x.jsx)(`button`,{onClick:()=>H(!1),className:`absolute top-6 right-6 w-8 h-8 flex items-center justify-center bg-z-hover hover:bg-z-panel rounded-none-none border border-z-border transition-colors text-z-muted hover:text-z-primary`}),(0,x.jsxs)(`h2`,{className:`text-3xl font-semibold mb-4 flex items-center gap-3`,children:[(0,x.jsx)(c,{className:`text-z-secondary animate-pulse`}),` Visual Schema Builder`]}),(0,x.jsx)(`p`,{className:`text-sm font-semibold text-z-secondary mb-8 border-b border-z-border pb-4`,children:`Define collection specifications, fields, types, and constraints visually without writing code.`}),(0,x.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6 mb-8`,children:[(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Collection Name`}),(0,x.jsx)(`input`,{type:`text`,name:`name`,value:G,onChange:e=>re(e.target.value),placeholder:`e.g. Review`,className:y(`w-full px-4 py-3 text-sm font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all `,`bg-z-input border-z-border text-z-primary`)})]}),(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Slug`}),(0,x.jsx)(`input`,{type:`text`,name:`slug`,value:q,onChange:e=>J(e.target.value),placeholder:`e.g. reviews`,className:y(`w-full px-4 py-3 text-sm font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all lowercase `,e===`dark`?`bg-app border-z-border text-z-muted`:`bg-z-input border-z-border text-z-secondary`)})]})]}),(0,x.jsxs)(`div`,{className:`flex items-center gap-3 mb-8 px-2`,children:[(0,x.jsx)(`input`,{type:`checkbox`,id:`enable-drafts-checkbox`,checked:Y,onChange:e=>X(e.target.checked),className:`w-4 h-4 text-z-secondary focus:ring-z-active-border border-z-border-strong rounded-none-none bg-app`}),(0,x.jsx)(`label`,{htmlFor:`enable-drafts-checkbox`,className:`text-sm font-semibold text-z-muted cursor-pointer select-none`,children:`Enable Draft/Publish Workflow`})]}),(0,x.jsxs)(`div`,{className:`space-y-6`,children:[(0,x.jsxs)(`div`,{className:`flex items-center justify-between border-b border-z-border pb-3`,children:[(0,x.jsx)(`h3`,{className:`text-xs font-semibold text-z-muted`,children:`Field Definitions`}),(0,x.jsxs)(`button`,{onClick:ie,className:`px-4 py-2 border border-dashed border-z-border/30 text-z-secondary hover:bg-z-hover text-sm font-semibold transition-all flex items-center gap-2`,children:[(0,x.jsx)(o,{size:12}),` Add Field`]})]}),(0,x.jsx)(`div`,{className:`space-y-4 max-h-[30vh] overflow-y-auto pr-2 custom-scrollbar`,children:Z.map((n,r)=>(0,x.jsxs)(`div`,{className:y(`p-5 border rounded-none-none grid grid-cols-1 md:grid-cols-4 gap-4 items-center relative group/field`,e===`dark`?`bg-app border-z-border`:`bg-z-input border-z-border shadow-sm`),children:[(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Field Name`}),(0,x.jsx)(`input`,{type:`text`,name:`field-name-${r}`,value:n.name,onChange:e=>$(r,`name`,e.target.value),placeholder:`e.g. rating`,className:y(`w-full px-3 py-2 text-xs font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all lowercase font-mono`,e===`dark`?`bg-app border-z-border text-z-primary`:`bg-z-panel border-z-border`)})]}),(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Type`}),(0,x.jsxs)(`select`,{value:n.type,onChange:e=>$(r,`type`,e.target.value),className:y(`w-full px-3 py-2 text-xs font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all`,e===`dark`?`bg-app border-z-border text-z-primary`:`bg-z-panel border-z-border`),children:[(0,x.jsx)(`option`,{value:`text`,children:`Text`}),(0,x.jsx)(`option`,{value:`number`,children:`Number`}),(0,x.jsx)(`option`,{value:`richtext`,children:`Rich Text`}),(0,x.jsx)(`option`,{value:`media`,children:`Media`}),(0,x.jsx)(`option`,{value:`checkbox`,children:`Boolean`}),(0,x.jsx)(`option`,{value:`select`,children:`Dropdown Select`}),(0,x.jsx)(`option`,{value:`relationship`,children:`Relationship`})]})]}),n.type===`select`?(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Options (Comma separated)`}),(0,x.jsx)(`input`,{type:`text`,value:n.options||``,onChange:e=>$(r,`options`,e.target.value),placeholder:`e.g. red, blue, green`,className:y(`w-full px-3 py-2 text-xs font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all`,e===`dark`?`bg-app border-z-border text-z-primary`:`bg-z-panel border-z-border`)})]}):n.type===`relationship`?(0,x.jsxs)(`div`,{className:`space-y-2`,children:[(0,x.jsx)(`label`,{className:`text-sm font-semibold text-z-secondary block`,children:`Relate To Collection`}),(0,x.jsxs)(`select`,{value:n.relationTo||``,onChange:e=>$(r,`relationTo`,e.target.value),className:y(`w-full px-3 py-2 text-xs font-bold border rounded-none-none focus:ring-2 focus:ring-z-active-border outline-none focus-visible:ring-2 focus-visible:ring-z-active-border focus-visible:ring-offset-1 focus-visible:ring-offset-black transition-all`,e===`dark`?`bg-app border-z-border text-z-primary`:`bg-z-panel border-z-border`),children:[(0,x.jsx)(`option`,{value:``,children:`Select Target...`}),(0,x.jsx)(`option`,{value:`users`,children:`Users`}),g.map(e=>(0,x.jsx)(`option`,{value:e.slug,children:e.label},e.slug))]})]}):(0,x.jsxs)(`div`,{className:`flex items-center gap-3 pt-6`,children:[(0,x.jsx)(`input`,{type:`checkbox`,id:`required-checkbox-${r}`,checked:!!n.required,onChange:e=>$(r,`required`,e.target.checked),className:`w-3.5 h-3.5 text-z-secondary focus:ring-z-active-border border-z-border-strong rounded-none-none bg-app`}),(0,x.jsx)(`label`,{htmlFor:`required-checkbox-${r}`,className:`text-sm font-semibold text-z-muted cursor-pointer select-none`,children:`Required Field`})]}),(0,x.jsx)(`div`,{className:`flex justify-end pt-5 md:pt-0`,children:(0,x.jsx)(`button`,{onClick:()=>ae(r),disabled:Z.length===1,className:`p-2 border border-transparent hover:border-red-500/30 hover:bg-red-500/5 text-z-secondary hover:text-red-500 transition-colors disabled:opacity-20`,children:(0,x.jsx)(t,{size:14})})})]},r))})]}),(0,x.jsxs)(`div`,{className:`mt-10 pt-8 border-t border-z-border flex justify-end gap-4`,children:[(0,x.jsx)(`button`,{onClick:()=>H(!1),className:y(`px-6 py-3 font-semibold text-sm transition-all leading-none border`,e===`dark`?`bg-z-hover border-z-border text-z-muted hover:text-z-primary`:`bg-z-panel border-z-border text-z-muted hover:text-z-primary`),children:`Cancel`}),(0,x.jsxs)(`button`,{onClick:async()=>{if(!G||!q||Z.length===0){u.error(`Please enter a collection name and add at least one field.`);return}if(Z.some(e=>!e.name)){u.error(`All fields must have a name.`);return}W(!0);try{await v.post(`/system/collections`,{name:G,slug:q,drafts:Y,fields:Z.map(e=>({name:e.name.toLowerCase().trim().replace(/\s+/g,`_`).replace(/[^a-z0-9_]/g,``),type:e.type,required:!!e.required,...e.type===`select`&&e.options&&{options:e.options.split(`,`).map(e=>({label:e.trim(),value:e.trim()})).filter(e=>e.value)},...e.type===`relationship`&&e.relationTo&&{relationTo:e.relationTo}}))}),u.success(`Collection created successfully! Reloading...`),H(!1),setTimeout(()=>{window.location.reload()},1500)}catch(e){u.error(e.response?.data?.message||`Failed to create collection.`)}finally{W(!1)}},disabled:U,className:`px-8 py-3 bg-z-accent hover:bg-z-base text-z-primary rounded-none-none text-sm font-semibold shadow-xl shadow-[var(--z-border)] transition-all flex items-center gap-2 leading-none`,children:[U?(0,x.jsx)(a,{size:12,className:`animate-spin`}):(0,x.jsx)(l,{size:12}),`Create Content Type`]})]})]})})]})]})};export{S as default};
|