@questpie/admin 0.0.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/README.md +439 -424
  2. package/dist/auth-layout-M8K8_q5R.mjs +181 -0
  3. package/dist/auth-layout-M8K8_q5R.mjs.map +1 -0
  4. package/dist/bulk-upload-dialog-D7w7W1Hl.mjs +273 -0
  5. package/dist/bulk-upload-dialog-D7w7W1Hl.mjs.map +1 -0
  6. package/dist/{components/ui/card.mjs → card-BKHjBQfw.mjs} +8 -8
  7. package/dist/card-BKHjBQfw.mjs.map +1 -0
  8. package/dist/client/styles/index.css +434 -0
  9. package/dist/client-DbpZKSgH.d.mts +13585 -0
  10. package/dist/client-DbpZKSgH.d.mts.map +1 -0
  11. package/dist/client-njX1rZmi.mjs +22612 -0
  12. package/dist/client-njX1rZmi.mjs.map +1 -0
  13. package/dist/client.d.mts +3 -0
  14. package/dist/client.mjs +13 -0
  15. package/dist/content-locales-provider-BXvuIgfg.mjs +1650 -0
  16. package/dist/content-locales-provider-BXvuIgfg.mjs.map +1 -0
  17. package/dist/dashboard-page-B4PGEdc2.mjs +2500 -0
  18. package/dist/dashboard-page-B4PGEdc2.mjs.map +1 -0
  19. package/dist/dashboard-page-mCY0pgZv.mjs +3 -0
  20. package/dist/dropzone-Do3awXKd.mjs +634 -0
  21. package/dist/dropzone-Do3awXKd.mjs.map +1 -0
  22. package/dist/{views/auth/forgot-password-form.mjs → forgot-password-page-Bcp-An4Y.mjs} +87 -14
  23. package/dist/forgot-password-page-Bcp-An4Y.mjs.map +1 -0
  24. package/dist/forgot-password-page-CEwsdLwn.mjs +3 -0
  25. package/dist/index-B9Xwk4hi.d.mts +2753 -0
  26. package/dist/index-B9Xwk4hi.d.mts.map +1 -0
  27. package/dist/index.d.mts +3 -0
  28. package/dist/index.mjs +13 -0
  29. package/dist/login-page-BUnpCbCa.mjs +3 -0
  30. package/dist/login-page-CP4gA-dl.mjs +298 -0
  31. package/dist/login-page-CP4gA-dl.mjs.map +1 -0
  32. package/dist/preview-utils-BKQ9-TMa.mjs +65 -0
  33. package/dist/preview-utils-BKQ9-TMa.mjs.map +1 -0
  34. package/dist/{views/auth/reset-password-form.mjs → reset-password-page-BqfDmLxA.mjs} +111 -14
  35. package/dist/reset-password-page-BqfDmLxA.mjs.map +1 -0
  36. package/dist/reset-password-page-CufHz3h3.mjs +3 -0
  37. package/dist/runtime-6VZM878K.mjs +69 -0
  38. package/dist/runtime-6VZM878K.mjs.map +1 -0
  39. package/dist/saved-views.types-BMsz5mCy.d.mts +42 -0
  40. package/dist/saved-views.types-BMsz5mCy.d.mts.map +1 -0
  41. package/dist/server.d.mts +250 -0
  42. package/dist/server.d.mts.map +1 -0
  43. package/dist/server.mjs +832 -0
  44. package/dist/server.mjs.map +1 -0
  45. package/dist/setup-page-BNNzt_Z6.mjs +3 -0
  46. package/dist/setup-page-YAP_fzqh.mjs +264 -0
  47. package/dist/setup-page-YAP_fzqh.mjs.map +1 -0
  48. package/dist/shared.d.mts +57 -0
  49. package/dist/shared.d.mts.map +1 -0
  50. package/dist/shared.mjs +3 -0
  51. package/dist/{hooks/use-auth.mjs → use-auth-BoLmWtmU.mjs} +42 -30
  52. package/dist/use-auth-BoLmWtmU.mjs.map +1 -0
  53. package/package.json +48 -198
  54. package/.turbo/turbo-build.log +0 -108
  55. package/CHANGELOG.md +0 -10
  56. package/STATUS.md +0 -917
  57. package/VALIDATION.md +0 -602
  58. package/components.json +0 -24
  59. package/dist/__tests__/setup.mjs +0 -38
  60. package/dist/__tests__/test-utils.mjs +0 -45
  61. package/dist/__tests__/vitest.d.mjs +0 -3
  62. package/dist/components/admin-app.mjs +0 -69
  63. package/dist/components/fields/array-field.mjs +0 -190
  64. package/dist/components/fields/checkbox-field.mjs +0 -34
  65. package/dist/components/fields/custom-field.mjs +0 -32
  66. package/dist/components/fields/date-field.mjs +0 -41
  67. package/dist/components/fields/datetime-field.mjs +0 -42
  68. package/dist/components/fields/email-field.mjs +0 -37
  69. package/dist/components/fields/embedded-collection.mjs +0 -253
  70. package/dist/components/fields/field-types.mjs +0 -1
  71. package/dist/components/fields/field-utils.mjs +0 -10
  72. package/dist/components/fields/field-wrapper.mjs +0 -34
  73. package/dist/components/fields/index.mjs +0 -23
  74. package/dist/components/fields/json-field.mjs +0 -243
  75. package/dist/components/fields/locale-badge.mjs +0 -16
  76. package/dist/components/fields/number-field.mjs +0 -39
  77. package/dist/components/fields/password-field.mjs +0 -37
  78. package/dist/components/fields/relation-field.mjs +0 -104
  79. package/dist/components/fields/relation-picker.mjs +0 -229
  80. package/dist/components/fields/relation-select.mjs +0 -188
  81. package/dist/components/fields/rich-text-editor/index.mjs +0 -897
  82. package/dist/components/fields/select-field.mjs +0 -41
  83. package/dist/components/fields/switch-field.mjs +0 -34
  84. package/dist/components/fields/text-field.mjs +0 -38
  85. package/dist/components/fields/textarea-field.mjs +0 -38
  86. package/dist/components/index.mjs +0 -59
  87. package/dist/components/primitives/checkbox-input.mjs +0 -127
  88. package/dist/components/primitives/date-input.mjs +0 -303
  89. package/dist/components/primitives/index.mjs +0 -12
  90. package/dist/components/primitives/number-input.mjs +0 -104
  91. package/dist/components/primitives/select-input.mjs +0 -177
  92. package/dist/components/primitives/tag-input.mjs +0 -135
  93. package/dist/components/primitives/text-input.mjs +0 -39
  94. package/dist/components/primitives/textarea-input.mjs +0 -37
  95. package/dist/components/primitives/toggle-input.mjs +0 -31
  96. package/dist/components/primitives/types.mjs +0 -12
  97. package/dist/components/ui/accordion.mjs +0 -55
  98. package/dist/components/ui/avatar.mjs +0 -54
  99. package/dist/components/ui/badge.mjs +0 -34
  100. package/dist/components/ui/button.mjs +0 -48
  101. package/dist/components/ui/checkbox.mjs +0 -21
  102. package/dist/components/ui/combobox.mjs +0 -163
  103. package/dist/components/ui/dialog.mjs +0 -95
  104. package/dist/components/ui/dropdown-menu.mjs +0 -138
  105. package/dist/components/ui/field.mjs +0 -113
  106. package/dist/components/ui/input-group.mjs +0 -82
  107. package/dist/components/ui/input.mjs +0 -17
  108. package/dist/components/ui/label.mjs +0 -15
  109. package/dist/components/ui/popover.mjs +0 -56
  110. package/dist/components/ui/scroll-area.mjs +0 -38
  111. package/dist/components/ui/select.mjs +0 -100
  112. package/dist/components/ui/separator.mjs +0 -16
  113. package/dist/components/ui/sheet.mjs +0 -90
  114. package/dist/components/ui/sidebar.mjs +0 -387
  115. package/dist/components/ui/skeleton.mjs +0 -14
  116. package/dist/components/ui/spinner.mjs +0 -16
  117. package/dist/components/ui/switch.mjs +0 -22
  118. package/dist/components/ui/table.mjs +0 -68
  119. package/dist/components/ui/tabs.mjs +0 -48
  120. package/dist/components/ui/textarea.mjs +0 -15
  121. package/dist/components/ui/tooltip.mjs +0 -44
  122. package/dist/config/component-registry.mjs +0 -38
  123. package/dist/config/index.mjs +0 -129
  124. package/dist/hooks/admin-provider.mjs +0 -70
  125. package/dist/hooks/index.mjs +0 -7
  126. package/dist/hooks/store.mjs +0 -178
  127. package/dist/hooks/use-collection-db.mjs +0 -146
  128. package/dist/hooks/use-collection.mjs +0 -112
  129. package/dist/hooks/use-global.mjs +0 -46
  130. package/dist/hooks/use-mobile.mjs +0 -20
  131. package/dist/lib/utils.mjs +0 -10
  132. package/dist/styles/index.css +0 -336
  133. package/dist/styles/index.mjs +0 -1
  134. package/dist/utils/index.mjs +0 -9
  135. package/dist/views/auth/auth-layout.mjs +0 -52
  136. package/dist/views/auth/index.mjs +0 -6
  137. package/dist/views/auth/login-form.mjs +0 -156
  138. package/dist/views/collection/auto-form-fields.mjs +0 -525
  139. package/dist/views/collection/collection-form.mjs +0 -91
  140. package/dist/views/collection/collection-list.mjs +0 -76
  141. package/dist/views/collection/form-field.mjs +0 -42
  142. package/dist/views/collection/index.mjs +0 -6
  143. package/dist/views/common/index.mjs +0 -4
  144. package/dist/views/common/locale-switcher.mjs +0 -39
  145. package/dist/views/common/version-history.mjs +0 -272
  146. package/dist/views/index.mjs +0 -9
  147. package/dist/views/layout/admin-layout.mjs +0 -40
  148. package/dist/views/layout/admin-router.mjs +0 -95
  149. package/dist/views/layout/admin-sidebar.mjs +0 -63
  150. package/dist/views/layout/index.mjs +0 -5
  151. package/src/__tests__/setup.ts +0 -44
  152. package/src/__tests__/test-utils.tsx +0 -49
  153. package/src/__tests__/vitest.d.ts +0 -9
  154. package/src/components/admin-app.tsx +0 -221
  155. package/src/components/fields/array-field.tsx +0 -237
  156. package/src/components/fields/checkbox-field.tsx +0 -47
  157. package/src/components/fields/custom-field.tsx +0 -50
  158. package/src/components/fields/date-field.tsx +0 -65
  159. package/src/components/fields/datetime-field.tsx +0 -67
  160. package/src/components/fields/email-field.tsx +0 -51
  161. package/src/components/fields/embedded-collection.tsx +0 -315
  162. package/src/components/fields/field-types.ts +0 -162
  163. package/src/components/fields/field-utils.ts +0 -6
  164. package/src/components/fields/field-wrapper.tsx +0 -52
  165. package/src/components/fields/index.ts +0 -66
  166. package/src/components/fields/json-field.tsx +0 -440
  167. package/src/components/fields/locale-badge.tsx +0 -15
  168. package/src/components/fields/number-field.tsx +0 -57
  169. package/src/components/fields/password-field.tsx +0 -51
  170. package/src/components/fields/relation-field.tsx +0 -243
  171. package/src/components/fields/relation-picker.tsx +0 -402
  172. package/src/components/fields/relation-select.tsx +0 -327
  173. package/src/components/fields/rich-text-editor/index.tsx +0 -1337
  174. package/src/components/fields/select-field.tsx +0 -61
  175. package/src/components/fields/switch-field.tsx +0 -47
  176. package/src/components/fields/text-field.tsx +0 -55
  177. package/src/components/fields/textarea-field.tsx +0 -55
  178. package/src/components/index.ts +0 -40
  179. package/src/components/primitives/checkbox-input.tsx +0 -193
  180. package/src/components/primitives/date-input.tsx +0 -401
  181. package/src/components/primitives/index.ts +0 -24
  182. package/src/components/primitives/number-input.tsx +0 -132
  183. package/src/components/primitives/select-input.tsx +0 -296
  184. package/src/components/primitives/tag-input.tsx +0 -200
  185. package/src/components/primitives/text-input.tsx +0 -49
  186. package/src/components/primitives/textarea-input.tsx +0 -46
  187. package/src/components/primitives/toggle-input.tsx +0 -36
  188. package/src/components/primitives/types.ts +0 -235
  189. package/src/components/ui/accordion.tsx +0 -72
  190. package/src/components/ui/avatar.tsx +0 -106
  191. package/src/components/ui/badge.tsx +0 -48
  192. package/src/components/ui/button.tsx +0 -53
  193. package/src/components/ui/card.tsx +0 -94
  194. package/src/components/ui/checkbox.tsx +0 -27
  195. package/src/components/ui/combobox.tsx +0 -290
  196. package/src/components/ui/dialog.tsx +0 -151
  197. package/src/components/ui/dropdown-menu.tsx +0 -254
  198. package/src/components/ui/field.tsx +0 -227
  199. package/src/components/ui/input-group.tsx +0 -149
  200. package/src/components/ui/input.tsx +0 -20
  201. package/src/components/ui/label.tsx +0 -18
  202. package/src/components/ui/popover.tsx +0 -88
  203. package/src/components/ui/scroll-area.tsx +0 -53
  204. package/src/components/ui/select.tsx +0 -192
  205. package/src/components/ui/separator.tsx +0 -23
  206. package/src/components/ui/sheet.tsx +0 -127
  207. package/src/components/ui/sidebar.tsx +0 -723
  208. package/src/components/ui/skeleton.tsx +0 -13
  209. package/src/components/ui/spinner.tsx +0 -10
  210. package/src/components/ui/switch.tsx +0 -32
  211. package/src/components/ui/table.tsx +0 -99
  212. package/src/components/ui/tabs.tsx +0 -82
  213. package/src/components/ui/textarea.tsx +0 -18
  214. package/src/components/ui/tooltip.tsx +0 -70
  215. package/src/config/component-registry.ts +0 -190
  216. package/src/config/index.ts +0 -1099
  217. package/src/hooks/README.md +0 -269
  218. package/src/hooks/admin-provider.tsx +0 -110
  219. package/src/hooks/index.ts +0 -41
  220. package/src/hooks/store.ts +0 -248
  221. package/src/hooks/use-auth.ts +0 -168
  222. package/src/hooks/use-collection-db.ts +0 -209
  223. package/src/hooks/use-collection.ts +0 -156
  224. package/src/hooks/use-global.ts +0 -69
  225. package/src/hooks/use-mobile.ts +0 -21
  226. package/src/lib/utils.ts +0 -6
  227. package/src/styles/index.css +0 -340
  228. package/src/utils/index.ts +0 -6
  229. package/src/views/auth/auth-layout.tsx +0 -77
  230. package/src/views/auth/forgot-password-form.tsx +0 -192
  231. package/src/views/auth/index.ts +0 -21
  232. package/src/views/auth/login-form.tsx +0 -229
  233. package/src/views/auth/reset-password-form.tsx +0 -232
  234. package/src/views/collection/auto-form-fields.tsx +0 -982
  235. package/src/views/collection/collection-form.tsx +0 -186
  236. package/src/views/collection/collection-list.tsx +0 -223
  237. package/src/views/collection/form-field.tsx +0 -52
  238. package/src/views/collection/index.ts +0 -15
  239. package/src/views/common/index.ts +0 -8
  240. package/src/views/common/locale-switcher.tsx +0 -45
  241. package/src/views/common/version-history.tsx +0 -406
  242. package/src/views/index.ts +0 -25
  243. package/src/views/layout/admin-layout.tsx +0 -117
  244. package/src/views/layout/admin-router.tsx +0 -206
  245. package/src/views/layout/admin-sidebar.tsx +0 -185
  246. package/src/views/layout/index.ts +0 -12
  247. package/tsconfig.json +0 -13
  248. package/tsconfig.tsbuildinfo +0 -1
  249. package/tsdown.config.ts +0 -13
  250. package/vitest.config.ts +0 -29
@@ -1,406 +0,0 @@
1
- /**
2
- * VersionHistory Component
3
- *
4
- * Displays version history and audit log for a collection item
5
- * - Shows all versions with timestamps
6
- * - Displays who made changes
7
- * - Allows comparing versions
8
- * - Shows diff between versions
9
- * - Ability to restore previous versions
10
- */
11
-
12
- import * as React from "react";
13
- import { useQuery } from "@tanstack/react-query";
14
- import {
15
- ClockCounterClockwise,
16
- User,
17
- Clock,
18
- CaretDown,
19
- CaretRight,
20
- ArrowCounterClockwise,
21
- } from "@phosphor-icons/react";
22
- import { Button } from "../../components/ui/button";
23
- import {
24
- Card,
25
- CardContent,
26
- CardDescription,
27
- CardHeader,
28
- CardTitle,
29
- } from "../../components/ui/card";
30
- import { Badge } from "../../components/ui/badge";
31
- import { Separator } from "../../components/ui/separator";
32
- import { Spinner } from "../../components/ui/spinner";
33
- import { useAdminContext } from "../../hooks/admin-provider";
34
- import type { Questpie } from "questpie";
35
-
36
- export interface VersionHistoryProps<T extends Questpie<any>> {
37
- /**
38
- * Collection name
39
- */
40
- collection: string;
41
-
42
- /**
43
- * Item ID
44
- */
45
- itemId: string;
46
-
47
- /**
48
- * Show restore buttons
49
- */
50
- allowRestore?: boolean;
51
-
52
- /**
53
- * Callback when version is restored
54
- */
55
- onRestore?: (versionId: string) => void;
56
-
57
- /**
58
- * Custom render for version data
59
- */
60
- renderVersion?: (version: any) => React.ReactNode;
61
-
62
- /**
63
- * Show full diff or summary
64
- */
65
- showFullDiff?: boolean;
66
- }
67
-
68
- interface Version {
69
- id: string;
70
- versionNumber: number;
71
- createdAt: string;
72
- createdBy?: {
73
- id: string;
74
- name?: string;
75
- email?: string;
76
- };
77
- changes?: {
78
- field: string;
79
- oldValue: any;
80
- newValue: any;
81
- }[];
82
- action: "created" | "updated" | "deleted" | "restored";
83
- data: Record<string, any>;
84
- }
85
-
86
- export function VersionHistory<T extends Questpie<any>>({
87
- collection,
88
- itemId,
89
- allowRestore = false,
90
- onRestore,
91
- renderVersion,
92
- showFullDiff = false,
93
- }: VersionHistoryProps<T>) {
94
- const { client, locale } = useAdminContext<T>();
95
- const localeKey = locale ?? "default";
96
- const [expandedVersions, setExpandedVersions] = React.useState<Set<string>>(
97
- new Set(),
98
- );
99
-
100
- // Fetch version history
101
- const {
102
- data: versions,
103
- isLoading,
104
- error,
105
- } = useQuery({
106
- queryKey: ["version-history", collection, itemId, localeKey],
107
- queryFn: async () => {
108
- // TODO: Implement actual version history endpoint
109
- // For now, return mock data structure
110
- // const result = await client.collections[collection].getVersionHistory(itemId);
111
- // return result;
112
-
113
- // Mock data for demonstration
114
- return [
115
- {
116
- id: "v3",
117
- versionNumber: 3,
118
- createdAt: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),
119
- createdBy: {
120
- id: "user1",
121
- name: "John Doe",
122
- email: "john@example.com",
123
- },
124
- action: "updated",
125
- changes: [
126
- { field: "status", oldValue: "pending", newValue: "confirmed" },
127
- ],
128
- data: {},
129
- },
130
- {
131
- id: "v2",
132
- versionNumber: 2,
133
- createdAt: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
134
- createdBy: {
135
- id: "user2",
136
- name: "Jane Smith",
137
- email: "jane@example.com",
138
- },
139
- action: "updated",
140
- changes: [
141
- {
142
- field: "scheduledAt",
143
- oldValue: "2025-01-15T10:00:00",
144
- newValue: "2025-01-20T14:00:00",
145
- },
146
- ],
147
- data: {},
148
- },
149
- {
150
- id: "v1",
151
- versionNumber: 1,
152
- createdAt: new Date(
153
- Date.now() - 7 * 24 * 60 * 60 * 1000,
154
- ).toISOString(),
155
- createdBy: {
156
- id: "user1",
157
- name: "John Doe",
158
- email: "john@example.com",
159
- },
160
- action: "created",
161
- changes: [],
162
- data: {},
163
- },
164
- ] as Version[];
165
- },
166
- });
167
-
168
- const toggleVersion = (versionId: string) => {
169
- setExpandedVersions((prev) => {
170
- const next = new Set(prev);
171
- if (next.has(versionId)) {
172
- next.delete(versionId);
173
- } else {
174
- next.add(versionId);
175
- }
176
- return next;
177
- });
178
- };
179
-
180
- const handleRestore = (versionId: string) => {
181
- onRestore?.(versionId);
182
- };
183
-
184
- const formatDate = (dateString: string) => {
185
- const date = new Date(dateString);
186
- const now = new Date();
187
- const diffMs = now.getTime() - date.getTime();
188
- const diffMins = Math.floor(diffMs / 60000);
189
- const diffHours = Math.floor(diffMs / 3600000);
190
- const diffDays = Math.floor(diffMs / 86400000);
191
-
192
- if (diffMins < 1) return "Just now";
193
- if (diffMins < 60)
194
- return `${diffMins} minute${diffMins > 1 ? "s" : ""} ago`;
195
- if (diffHours < 24)
196
- return `${diffHours} hour${diffHours > 1 ? "s" : ""} ago`;
197
- if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? "s" : ""} ago`;
198
- return date.toLocaleDateString();
199
- };
200
-
201
- const getActionBadge = (action: Version["action"]) => {
202
- const variants: Record<Version["action"], { variant: any; label: string }> =
203
- {
204
- created: { variant: "default", label: "Created" },
205
- updated: { variant: "secondary", label: "Updated" },
206
- deleted: { variant: "destructive", label: "Deleted" },
207
- restored: { variant: "outline", label: "Restored" },
208
- };
209
-
210
- const config = variants[action];
211
- return <Badge variant={config.variant}>{config.label}</Badge>;
212
- };
213
-
214
- const formatValue = (value: any): string => {
215
- if (value === null || value === undefined) return "—";
216
- if (typeof value === "boolean") return value ? "Yes" : "No";
217
- if (typeof value === "object") return JSON.stringify(value);
218
- return String(value);
219
- };
220
-
221
- if (isLoading) {
222
- return (
223
- <Card>
224
- <CardHeader>
225
- <CardTitle className="flex items-center gap-2">
226
- <ClockCounterClockwise className="h-5 w-5" />
227
- Version History
228
- </CardTitle>
229
- </CardHeader>
230
- <CardContent className="flex items-center justify-center p-8">
231
- <Spinner className="h-6 w-6" />
232
- </CardContent>
233
- </Card>
234
- );
235
- }
236
-
237
- if (error) {
238
- return (
239
- <Card>
240
- <CardHeader>
241
- <CardTitle className="flex items-center gap-2">
242
- <ClockCounterClockwise className="h-5 w-5" />
243
- Version History
244
- </CardTitle>
245
- </CardHeader>
246
- <CardContent>
247
- <p className="text-sm text-destructive">
248
- Failed to load version history:{" "}
249
- {error instanceof Error ? error.message : "Unknown error"}
250
- </p>
251
- </CardContent>
252
- </Card>
253
- );
254
- }
255
-
256
- if (!versions || versions.length === 0) {
257
- return (
258
- <Card>
259
- <CardHeader>
260
- <CardTitle className="flex items-center gap-2">
261
- <ClockCounterClockwise className="h-5 w-5" />
262
- Version History
263
- </CardTitle>
264
- </CardHeader>
265
- <CardContent>
266
- <p className="text-sm text-muted-foreground">
267
- No version history available
268
- </p>
269
- </CardContent>
270
- </Card>
271
- );
272
- }
273
-
274
- return (
275
- <Card>
276
- <CardHeader>
277
- <CardTitle className="flex items-center gap-2">
278
- <ClockCounterClockwise className="h-5 w-5" />
279
- Version History
280
- </CardTitle>
281
- <CardDescription>
282
- {versions.length} version{versions.length !== 1 ? "s" : ""}
283
- </CardDescription>
284
- </CardHeader>
285
- <CardContent className="space-y-4">
286
- {versions.map((version, index) => {
287
- const isExpanded = expandedVersions.has(version.id);
288
- const isLatest = index === 0;
289
-
290
- return (
291
- <div key={version.id}>
292
- {index > 0 && <Separator className="my-4" />}
293
-
294
- <div className="space-y-2">
295
- <div className="flex items-start gap-3">
296
- <Button
297
- variant="ghost"
298
- size="icon"
299
- className="h-6 w-6 shrink-0"
300
- onClick={() => toggleVersion(version.id)}
301
- >
302
- {isExpanded ? (
303
- <CaretDown className="h-4 w-4" />
304
- ) : (
305
- <CaretRight className="h-4 w-4" />
306
- )}
307
- </Button>
308
-
309
- <div className="flex-1 space-y-1">
310
- {/* Version Header */}
311
- <div className="flex items-center gap-2">
312
- <span className="text-sm font-medium">
313
- Version {version.versionNumber}
314
- </span>
315
- {getActionBadge(version.action)}
316
- {isLatest && <Badge variant="outline">Current</Badge>}
317
- </div>
318
-
319
- {/* Metadata */}
320
- <div className="flex items-center gap-4 text-xs text-muted-foreground">
321
- <div className="flex items-center gap-1">
322
- <Clock className="h-3 w-3" />
323
- {formatDate(version.createdAt)}
324
- </div>
325
- {version.createdBy && (
326
- <div className="flex items-center gap-1">
327
- <User className="h-3 w-3" />
328
- {version.createdBy.name || version.createdBy.email}
329
- </div>
330
- )}
331
- </div>
332
-
333
- {/* Changes Summary */}
334
- {version.changes &&
335
- version.changes.length > 0 &&
336
- !isExpanded && (
337
- <p className="text-xs text-muted-foreground">
338
- {version.changes.length} field
339
- {version.changes.length !== 1 ? "s" : ""} changed
340
- </p>
341
- )}
342
-
343
- {/* Expanded Changes */}
344
- {isExpanded && (
345
- <div className="mt-3 space-y-2">
346
- {version.changes && version.changes.length > 0 ? (
347
- <div className="rounded-lg border bg-muted/50 p-3 space-y-2">
348
- {version.changes.map((change, changeIndex) => (
349
- <div key={changeIndex} className="text-xs">
350
- <div className="font-medium text-foreground mb-1">
351
- {change.field}
352
- </div>
353
- <div className="grid grid-cols-2 gap-2">
354
- <div>
355
- <div className="text-muted-foreground">
356
- Old value:
357
- </div>
358
- <div className="font-mono rounded bg-background p-1 mt-1">
359
- {formatValue(change.oldValue)}
360
- </div>
361
- </div>
362
- <div>
363
- <div className="text-muted-foreground">
364
- New value:
365
- </div>
366
- <div className="font-mono rounded bg-background p-1 mt-1">
367
- {formatValue(change.newValue)}
368
- </div>
369
- </div>
370
- </div>
371
- </div>
372
- ))}
373
- </div>
374
- ) : (
375
- <p className="text-xs text-muted-foreground">
376
- No changes recorded
377
- </p>
378
- )}
379
-
380
- {/* Custom Version Render */}
381
- {renderVersion && renderVersion(version)}
382
-
383
- {/* Restore Button */}
384
- {allowRestore && !isLatest && (
385
- <Button
386
- variant="outline"
387
- size="sm"
388
- onClick={() => handleRestore(version.id)}
389
- className="mt-2"
390
- >
391
- <ArrowCounterClockwise className="mr-2 h-3 w-3" />
392
- Restore this version
393
- </Button>
394
- )}
395
- </div>
396
- )}
397
- </div>
398
- </div>
399
- </div>
400
- </div>
401
- );
402
- })}
403
- </CardContent>
404
- </Card>
405
- );
406
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * @questpie/admin Views
3
- *
4
- * Full-page and section-level view components.
5
- * Views are smart components that handle routing, data fetching, and state.
6
- *
7
- * Architecture:
8
- * - ui/ - Headless/styled primitives (Button, Card, Input)
9
- * - primitives/ - Generic input wrappers with callback API
10
- * - fields/ - react-hook-form connected field components
11
- * - views/ - Route-level components with business logic (this directory)
12
- * - features/ - Complex feature modules (Puck editor, media library)
13
- */
14
-
15
- // Auth views
16
- export * from "./auth";
17
-
18
- // Layout views
19
- export * from "./layout";
20
-
21
- // Collection views
22
- export * from "./collection";
23
-
24
- // Common/utility views
25
- export * from "./common";
@@ -1,117 +0,0 @@
1
- /**
2
- * AdminLayout Component
3
- *
4
- * Complete admin layout generated from config
5
- * - Sidebar navigation
6
- * - Main content area
7
- * - Optional header/footer
8
- */
9
-
10
- import * as React from "react";
11
- import { cn } from "../../lib/utils";
12
- import { AdminSidebar, type AdminSidebarProps } from "./admin-sidebar";
13
-
14
- export interface AdminLayoutProps {
15
- /**
16
- * Admin configuration
17
- */
18
- config: AdminSidebarProps["config"] & {
19
- app?: {
20
- header?: {
21
- show?: boolean;
22
- component?: React.ComponentType;
23
- };
24
- footer?: {
25
- show?: boolean;
26
- component?: React.ComponentType;
27
- };
28
- };
29
- };
30
-
31
- /**
32
- * Current active route
33
- */
34
- activeRoute?: string;
35
-
36
- /**
37
- * Link component (router-specific)
38
- */
39
- LinkComponent: AdminSidebarProps["LinkComponent"];
40
-
41
- /**
42
- * Main content to render
43
- */
44
- children: React.ReactNode;
45
-
46
- /**
47
- * Custom layout className
48
- */
49
- className?: string;
50
-
51
- /**
52
- * Custom sidebar props
53
- */
54
- sidebarProps?: Partial<AdminSidebarProps>;
55
-
56
- /**
57
- * Custom header content
58
- */
59
- renderHeader?: () => React.ReactNode;
60
-
61
- /**
62
- * Custom footer content
63
- */
64
- renderFooter?: () => React.ReactNode;
65
- }
66
-
67
- export function AdminLayout({
68
- config,
69
- activeRoute,
70
- LinkComponent,
71
- children,
72
- className,
73
- sidebarProps,
74
- renderHeader,
75
- renderFooter,
76
- }: AdminLayoutProps): React.ReactElement {
77
- const showHeader = config.app?.header?.show ?? false;
78
- const showFooter = config.app?.footer?.show ?? false;
79
- const HeaderComponent = config.app?.header?.component;
80
- const FooterComponent = config.app?.footer?.component;
81
-
82
- return (
83
- <div className={cn("flex h-screen flex-col", className)}>
84
- {/* Header (optional) */}
85
- {showHeader && (
86
- <header className="border-b">
87
- {renderHeader
88
- ? renderHeader()
89
- : HeaderComponent && <HeaderComponent />}
90
- </header>
91
- )}
92
-
93
- {/* Main Layout */}
94
- <div className="flex flex-1 overflow-hidden">
95
- {/* Sidebar */}
96
- <AdminSidebar
97
- config={config}
98
- activeRoute={activeRoute}
99
- LinkComponent={LinkComponent}
100
- {...sidebarProps}
101
- />
102
-
103
- {/* Main Content */}
104
- <main className="flex-1 overflow-auto">{children}</main>
105
- </div>
106
-
107
- {/* Footer (optional) */}
108
- {showFooter && (
109
- <footer className="border-t">
110
- {renderFooter
111
- ? renderFooter()
112
- : FooterComponent && <FooterComponent />}
113
- </footer>
114
- )}
115
- </div>
116
- );
117
- }