@actuate-media/cms-admin 0.22.0 → 0.23.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 (38) hide show
  1. package/dist/__tests__/components/forms-pagination.render.test.d.ts +2 -0
  2. package/dist/__tests__/components/forms-pagination.render.test.d.ts.map +1 -0
  3. package/dist/__tests__/components/forms-pagination.render.test.js +33 -0
  4. package/dist/__tests__/components/forms-pagination.render.test.js.map +1 -0
  5. package/dist/__tests__/views/form-submissions.render.test.d.ts +2 -0
  6. package/dist/__tests__/views/form-submissions.render.test.d.ts.map +1 -0
  7. package/dist/__tests__/views/form-submissions.render.test.js +110 -0
  8. package/dist/__tests__/views/form-submissions.render.test.js.map +1 -0
  9. package/dist/actuate-admin.css +1 -1
  10. package/dist/components/forms/EntryDetailDrawer.d.ts +11 -0
  11. package/dist/components/forms/EntryDetailDrawer.d.ts.map +1 -0
  12. package/dist/components/forms/EntryDetailDrawer.js +145 -0
  13. package/dist/components/forms/EntryDetailDrawer.js.map +1 -0
  14. package/dist/components/forms/NotificationsPanel.js +1 -1
  15. package/dist/components/forms/NotificationsPanel.js.map +1 -1
  16. package/dist/components/forms/primitives.d.ts +15 -0
  17. package/dist/components/forms/primitives.d.ts.map +1 -1
  18. package/dist/components/forms/primitives.js +36 -1
  19. package/dist/components/forms/primitives.js.map +1 -1
  20. package/dist/lib/forms-service.d.ts +36 -2
  21. package/dist/lib/forms-service.d.ts.map +1 -1
  22. package/dist/lib/forms-service.js +66 -0
  23. package/dist/lib/forms-service.js.map +1 -1
  24. package/dist/views/FormSubmissions.d.ts.map +1 -1
  25. package/dist/views/FormSubmissions.js +224 -77
  26. package/dist/views/FormSubmissions.js.map +1 -1
  27. package/dist/views/Forms.d.ts.map +1 -1
  28. package/dist/views/Forms.js +26 -10
  29. package/dist/views/Forms.js.map +1 -1
  30. package/package.json +1 -1
  31. package/src/__tests__/components/forms-pagination.render.test.tsx +49 -0
  32. package/src/__tests__/views/form-submissions.render.test.tsx +129 -0
  33. package/src/components/forms/EntryDetailDrawer.tsx +312 -0
  34. package/src/components/forms/NotificationsPanel.tsx +1 -1
  35. package/src/components/forms/primitives.tsx +101 -1
  36. package/src/lib/forms-service.ts +99 -0
  37. package/src/views/FormSubmissions.tsx +529 -394
  38. package/src/views/Forms.tsx +145 -107
@@ -21,6 +21,9 @@ import type {
21
21
  FormStats,
22
22
  FormsSidebarCount,
23
23
  FetchFormsParams,
24
+ FormSubmission,
25
+ FetchFormEntriesParams,
26
+ EntryCounts,
24
27
  } from '@actuate-media/cms-core'
25
28
 
26
29
  export type {
@@ -35,6 +38,11 @@ export type {
35
38
  FormStatus,
36
39
  FormStats,
37
40
  FormsSidebarCount,
41
+ FormSubmission,
42
+ FormSubmissionFile,
43
+ FetchFormEntriesParams,
44
+ EntryCounts,
45
+ SpamStatus,
38
46
  } from '@actuate-media/cms-core'
39
47
 
40
48
  /**
@@ -242,3 +250,94 @@ export async function updateEmbedSettings(
242
250
  })
243
251
  return { data: res.data, error: res.error }
244
252
  }
253
+
254
+ // ─── Entries (submissions) ─────────────────────────────────────────────────
255
+
256
+ /** A page of submissions as returned by `GET /forms/entries`. */
257
+ export interface EntriesPage {
258
+ entries: FormSubmission[]
259
+ total: number
260
+ page: number
261
+ pageSize: number
262
+ }
263
+
264
+ /** Patch shape accepted by the entry mutation endpoints. */
265
+ export interface EntryPatch {
266
+ unread?: boolean
267
+ starred?: boolean
268
+ archived?: boolean
269
+ }
270
+
271
+ function buildEntriesQuery(params: FetchFormEntriesParams): string {
272
+ const qs = new URLSearchParams()
273
+ if (params.search) qs.set('search', params.search)
274
+ if (params.formId) qs.set('formId', params.formId)
275
+ if (typeof params.unread === 'boolean') qs.set('unread', String(params.unread))
276
+ if (typeof params.starred === 'boolean') qs.set('starred', String(params.starred))
277
+ if (typeof params.archived === 'boolean') qs.set('archived', String(params.archived))
278
+ if (params.spamStatus) qs.set('spamStatus', params.spamStatus)
279
+ if (params.dateFrom) qs.set('dateFrom', params.dateFrom)
280
+ if (params.dateTo) qs.set('dateTo', params.dateTo)
281
+ if (params.thisWeek) qs.set('thisWeek', 'true')
282
+ if (params.sortBy) qs.set('sortBy', params.sortBy)
283
+ if (params.sortDirection) qs.set('sortDirection', params.sortDirection)
284
+ if (params.page) qs.set('page', String(params.page))
285
+ if (params.pageSize) qs.set('pageSize', String(params.pageSize))
286
+ const str = qs.toString()
287
+ return str ? `?${str}` : ''
288
+ }
289
+
290
+ const EMPTY_PAGE: EntriesPage = { entries: [], total: 0, page: 1, pageSize: 25 }
291
+
292
+ export async function fetchEntries(params: FetchFormEntriesParams = {}): Promise<EntriesPage> {
293
+ const res = await cmsApi<EntriesPage>(`/forms/entries${buildEntriesQuery(params)}`)
294
+ throwIfError(res)
295
+ return res.data ?? EMPTY_PAGE
296
+ }
297
+
298
+ const EMPTY_COUNTS: EntryCounts = { total: 0, unread: 0, starred: 0, thisWeek: 0, byForm: {} }
299
+
300
+ export async function fetchEntryCounts(params: FetchFormEntriesParams = {}): Promise<EntryCounts> {
301
+ const res = await cmsApi<EntryCounts>(`/forms/entries/counts${buildEntriesQuery(params)}`)
302
+ throwIfError(res)
303
+ return res.data ?? EMPTY_COUNTS
304
+ }
305
+
306
+ /** A single entry rendered against the schema version it was captured with. */
307
+ export interface EntryDetail {
308
+ entry: FormSubmission
309
+ fields: FormField[]
310
+ }
311
+
312
+ export async function fetchEntry(id: string): Promise<EntryDetail | null> {
313
+ const res = await cmsApi<EntryDetail>(`/forms/entries/${encodeURIComponent(id)}`)
314
+ throwIfError(res)
315
+ return res.data ?? null
316
+ }
317
+
318
+ export async function updateEntry(
319
+ id: string,
320
+ patch: EntryPatch,
321
+ ): Promise<{ data?: FormSubmission; error?: string }> {
322
+ const res = await cmsApi<FormSubmission>(`/forms/entries/${encodeURIComponent(id)}`, {
323
+ method: 'PATCH',
324
+ body: JSON.stringify(patch),
325
+ })
326
+ return { data: res.data, error: res.error }
327
+ }
328
+
329
+ export async function deleteEntry(id: string): Promise<{ error?: string }> {
330
+ const res = await cmsApi(`/forms/entries/${encodeURIComponent(id)}`, { method: 'DELETE' })
331
+ return { error: res.error }
332
+ }
333
+
334
+ export async function bulkUpdateEntries(
335
+ ids: string[],
336
+ patch: EntryPatch,
337
+ ): Promise<{ data?: { updated: number }; error?: string }> {
338
+ const res = await cmsApi<{ updated: number }>('/forms/entries/bulk', {
339
+ method: 'POST',
340
+ body: JSON.stringify({ ids, patch }),
341
+ })
342
+ return { data: res.data, error: res.error }
343
+ }