@actuate-media/cms-admin 0.4.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/dist/AdminRoot.d.ts.map +1 -1
  2. package/dist/AdminRoot.js +35 -0
  3. package/dist/AdminRoot.js.map +1 -1
  4. package/dist/actuate-admin.css +1 -1
  5. package/dist/components/Breadcrumbs.d.ts.map +1 -1
  6. package/dist/components/Breadcrumbs.js +1 -0
  7. package/dist/components/Breadcrumbs.js.map +1 -1
  8. package/dist/components/ErrorBoundary.js +1 -1
  9. package/dist/components/ErrorBoundary.js.map +1 -1
  10. package/dist/hooks/useBuilderState.d.ts +49 -0
  11. package/dist/hooks/useBuilderState.d.ts.map +1 -0
  12. package/dist/hooks/useBuilderState.js +238 -0
  13. package/dist/hooks/useBuilderState.js.map +1 -0
  14. package/dist/index.d.ts +7 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +4 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/layout/Sidebar.d.ts.map +1 -1
  19. package/dist/layout/Sidebar.js +2 -2
  20. package/dist/layout/Sidebar.js.map +1 -1
  21. package/dist/views/ForgotPassword.d.ts +5 -0
  22. package/dist/views/ForgotPassword.d.ts.map +1 -0
  23. package/dist/views/ForgotPassword.js +41 -0
  24. package/dist/views/ForgotPassword.js.map +1 -0
  25. package/dist/views/ResetPassword.d.ts +6 -0
  26. package/dist/views/ResetPassword.d.ts.map +1 -0
  27. package/dist/views/ResetPassword.js +46 -0
  28. package/dist/views/ResetPassword.js.map +1 -0
  29. package/dist/views/ScriptTagEditor.d.ts +6 -0
  30. package/dist/views/ScriptTagEditor.d.ts.map +1 -0
  31. package/dist/views/ScriptTagEditor.js +109 -0
  32. package/dist/views/ScriptTagEditor.js.map +1 -0
  33. package/dist/views/ScriptTags.d.ts +5 -0
  34. package/dist/views/ScriptTags.d.ts.map +1 -0
  35. package/dist/views/ScriptTags.js +54 -0
  36. package/dist/views/ScriptTags.js.map +1 -0
  37. package/dist/views/page-builder/AIBlockAssist.d.ts +9 -0
  38. package/dist/views/page-builder/AIBlockAssist.d.ts.map +1 -0
  39. package/dist/views/page-builder/AIBlockAssist.js +40 -0
  40. package/dist/views/page-builder/AIBlockAssist.js.map +1 -0
  41. package/dist/views/page-builder/AIGenerateDialog.d.ts +8 -0
  42. package/dist/views/page-builder/AIGenerateDialog.d.ts.map +1 -0
  43. package/dist/views/page-builder/AIGenerateDialog.js +170 -0
  44. package/dist/views/page-builder/AIGenerateDialog.js.map +1 -0
  45. package/dist/views/page-builder/BlockEditor.d.ts +11 -0
  46. package/dist/views/page-builder/BlockEditor.d.ts.map +1 -0
  47. package/dist/views/page-builder/BlockEditor.js +67 -0
  48. package/dist/views/page-builder/BlockEditor.js.map +1 -0
  49. package/dist/views/page-builder/BlockPicker.d.ts +7 -0
  50. package/dist/views/page-builder/BlockPicker.d.ts.map +1 -0
  51. package/dist/views/page-builder/BlockPicker.js +102 -0
  52. package/dist/views/page-builder/BlockPicker.js.map +1 -0
  53. package/dist/views/page-builder/BottomBar.d.ts +9 -0
  54. package/dist/views/page-builder/BottomBar.d.ts.map +1 -0
  55. package/dist/views/page-builder/BottomBar.js +13 -0
  56. package/dist/views/page-builder/BottomBar.js.map +1 -0
  57. package/dist/views/page-builder/BuilderToolbar.d.ts +21 -0
  58. package/dist/views/page-builder/BuilderToolbar.d.ts.map +1 -0
  59. package/dist/views/page-builder/BuilderToolbar.js +18 -0
  60. package/dist/views/page-builder/BuilderToolbar.js.map +1 -0
  61. package/dist/views/page-builder/ContextPanel.d.ts +20 -0
  62. package/dist/views/page-builder/ContextPanel.d.ts.map +1 -0
  63. package/dist/views/page-builder/ContextPanel.js +40 -0
  64. package/dist/views/page-builder/ContextPanel.js.map +1 -0
  65. package/dist/views/page-builder/DesignScore.d.ts +6 -0
  66. package/dist/views/page-builder/DesignScore.d.ts.map +1 -0
  67. package/dist/views/page-builder/DesignScore.js +93 -0
  68. package/dist/views/page-builder/DesignScore.js.map +1 -0
  69. package/dist/views/page-builder/NodeSettings.d.ts +12 -0
  70. package/dist/views/page-builder/NodeSettings.d.ts.map +1 -0
  71. package/dist/views/page-builder/NodeSettings.js +80 -0
  72. package/dist/views/page-builder/NodeSettings.js.map +1 -0
  73. package/dist/views/page-builder/PageBuilder.d.ts +8 -0
  74. package/dist/views/page-builder/PageBuilder.d.ts.map +1 -0
  75. package/dist/views/page-builder/PageBuilder.js +126 -0
  76. package/dist/views/page-builder/PageBuilder.js.map +1 -0
  77. package/dist/views/page-builder/PageSettings.d.ts +7 -0
  78. package/dist/views/page-builder/PageSettings.d.ts.map +1 -0
  79. package/dist/views/page-builder/PageSettings.js +27 -0
  80. package/dist/views/page-builder/PageSettings.js.map +1 -0
  81. package/dist/views/page-builder/SEOPanel.d.ts +10 -0
  82. package/dist/views/page-builder/SEOPanel.d.ts.map +1 -0
  83. package/dist/views/page-builder/SEOPanel.js +105 -0
  84. package/dist/views/page-builder/SEOPanel.js.map +1 -0
  85. package/dist/views/page-builder/SavedSections.d.ts +6 -0
  86. package/dist/views/page-builder/SavedSections.d.ts.map +1 -0
  87. package/dist/views/page-builder/SavedSections.js +145 -0
  88. package/dist/views/page-builder/SavedSections.js.map +1 -0
  89. package/dist/views/page-builder/TemplatePicker.d.ts +7 -0
  90. package/dist/views/page-builder/TemplatePicker.d.ts.map +1 -0
  91. package/dist/views/page-builder/TemplatePicker.js +68 -0
  92. package/dist/views/page-builder/TemplatePicker.js.map +1 -0
  93. package/dist/views/page-builder/block-renderers/CTAPreview.d.ts +3 -0
  94. package/dist/views/page-builder/block-renderers/CTAPreview.d.ts.map +1 -0
  95. package/dist/views/page-builder/block-renderers/CTAPreview.js +19 -0
  96. package/dist/views/page-builder/block-renderers/CTAPreview.js.map +1 -0
  97. package/dist/views/page-builder/block-renderers/CardsPreview.d.ts +3 -0
  98. package/dist/views/page-builder/block-renderers/CardsPreview.d.ts.map +1 -0
  99. package/dist/views/page-builder/block-renderers/CardsPreview.js +22 -0
  100. package/dist/views/page-builder/block-renderers/CardsPreview.js.map +1 -0
  101. package/dist/views/page-builder/block-renderers/CodePreview.d.ts +3 -0
  102. package/dist/views/page-builder/block-renderers/CodePreview.d.ts.map +1 -0
  103. package/dist/views/page-builder/block-renderers/CodePreview.js +16 -0
  104. package/dist/views/page-builder/block-renderers/CodePreview.js.map +1 -0
  105. package/dist/views/page-builder/block-renderers/FAQPreview.d.ts +3 -0
  106. package/dist/views/page-builder/block-renderers/FAQPreview.d.ts.map +1 -0
  107. package/dist/views/page-builder/block-renderers/FAQPreview.js +24 -0
  108. package/dist/views/page-builder/block-renderers/FAQPreview.js.map +1 -0
  109. package/dist/views/page-builder/block-renderers/FallbackPreview.d.ts +6 -0
  110. package/dist/views/page-builder/block-renderers/FallbackPreview.d.ts.map +1 -0
  111. package/dist/views/page-builder/block-renderers/FallbackPreview.js +7 -0
  112. package/dist/views/page-builder/block-renderers/FallbackPreview.js.map +1 -0
  113. package/dist/views/page-builder/block-renderers/FormPreview.d.ts +3 -0
  114. package/dist/views/page-builder/block-renderers/FormPreview.d.ts.map +1 -0
  115. package/dist/views/page-builder/block-renderers/FormPreview.js +14 -0
  116. package/dist/views/page-builder/block-renderers/FormPreview.js.map +1 -0
  117. package/dist/views/page-builder/block-renderers/GalleryPreview.d.ts +3 -0
  118. package/dist/views/page-builder/block-renderers/GalleryPreview.d.ts.map +1 -0
  119. package/dist/views/page-builder/block-renderers/GalleryPreview.js +21 -0
  120. package/dist/views/page-builder/block-renderers/GalleryPreview.js.map +1 -0
  121. package/dist/views/page-builder/block-renderers/HeroPreview.d.ts +3 -0
  122. package/dist/views/page-builder/block-renderers/HeroPreview.d.ts.map +1 -0
  123. package/dist/views/page-builder/block-renderers/HeroPreview.js +19 -0
  124. package/dist/views/page-builder/block-renderers/HeroPreview.js.map +1 -0
  125. package/dist/views/page-builder/block-renderers/ImagePreview.d.ts +3 -0
  126. package/dist/views/page-builder/block-renderers/ImagePreview.d.ts.map +1 -0
  127. package/dist/views/page-builder/block-renderers/ImagePreview.js +17 -0
  128. package/dist/views/page-builder/block-renderers/ImagePreview.js.map +1 -0
  129. package/dist/views/page-builder/block-renderers/TextPreview.d.ts +3 -0
  130. package/dist/views/page-builder/block-renderers/TextPreview.d.ts.map +1 -0
  131. package/dist/views/page-builder/block-renderers/TextPreview.js +26 -0
  132. package/dist/views/page-builder/block-renderers/TextPreview.js.map +1 -0
  133. package/dist/views/page-builder/block-renderers/VideoPreview.d.ts +3 -0
  134. package/dist/views/page-builder/block-renderers/VideoPreview.d.ts.map +1 -0
  135. package/dist/views/page-builder/block-renderers/VideoPreview.js +21 -0
  136. package/dist/views/page-builder/block-renderers/VideoPreview.js.map +1 -0
  137. package/dist/views/page-builder/block-renderers/index.d.ts +9 -0
  138. package/dist/views/page-builder/block-renderers/index.d.ts.map +1 -0
  139. package/dist/views/page-builder/block-renderers/index.js +25 -0
  140. package/dist/views/page-builder/block-renderers/index.js.map +1 -0
  141. package/dist/views/page-builder/canvas/BlockRenderer.d.ts +8 -0
  142. package/dist/views/page-builder/canvas/BlockRenderer.d.ts.map +1 -0
  143. package/dist/views/page-builder/canvas/BlockRenderer.js +30 -0
  144. package/dist/views/page-builder/canvas/BlockRenderer.js.map +1 -0
  145. package/dist/views/page-builder/canvas/BuilderCanvas.d.ts +10 -0
  146. package/dist/views/page-builder/canvas/BuilderCanvas.d.ts.map +1 -0
  147. package/dist/views/page-builder/canvas/BuilderCanvas.js +26 -0
  148. package/dist/views/page-builder/canvas/BuilderCanvas.js.map +1 -0
  149. package/dist/views/page-builder/canvas/ColumnRenderer.d.ts +8 -0
  150. package/dist/views/page-builder/canvas/ColumnRenderer.d.ts.map +1 -0
  151. package/dist/views/page-builder/canvas/ColumnRenderer.js +36 -0
  152. package/dist/views/page-builder/canvas/ColumnRenderer.js.map +1 -0
  153. package/dist/views/page-builder/canvas/ContainerRenderer.d.ts +8 -0
  154. package/dist/views/page-builder/canvas/ContainerRenderer.d.ts.map +1 -0
  155. package/dist/views/page-builder/canvas/ContainerRenderer.js +33 -0
  156. package/dist/views/page-builder/canvas/ContainerRenderer.js.map +1 -0
  157. package/dist/views/page-builder/canvas/RowRenderer.d.ts +8 -0
  158. package/dist/views/page-builder/canvas/RowRenderer.d.ts.map +1 -0
  159. package/dist/views/page-builder/canvas/RowRenderer.js +32 -0
  160. package/dist/views/page-builder/canvas/RowRenderer.js.map +1 -0
  161. package/dist/views/page-builder/canvas/SectionRenderer.d.ts +8 -0
  162. package/dist/views/page-builder/canvas/SectionRenderer.d.ts.map +1 -0
  163. package/dist/views/page-builder/canvas/SectionRenderer.js +54 -0
  164. package/dist/views/page-builder/canvas/SectionRenderer.js.map +1 -0
  165. package/dist/views/page-builder/canvas/index.d.ts +3 -0
  166. package/dist/views/page-builder/canvas/index.d.ts.map +1 -0
  167. package/dist/views/page-builder/canvas/index.js +2 -0
  168. package/dist/views/page-builder/canvas/index.js.map +1 -0
  169. package/package.json +7 -4
  170. package/src/AdminRoot.tsx +41 -0
  171. package/src/components/Breadcrumbs.tsx +1 -0
  172. package/src/components/ErrorBoundary.tsx +3 -3
  173. package/src/hooks/useBuilderState.ts +328 -0
  174. package/src/index.ts +8 -0
  175. package/src/layout/Sidebar.tsx +7 -0
  176. package/src/views/ForgotPassword.tsx +136 -0
  177. package/src/views/ResetPassword.tsx +192 -0
  178. package/src/views/ScriptTagEditor.tsx +361 -0
  179. package/src/views/ScriptTags.tsx +174 -0
  180. package/src/views/page-builder/AIBlockAssist.tsx +68 -0
  181. package/src/views/page-builder/AIGenerateDialog.tsx +574 -0
  182. package/src/views/page-builder/BlockEditor.tsx +352 -0
  183. package/src/views/page-builder/BlockPicker.tsx +338 -0
  184. package/src/views/page-builder/BottomBar.tsx +64 -0
  185. package/src/views/page-builder/BuilderToolbar.tsx +218 -0
  186. package/src/views/page-builder/ContextPanel.tsx +145 -0
  187. package/src/views/page-builder/DesignScore.tsx +258 -0
  188. package/src/views/page-builder/NodeSettings.tsx +515 -0
  189. package/src/views/page-builder/PageBuilder.tsx +288 -0
  190. package/src/views/page-builder/PageSettings.tsx +161 -0
  191. package/src/views/page-builder/SEOPanel.tsx +485 -0
  192. package/src/views/page-builder/SavedSections.tsx +486 -0
  193. package/src/views/page-builder/TemplatePicker.tsx +201 -0
  194. package/src/views/page-builder/block-renderers/CTAPreview.tsx +81 -0
  195. package/src/views/page-builder/block-renderers/CardsPreview.tsx +71 -0
  196. package/src/views/page-builder/block-renderers/CodePreview.tsx +46 -0
  197. package/src/views/page-builder/block-renderers/FAQPreview.tsx +90 -0
  198. package/src/views/page-builder/block-renderers/FallbackPreview.tsx +18 -0
  199. package/src/views/page-builder/block-renderers/FormPreview.tsx +69 -0
  200. package/src/views/page-builder/block-renderers/GalleryPreview.tsx +93 -0
  201. package/src/views/page-builder/block-renderers/HeroPreview.tsx +103 -0
  202. package/src/views/page-builder/block-renderers/ImagePreview.tsx +54 -0
  203. package/src/views/page-builder/block-renderers/TextPreview.tsx +81 -0
  204. package/src/views/page-builder/block-renderers/VideoPreview.tsx +78 -0
  205. package/src/views/page-builder/block-renderers/index.ts +34 -0
  206. package/src/views/page-builder/canvas/BlockRenderer.tsx +62 -0
  207. package/src/views/page-builder/canvas/BuilderCanvas.tsx +90 -0
  208. package/src/views/page-builder/canvas/ColumnRenderer.tsx +86 -0
  209. package/src/views/page-builder/canvas/ContainerRenderer.tsx +71 -0
  210. package/src/views/page-builder/canvas/RowRenderer.tsx +72 -0
  211. package/src/views/page-builder/canvas/SectionRenderer.tsx +97 -0
  212. package/src/views/page-builder/canvas/index.ts +2 -0
@@ -0,0 +1,174 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+ import { Code2, Plus, Loader2, AlertTriangle } from 'lucide-react';
5
+ import { toast } from 'sonner';
6
+ import { useApiData } from '../lib/useApiData.js';
7
+ import { cmsApi } from '../lib/api.js';
8
+
9
+ interface ScriptTag {
10
+ id: string;
11
+ name: string;
12
+ code: string;
13
+ placement: string;
14
+ scope: string;
15
+ targetPaths: string[];
16
+ priority: number;
17
+ enabled: boolean;
18
+ createdAt: string;
19
+ updatedAt: string;
20
+ }
21
+
22
+ export interface ScriptTagsProps {
23
+ onNavigate?: (path: string) => void;
24
+ }
25
+
26
+ const PLACEMENT_LABELS: Record<string, string> = {
27
+ head: 'Head',
28
+ body_open: 'Body Open',
29
+ body_close: 'Body Close',
30
+ };
31
+
32
+ const PLACEMENT_COLORS: Record<string, string> = {
33
+ head: 'bg-purple-100 text-purple-700',
34
+ body_open: 'bg-blue-100 text-blue-700',
35
+ body_close: 'bg-green-100 text-green-700',
36
+ };
37
+
38
+ function scopeLabel(tag: ScriptTag): string {
39
+ if (tag.scope === 'site') return 'Entire Site';
40
+ if (tag.scope === 'parents') {
41
+ const count = tag.targetPaths?.length ?? 0;
42
+ return `${count} parent path${count !== 1 ? 's' : ''} + children`;
43
+ }
44
+ if (tag.scope === 'urls') {
45
+ const count = tag.targetPaths?.length ?? 0;
46
+ return `${count} URL${count !== 1 ? 's' : ''}`;
47
+ }
48
+ return tag.scope;
49
+ }
50
+
51
+ export function ScriptTags({ onNavigate }: ScriptTagsProps) {
52
+ const { data, loading, error, refetch } = useApiData<ScriptTag[]>('/script-tags');
53
+ const [togglingId, setTogglingId] = useState<string | null>(null);
54
+
55
+ const tags = data ?? [];
56
+
57
+ const toggleEnabled = async (tag: ScriptTag) => {
58
+ setTogglingId(tag.id);
59
+ const res = await cmsApi(`/script-tags/${tag.id}`, {
60
+ method: 'PUT',
61
+ body: JSON.stringify({ enabled: !tag.enabled }),
62
+ });
63
+ setTogglingId(null);
64
+ if (res.error) {
65
+ toast.error(res.error);
66
+ } else {
67
+ refetch();
68
+ }
69
+ };
70
+
71
+ if (loading) {
72
+ return (
73
+ <div className="p-3 pr-6 sm:p-4 sm:pr-8 flex items-center justify-center h-64">
74
+ <Loader2 className="w-6 h-6 animate-spin text-blue-600" />
75
+ </div>
76
+ );
77
+ }
78
+
79
+ return (
80
+ <div className="p-3 pr-6 sm:p-4 sm:pr-8">
81
+ {error && (
82
+ <div className="mb-4 flex items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-3">
83
+ <AlertTriangle className="w-5 h-5 text-red-600 shrink-0" />
84
+ <span className="text-sm text-red-800 flex-1">{error}</span>
85
+ <button onClick={refetch} className="px-3 py-1 text-sm text-red-700 border border-red-300 rounded-lg hover:bg-red-100 transition-colors">Retry</button>
86
+ </div>
87
+ )}
88
+
89
+ <div className="mb-4 flex items-center justify-between">
90
+ <div>
91
+ <h1 className="mb-1 text-2xl font-semibold text-gray-900">Script Tags</h1>
92
+ <p className="text-sm text-gray-600">Manage tracking codes, analytics, and custom scripts injected into your site</p>
93
+ </div>
94
+ <button
95
+ type="button"
96
+ onClick={() => onNavigate?.('/script-tags/new')}
97
+ className="flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700"
98
+ >
99
+ <Plus className="w-4 h-4" />
100
+ New Tag
101
+ </button>
102
+ </div>
103
+
104
+ {tags.length === 0 && !error ? (
105
+ <div className="rounded-lg border border-gray-200 bg-white p-12 text-center">
106
+ <Code2 className="mx-auto mb-3 h-10 w-10 text-gray-300" />
107
+ <h3 className="text-sm font-semibold text-gray-900">No script tags yet</h3>
108
+ <p className="mt-1 text-sm text-gray-500">
109
+ Add tracking codes like Google Analytics, Tag Manager, or Facebook Pixel.
110
+ </p>
111
+ <button
112
+ type="button"
113
+ onClick={() => onNavigate?.('/script-tags/new')}
114
+ className="mt-4 inline-flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700"
115
+ >
116
+ <Plus className="w-4 h-4" />
117
+ Add Your First Tag
118
+ </button>
119
+ </div>
120
+ ) : (
121
+ <div className="rounded-lg border border-gray-200 bg-white overflow-hidden">
122
+ <table className="w-full text-sm">
123
+ <thead>
124
+ <tr className="border-b border-gray-200 bg-gray-50">
125
+ <th className="px-4 py-3 text-left font-medium text-gray-600">Name</th>
126
+ <th className="px-4 py-3 text-left font-medium text-gray-600">Placement</th>
127
+ <th className="px-4 py-3 text-left font-medium text-gray-600">Scope</th>
128
+ <th className="px-4 py-3 text-center font-medium text-gray-600">Priority</th>
129
+ <th className="px-4 py-3 text-center font-medium text-gray-600">Enabled</th>
130
+ </tr>
131
+ </thead>
132
+ <tbody>
133
+ {tags.map((tag) => (
134
+ <tr key={tag.id} className="border-b border-gray-100 last:border-0 hover:bg-gray-50 transition-colors">
135
+ <td className="px-4 py-3">
136
+ <button
137
+ type="button"
138
+ onClick={() => onNavigate?.(`/script-tags/${tag.id}`)}
139
+ className="font-medium text-blue-600 hover:text-blue-800 hover:underline"
140
+ >
141
+ {tag.name}
142
+ </button>
143
+ </td>
144
+ <td className="px-4 py-3">
145
+ <span className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${PLACEMENT_COLORS[tag.placement] ?? 'bg-gray-100 text-gray-700'}`}>
146
+ {PLACEMENT_LABELS[tag.placement] ?? tag.placement}
147
+ </span>
148
+ </td>
149
+ <td className="px-4 py-3 text-gray-600">{scopeLabel(tag)}</td>
150
+ <td className="px-4 py-3 text-center text-gray-600 font-mono">{tag.priority}</td>
151
+ <td className="px-4 py-3 text-center">
152
+ <button
153
+ type="button"
154
+ onClick={() => toggleEnabled(tag)}
155
+ disabled={togglingId === tag.id}
156
+ className={`relative h-6 w-11 shrink-0 rounded-full transition-colors ${tag.enabled ? 'bg-blue-600' : 'bg-gray-300'}`}
157
+ aria-pressed={tag.enabled}
158
+ >
159
+ <span
160
+ className={`absolute top-0.5 block h-5 w-5 rounded-full bg-white transition-transform ${
161
+ tag.enabled ? 'translate-x-[22px]' : 'translate-x-0.5'
162
+ }`}
163
+ />
164
+ </button>
165
+ </td>
166
+ </tr>
167
+ ))}
168
+ </tbody>
169
+ </table>
170
+ </div>
171
+ )}
172
+ </div>
173
+ );
174
+ }
@@ -0,0 +1,68 @@
1
+ 'use client';
2
+
3
+ import { useState, useCallback } from 'react';
4
+ import { Sparkles, Loader2 } from 'lucide-react';
5
+ import { toast } from 'sonner';
6
+ import { cmsApi } from '../../lib/api.js';
7
+ import type { BlockNode } from '@actuate-media/cms-core';
8
+
9
+ export interface AIBlockAssistProps {
10
+ block: BlockNode;
11
+ pageTitle?: string;
12
+ businessName?: string;
13
+ onUpdateData: (data: Record<string, unknown>) => void;
14
+ }
15
+
16
+ export function AIBlockAssist({
17
+ block,
18
+ pageTitle,
19
+ businessName,
20
+ onUpdateData,
21
+ }: AIBlockAssistProps) {
22
+ const [generating, setGenerating] = useState(false);
23
+
24
+ const handleGenerate = useCallback(async () => {
25
+ setGenerating(true);
26
+
27
+ try {
28
+ const res = await cmsApi<Record<string, unknown>>('/page-builder/generate-block', {
29
+ method: 'POST',
30
+ body: JSON.stringify({
31
+ blockType: block.settings.blockType,
32
+ variant: block.settings.variant,
33
+ pageContext: {
34
+ pageTitle,
35
+ businessName,
36
+ },
37
+ }),
38
+ });
39
+
40
+ if (res.error) {
41
+ toast.error(res.error);
42
+ } else if (res.data) {
43
+ onUpdateData(res.data);
44
+ toast.success('Content generated');
45
+ }
46
+ } catch {
47
+ toast.error('Failed to generate content');
48
+ } finally {
49
+ setGenerating(false);
50
+ }
51
+ }, [block, pageTitle, businessName, onUpdateData]);
52
+
53
+ return (
54
+ <button
55
+ onClick={handleGenerate}
56
+ disabled={generating}
57
+ className="flex items-center gap-1.5 px-2.5 py-1 text-xs text-primary hover:bg-primary/10 rounded-md transition-colors disabled:opacity-50"
58
+ title="Generate content with AI"
59
+ >
60
+ {generating ? (
61
+ <Loader2 size={12} className="animate-spin" />
62
+ ) : (
63
+ <Sparkles size={12} />
64
+ )}
65
+ {generating ? 'Generating...' : 'AI Fill'}
66
+ </button>
67
+ );
68
+ }