@actuate-media/cms-admin 0.21.1 → 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.
- package/dist/__tests__/components/forms-pagination.render.test.d.ts +2 -0
- package/dist/__tests__/components/forms-pagination.render.test.d.ts.map +1 -0
- package/dist/__tests__/components/forms-pagination.render.test.js +33 -0
- package/dist/__tests__/components/forms-pagination.render.test.js.map +1 -0
- package/dist/__tests__/layout/sidebar-forms-badge.render.test.d.ts +2 -0
- package/dist/__tests__/layout/sidebar-forms-badge.render.test.d.ts.map +1 -0
- package/dist/__tests__/layout/sidebar-forms-badge.render.test.js +30 -0
- package/dist/__tests__/layout/sidebar-forms-badge.render.test.js.map +1 -0
- package/dist/__tests__/layout/sidebar-submenu.render.test.js +8 -2
- package/dist/__tests__/layout/sidebar-submenu.render.test.js.map +1 -1
- package/dist/__tests__/views/form-submissions.render.test.d.ts +2 -0
- package/dist/__tests__/views/form-submissions.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/form-submissions.render.test.js +110 -0
- package/dist/__tests__/views/form-submissions.render.test.js.map +1 -0
- package/dist/__tests__/views/forms-list.render.test.d.ts +2 -0
- package/dist/__tests__/views/forms-list.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/forms-list.render.test.js +122 -0
- package/dist/__tests__/views/forms-list.render.test.js.map +1 -0
- package/dist/actuate-admin.css +1 -1
- package/dist/components/forms/Drawer.d.ts +13 -0
- package/dist/components/forms/Drawer.d.ts.map +1 -0
- package/dist/components/forms/Drawer.js +13 -0
- package/dist/components/forms/Drawer.js.map +1 -0
- package/dist/components/forms/EmbedPanel.d.ts +7 -0
- package/dist/components/forms/EmbedPanel.d.ts.map +1 -0
- package/dist/components/forms/EmbedPanel.js +91 -0
- package/dist/components/forms/EmbedPanel.js.map +1 -0
- package/dist/components/forms/EntryDetailDrawer.d.ts +11 -0
- package/dist/components/forms/EntryDetailDrawer.d.ts.map +1 -0
- package/dist/components/forms/EntryDetailDrawer.js +145 -0
- package/dist/components/forms/EntryDetailDrawer.js.map +1 -0
- package/dist/components/forms/FieldsPanel.d.ts +8 -0
- package/dist/components/forms/FieldsPanel.d.ts.map +1 -0
- package/dist/components/forms/FieldsPanel.js +123 -0
- package/dist/components/forms/FieldsPanel.js.map +1 -0
- package/dist/components/forms/FormSchemaDrawer.d.ts +9 -0
- package/dist/components/forms/FormSchemaDrawer.d.ts.map +1 -0
- package/dist/components/forms/FormSchemaDrawer.js +96 -0
- package/dist/components/forms/FormSchemaDrawer.js.map +1 -0
- package/dist/components/forms/NotificationsPanel.d.ts +6 -0
- package/dist/components/forms/NotificationsPanel.d.ts.map +1 -0
- package/dist/components/forms/NotificationsPanel.js +80 -0
- package/dist/components/forms/NotificationsPanel.js.map +1 -0
- package/dist/components/forms/primitives.d.ts +57 -0
- package/dist/components/forms/primitives.d.ts.map +1 -0
- package/dist/components/forms/primitives.js +131 -0
- package/dist/components/forms/primitives.js.map +1 -0
- package/dist/layout/Sidebar.d.ts +5 -0
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Sidebar.js +43 -3
- package/dist/layout/Sidebar.js.map +1 -1
- package/dist/lib/forms-events.d.ts +17 -0
- package/dist/lib/forms-events.d.ts.map +1 -0
- package/dist/lib/forms-events.js +20 -0
- package/dist/lib/forms-events.js.map +1 -0
- package/dist/lib/forms-service.d.ts +114 -0
- package/dist/lib/forms-service.d.ts.map +1 -0
- package/dist/lib/forms-service.js +210 -0
- package/dist/lib/forms-service.js.map +1 -0
- package/dist/views/FormSubmissions.d.ts.map +1 -1
- package/dist/views/FormSubmissions.js +224 -77
- package/dist/views/FormSubmissions.js.map +1 -1
- package/dist/views/Forms.d.ts.map +1 -1
- package/dist/views/Forms.js +135 -17
- package/dist/views/Forms.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/components/forms-pagination.render.test.tsx +49 -0
- package/src/__tests__/layout/sidebar-forms-badge.render.test.tsx +50 -0
- package/src/__tests__/layout/sidebar-submenu.render.test.tsx +9 -2
- package/src/__tests__/views/form-submissions.render.test.tsx +129 -0
- package/src/__tests__/views/forms-list.render.test.tsx +141 -0
- package/src/components/forms/Drawer.tsx +70 -0
- package/src/components/forms/EmbedPanel.tsx +173 -0
- package/src/components/forms/EntryDetailDrawer.tsx +312 -0
- package/src/components/forms/FieldsPanel.tsx +385 -0
- package/src/components/forms/FormSchemaDrawer.tsx +185 -0
- package/src/components/forms/NotificationsPanel.tsx +240 -0
- package/src/components/forms/primitives.tsx +300 -0
- package/src/layout/Sidebar.tsx +72 -6
- package/src/lib/forms-events.ts +32 -0
- package/src/lib/forms-service.ts +343 -0
- package/src/views/FormSubmissions.tsx +529 -394
- package/src/views/Forms.tsx +381 -106
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbedPanel.js","sourceRoot":"","sources":["../../../src/components/forms/EmbedPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface EntryDetailDrawerProps {
|
|
2
|
+
entryId: string | null;
|
|
3
|
+
open: boolean;
|
|
4
|
+
onOpenChange: (open: boolean) => void;
|
|
5
|
+
/** Called after a mutation (star/archive/read/delete) so the list refreshes. */
|
|
6
|
+
onChanged?: () => void;
|
|
7
|
+
/** Called specifically after a delete so the caller can drop the row/selection. */
|
|
8
|
+
onDeleted?: (id: string) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function EntryDetailDrawer({ entryId, open, onOpenChange, onChanged, onDeleted, }: EntryDetailDrawerProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=EntryDetailDrawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntryDetailDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/forms/EntryDetailDrawer.tsx"],"names":[],"mappings":"AA6DA,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,mFAAmF;IACnF,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CACjC;AAED,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,SAAS,GACV,EAAE,sBAAsB,2CAyMxB"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Entry detail drawer — shows a single submission rendered against the schema
|
|
5
|
+
* version it was captured with, plus sender, attribution, and per-entry
|
|
6
|
+
* actions (star, archive, mark unread, delete). Opening an unread entry marks
|
|
7
|
+
* it read. Token-only styling; built on the shared `Drawer`.
|
|
8
|
+
*/
|
|
9
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
10
|
+
import { Archive, ArchiveRestore, Loader2, Mail, Star, Trash2 } from 'lucide-react';
|
|
11
|
+
import { toast } from 'sonner';
|
|
12
|
+
import { deleteEntry, fetchEntry, updateEntry, } from '../../lib/forms-service.js';
|
|
13
|
+
import { emitFormsChanged } from '../../lib/forms-events.js';
|
|
14
|
+
import { ConfirmDialog } from '../ui/ConfirmDialog.js';
|
|
15
|
+
import { Drawer } from './Drawer.js';
|
|
16
|
+
import { FormsErrorState, btnGhostIcon } from './primitives.js';
|
|
17
|
+
function formatDateTime(iso) {
|
|
18
|
+
if (!iso)
|
|
19
|
+
return '—';
|
|
20
|
+
const d = new Date(iso);
|
|
21
|
+
if (Number.isNaN(d.getTime()))
|
|
22
|
+
return '—';
|
|
23
|
+
return d.toLocaleString(undefined, {
|
|
24
|
+
month: 'short',
|
|
25
|
+
day: 'numeric',
|
|
26
|
+
year: 'numeric',
|
|
27
|
+
hour: 'numeric',
|
|
28
|
+
minute: '2-digit',
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Render a stored value for display, coping with arrays/objects/booleans. */
|
|
32
|
+
function displayValue(value) {
|
|
33
|
+
if (value == null || value === '')
|
|
34
|
+
return '—';
|
|
35
|
+
if (typeof value === 'boolean')
|
|
36
|
+
return value ? 'Yes' : 'No';
|
|
37
|
+
if (Array.isArray(value))
|
|
38
|
+
return value.map((v) => String(v)).join(', ');
|
|
39
|
+
if (typeof value === 'object')
|
|
40
|
+
return JSON.stringify(value);
|
|
41
|
+
return String(value);
|
|
42
|
+
}
|
|
43
|
+
function attributionRows(entry) {
|
|
44
|
+
return [
|
|
45
|
+
{ label: 'Source', value: entry.utmSource },
|
|
46
|
+
{ label: 'Medium', value: entry.utmMedium },
|
|
47
|
+
{ label: 'Campaign', value: entry.utmCampaign },
|
|
48
|
+
{ label: 'Page', value: entry.pageUrl },
|
|
49
|
+
{ label: 'Referrer', value: entry.referrer },
|
|
50
|
+
].filter((r) => r.value);
|
|
51
|
+
}
|
|
52
|
+
export function EntryDetailDrawer({ entryId, open, onOpenChange, onChanged, onDeleted, }) {
|
|
53
|
+
const [detail, setDetail] = useState(null);
|
|
54
|
+
const [loading, setLoading] = useState(false);
|
|
55
|
+
const [error, setError] = useState(null);
|
|
56
|
+
const [busy, setBusy] = useState(false);
|
|
57
|
+
const [confirmDelete, setConfirmDelete] = useState(false);
|
|
58
|
+
const notifyChanged = useCallback(() => {
|
|
59
|
+
emitFormsChanged();
|
|
60
|
+
onChanged?.();
|
|
61
|
+
}, [onChanged]);
|
|
62
|
+
// Load the entry (and its schema) when the drawer opens, marking it read.
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!open || !entryId)
|
|
65
|
+
return;
|
|
66
|
+
let cancelled = false;
|
|
67
|
+
setLoading(true);
|
|
68
|
+
setError(null);
|
|
69
|
+
setDetail(null);
|
|
70
|
+
void (async () => {
|
|
71
|
+
try {
|
|
72
|
+
const data = await fetchEntry(entryId);
|
|
73
|
+
if (cancelled)
|
|
74
|
+
return;
|
|
75
|
+
if (!data) {
|
|
76
|
+
setError('Entry not found');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
setDetail(data);
|
|
80
|
+
// Mark read on open (fire-and-forget; refresh the list counts).
|
|
81
|
+
if (data.entry.unread) {
|
|
82
|
+
const res = await updateEntry(entryId, { unread: false });
|
|
83
|
+
if (!cancelled && !res.error)
|
|
84
|
+
notifyChanged();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
if (!cancelled)
|
|
89
|
+
setError(e instanceof Error ? e.message : 'Failed to load entry');
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
if (!cancelled)
|
|
93
|
+
setLoading(false);
|
|
94
|
+
}
|
|
95
|
+
})();
|
|
96
|
+
return () => {
|
|
97
|
+
cancelled = true;
|
|
98
|
+
};
|
|
99
|
+
}, [open, entryId, notifyChanged]);
|
|
100
|
+
const mutate = useCallback(async (patch) => {
|
|
101
|
+
if (!entryId)
|
|
102
|
+
return;
|
|
103
|
+
setBusy(true);
|
|
104
|
+
const res = await updateEntry(entryId, patch);
|
|
105
|
+
setBusy(false);
|
|
106
|
+
if (res.error) {
|
|
107
|
+
toast.error(res.error);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
setDetail((cur) => (cur ? { ...cur, entry: { ...cur.entry, ...patch } } : cur));
|
|
111
|
+
notifyChanged();
|
|
112
|
+
}, [entryId, notifyChanged]);
|
|
113
|
+
const handleDelete = useCallback(async () => {
|
|
114
|
+
if (!entryId)
|
|
115
|
+
return;
|
|
116
|
+
setBusy(true);
|
|
117
|
+
const res = await deleteEntry(entryId);
|
|
118
|
+
setBusy(false);
|
|
119
|
+
if (res.error) {
|
|
120
|
+
toast.error(res.error);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
toast.success('Submission deleted');
|
|
124
|
+
notifyChanged();
|
|
125
|
+
onDeleted?.(entryId);
|
|
126
|
+
onOpenChange(false);
|
|
127
|
+
}, [entryId, notifyChanged, onDeleted, onOpenChange]);
|
|
128
|
+
const entry = detail?.entry;
|
|
129
|
+
const senderName = entry?.senderName || 'Anonymous';
|
|
130
|
+
const attrRows = entry ? attributionRows(entry) : [];
|
|
131
|
+
return (_jsxs(_Fragment, { children: [_jsx(Drawer, { open: open, onOpenChange: onOpenChange, title: entry ? `Entry${entry.entryNumber ? ` #${entry.entryNumber}` : ''}` : 'Entry', description: entry ? formatDateTime(entry.submittedAt) : undefined, headerExtra: entry ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: btnGhostIcon, "aria-pressed": entry.starred, "aria-label": entry.starred ? 'Unstar entry' : 'Star entry', disabled: busy, onClick: () => void mutate({ starred: !entry.starred }), children: _jsx(Star, { size: 18, "aria-hidden": true, className: entry.starred ? 'fill-warning text-warning' : '' }) }), _jsx("button", { type: "button", className: btnGhostIcon, "aria-pressed": entry.archived, "aria-label": entry.archived ? 'Unarchive entry' : 'Archive entry', disabled: busy, onClick: () => void mutate({ archived: !entry.archived }), children: entry.archived ? (_jsx(ArchiveRestore, { size: 18, "aria-hidden": true })) : (_jsx(Archive, { size: 18, "aria-hidden": true })) })] })) : undefined, footer: entry ? (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", className: "text-destructive hover:bg-destructive/10 focus-visible:ring-ring inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none disabled:opacity-60", disabled: busy, onClick: () => setConfirmDelete(true), children: [_jsx(Trash2, { size: 16, "aria-hidden": true }), "Delete"] }), _jsxs("button", { type: "button", className: "border-border text-foreground hover:bg-accent focus-visible:ring-ring inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none disabled:opacity-60", disabled: busy, onClick: () => void mutate({ unread: !entry.unread }), children: [_jsx(Mail, { size: 16, "aria-hidden": true }), "Mark ", entry.unread ? 'read' : 'unread'] })] })) : undefined, children: loading ? (_jsxs("div", { className: "flex h-40 items-center justify-center", role: "status", "aria-live": "polite", children: [_jsx(Loader2, { className: "text-muted-foreground h-5 w-5 animate-spin", "aria-hidden": true }), _jsx("span", { className: "sr-only", children: "Loading entry\u2026" })] })) : error ? (_jsx(FormsErrorState, { message: error })) : entry ? (_jsxs("div", { className: "space-y-6", children: [_jsxs("section", { className: "space-y-1", children: [_jsx("h3", { className: "text-foreground text-sm font-medium", children: senderName }), entry.senderEmail && (_jsx("a", { href: `mailto:${entry.senderEmail}`, className: "text-primary block text-sm hover:underline", children: entry.senderEmail })), entry.senderPhone && (_jsx("span", { className: "text-muted-foreground block text-sm", children: entry.senderPhone }))] }), _jsx(FieldValues, { entry: entry, fields: detail.fields }), attrRows.length > 0 && (_jsxs("section", { children: [_jsx("h4", { className: "text-muted-foreground mb-2 text-xs font-medium tracking-wide uppercase", children: "Attribution" }), _jsx("dl", { className: "divide-border divide-y text-sm", children: attrRows.map((row) => (_jsxs("div", { className: "flex justify-between gap-4 py-1.5", children: [_jsx("dt", { className: "text-muted-foreground shrink-0", children: row.label }), _jsx("dd", { className: "text-foreground min-w-0 truncate text-right", children: row.value })] }, row.label))) })] }))] })) : null }), _jsx(ConfirmDialog, { open: confirmDelete, onClose: () => setConfirmDelete(false), onConfirm: () => void handleDelete(), title: "Delete submission?", description: "This permanently removes the submission and any attached files. This cannot be undone.", confirmLabel: "Delete", destructive: true })] }));
|
|
132
|
+
}
|
|
133
|
+
/** Render the captured field values against the entry's schema. */
|
|
134
|
+
function FieldValues({ entry, fields }) {
|
|
135
|
+
// Prefer the schema order; fall back to whatever keys exist on the data.
|
|
136
|
+
const inputFields = fields.filter((f) => f.type !== 'divider' && f.type !== 'richtext' && f.type !== 'honeypot');
|
|
137
|
+
const rows = inputFields.length
|
|
138
|
+
? inputFields.map((f) => ({ key: f.key, label: f.label }))
|
|
139
|
+
: Object.keys(entry.data ?? {}).map((k) => ({ key: k, label: k }));
|
|
140
|
+
if (rows.length === 0) {
|
|
141
|
+
return _jsx("p", { className: "text-muted-foreground text-sm", children: "No field data captured." });
|
|
142
|
+
}
|
|
143
|
+
return (_jsxs("section", { children: [_jsx("h4", { className: "text-muted-foreground mb-2 text-xs font-medium tracking-wide uppercase", children: "Submission" }), _jsx("dl", { className: "space-y-3", children: rows.map((row) => (_jsxs("div", { children: [_jsx("dt", { className: "text-muted-foreground text-xs", children: row.label }), _jsx("dd", { className: "text-foreground mt-0.5 text-sm wrap-break-word whitespace-pre-wrap", children: displayValue(entry.data?.[row.key]) })] }, row.key))) })] }));
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=EntryDetailDrawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntryDetailDrawer.js","sourceRoot":"","sources":["../../../src/components/forms/EntryDetailDrawer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FormField } from '../../lib/forms-service.js';
|
|
2
|
+
export declare function FieldsPanel({ fields, onChange, hasSubmissions, }: {
|
|
3
|
+
fields: FormField[];
|
|
4
|
+
onChange: (next: FormField[]) => void;
|
|
5
|
+
/** When the form already has submissions, key renames/deletes are riskier. */
|
|
6
|
+
hasSubmissions: boolean;
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=FieldsPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldsPanel.d.ts","sourceRoot":"","sources":["../../../src/components/forms/FieldsPanel.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,4BAA4B,CAAA;AAqC1E,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,QAAQ,EACR,cAAc,GACf,EAAE;IACD,MAAM,EAAE,SAAS,EAAE,CAAA;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,IAAI,CAAA;IACrC,8EAA8E;IAC9E,cAAc,EAAE,OAAO,CAAA;CACxB,2CAiFA"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Fields tab of the Form Schema drawer. Renders the form's field list with
|
|
5
|
+
* drag-to-reorder (dnd-kit, keyboard-accessible) plus an inline editor for the
|
|
6
|
+
* selected field. The parent owns the `fields` array and persistence; this
|
|
7
|
+
* panel is a controlled editor that calls `onChange` with the next array.
|
|
8
|
+
*/
|
|
9
|
+
import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors, } from '@dnd-kit/core';
|
|
10
|
+
import { SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
|
|
11
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
12
|
+
import { ChevronDown, GripVertical, Plus, Trash2 } from 'lucide-react';
|
|
13
|
+
import * as Switch from '@radix-ui/react-switch';
|
|
14
|
+
import { useId, useState } from 'react';
|
|
15
|
+
import { FieldTypeBadge, FormsEmptyState } from './primitives.js';
|
|
16
|
+
const FIELD_TYPES = [
|
|
17
|
+
{ value: 'text', label: 'Text' },
|
|
18
|
+
{ value: 'email', label: 'Email' },
|
|
19
|
+
{ value: 'phone', label: 'Phone' },
|
|
20
|
+
{ value: 'textarea', label: 'Textarea' },
|
|
21
|
+
{ value: 'select', label: 'Select' },
|
|
22
|
+
{ value: 'multiselect', label: 'Multi-select' },
|
|
23
|
+
{ value: 'radio', label: 'Radio' },
|
|
24
|
+
{ value: 'checkbox', label: 'Checkbox' },
|
|
25
|
+
{ value: 'date', label: 'Date' },
|
|
26
|
+
{ value: 'number', label: 'Number' },
|
|
27
|
+
{ value: 'url', label: 'URL' },
|
|
28
|
+
{ value: 'consent', label: 'Consent' },
|
|
29
|
+
{ value: 'file', label: 'File upload' },
|
|
30
|
+
{ value: 'hidden', label: 'Hidden' },
|
|
31
|
+
{ value: 'richtext', label: 'Content block' },
|
|
32
|
+
{ value: 'divider', label: 'Divider / heading' },
|
|
33
|
+
];
|
|
34
|
+
const OPTION_TYPES = ['select', 'multiselect', 'radio'];
|
|
35
|
+
function slugifyKey(label) {
|
|
36
|
+
return label
|
|
37
|
+
.toLowerCase()
|
|
38
|
+
.trim()
|
|
39
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
40
|
+
.replace(/^_+|_+$/g, '');
|
|
41
|
+
}
|
|
42
|
+
function makeId() {
|
|
43
|
+
if (typeof crypto !== 'undefined' && 'randomUUID' in crypto)
|
|
44
|
+
return crypto.randomUUID();
|
|
45
|
+
return `f_${Math.random().toString(36).slice(2)}`;
|
|
46
|
+
}
|
|
47
|
+
export function FieldsPanel({ fields, onChange, hasSubmissions, }) {
|
|
48
|
+
const [editingId, setEditingId] = useState(null);
|
|
49
|
+
const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
|
|
50
|
+
function handleDragEnd(event) {
|
|
51
|
+
const { active, over } = event;
|
|
52
|
+
if (!over || active.id === over.id)
|
|
53
|
+
return;
|
|
54
|
+
const ids = fields.map((f) => f.id);
|
|
55
|
+
const from = ids.indexOf(String(active.id));
|
|
56
|
+
const to = ids.indexOf(String(over.id));
|
|
57
|
+
if (from === -1 || to === -1)
|
|
58
|
+
return;
|
|
59
|
+
const next = fields.slice();
|
|
60
|
+
const [moved] = next.splice(from, 1);
|
|
61
|
+
next.splice(to, 0, moved);
|
|
62
|
+
onChange(next.map((f, i) => ({ ...f, sortOrder: i })));
|
|
63
|
+
}
|
|
64
|
+
function updateField(id, patch) {
|
|
65
|
+
onChange(fields.map((f) => (f.id === id ? { ...f, ...patch } : f)));
|
|
66
|
+
}
|
|
67
|
+
function deleteField(id) {
|
|
68
|
+
onChange(fields.filter((f) => f.id !== id));
|
|
69
|
+
if (editingId === id)
|
|
70
|
+
setEditingId(null);
|
|
71
|
+
}
|
|
72
|
+
function addField() {
|
|
73
|
+
const id = makeId();
|
|
74
|
+
const next = {
|
|
75
|
+
id,
|
|
76
|
+
label: 'New Field',
|
|
77
|
+
key: `field_${fields.length + 1}`,
|
|
78
|
+
type: 'text',
|
|
79
|
+
required: false,
|
|
80
|
+
sortOrder: fields.length,
|
|
81
|
+
};
|
|
82
|
+
onChange([...fields, next]);
|
|
83
|
+
setEditingId(id);
|
|
84
|
+
}
|
|
85
|
+
return (_jsxs("div", { className: "space-y-3", children: [fields.length === 0 ? (_jsx(FormsEmptyState, { title: "No fields yet", description: "Add your first field to start building this form." })) : (_jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragEnd: handleDragEnd, children: _jsx(SortableContext, { items: fields.map((f) => f.id), strategy: verticalListSortingStrategy, children: _jsx("ul", { className: "space-y-2", children: fields.map((field) => (_jsx(SortableFieldRow, { field: field, editing: editingId === field.id, hasSubmissions: hasSubmissions, onToggleEdit: () => setEditingId((cur) => (cur === field.id ? null : field.id)), onUpdate: (patch) => updateField(field.id, patch), onDelete: () => deleteField(field.id) }, field.id))) }) }) })), _jsxs("button", { type: "button", onClick: addField, className: "border-border text-foreground hover:bg-accent flex w-full items-center justify-center gap-2 rounded-lg border border-dashed px-3 py-2.5 text-sm font-medium transition-colors", children: [_jsx(Plus, { className: "h-4 w-4", "aria-hidden": true }), "Add Field"] })] }));
|
|
86
|
+
}
|
|
87
|
+
function SortableFieldRow({ field, editing, hasSubmissions, onToggleEdit, onUpdate, onDelete, }) {
|
|
88
|
+
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
|
89
|
+
id: field.id,
|
|
90
|
+
});
|
|
91
|
+
const style = {
|
|
92
|
+
transform: CSS.Transform.toString(transform),
|
|
93
|
+
transition,
|
|
94
|
+
zIndex: isDragging ? 10 : undefined,
|
|
95
|
+
};
|
|
96
|
+
const needsOptions = OPTION_TYPES.includes(field.type);
|
|
97
|
+
return (_jsx("li", { ref: setNodeRef, style: style, children: _jsxs("div", { className: `border-border bg-card rounded-lg border ${isDragging ? 'shadow-md' : ''} ${editing ? 'ring-primary/30 ring-1' : ''}`, children: [_jsxs("div", { className: "flex items-center gap-2 px-2.5 py-2", children: [_jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground focus-visible:ring-ring shrink-0 cursor-grab touch-none rounded focus-visible:ring-2 focus-visible:outline-none", "aria-label": `Drag to reorder ${field.label}`, ...attributes, ...listeners, children: _jsx(GripVertical, { className: "h-4 w-4", "aria-hidden": true }) }), _jsx("button", { type: "button", onClick: onToggleEdit, className: "flex min-w-0 flex-1 items-center gap-2 text-left", "aria-expanded": editing, children: _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "text-foreground block truncate text-sm font-medium", children: field.label || '(untitled)' }), _jsx("span", { className: "text-muted-foreground block truncate font-mono text-xs", children: field.key })] }) }), _jsx(FieldTypeBadge, { type: field.type }), field.required && (_jsx("span", { className: "bg-muted text-muted-foreground rounded px-1.5 py-0.5 text-[10px] font-medium uppercase", children: "Required" })), _jsx("button", { type: "button", onClick: onToggleEdit, className: "text-muted-foreground hover:text-foreground focus-visible:ring-ring shrink-0 rounded p-1 focus-visible:ring-2 focus-visible:outline-none", "aria-label": `${editing ? 'Collapse' : 'Edit'} ${field.label}`, children: _jsx(ChevronDown, { className: `h-4 w-4 transition-transform ${editing ? '' : '-rotate-90'}`, "aria-hidden": true }) }), _jsx("button", { type: "button", onClick: onDelete, className: "text-muted-foreground hover:text-destructive focus-visible:ring-ring shrink-0 rounded p-1 focus-visible:ring-2 focus-visible:outline-none", "aria-label": `Delete ${field.label}`, children: _jsx(Trash2, { className: "h-4 w-4", "aria-hidden": true }) })] }), editing && (_jsx(FieldEditor, { field: field, hasSubmissions: hasSubmissions, needsOptions: needsOptions, onUpdate: onUpdate }))] }) }));
|
|
98
|
+
}
|
|
99
|
+
function FieldEditor({ field, hasSubmissions, needsOptions, onUpdate, }) {
|
|
100
|
+
const reqId = useId();
|
|
101
|
+
const optionsText = (field.options ?? []).map((o) => o.label).join('\n');
|
|
102
|
+
return (_jsxs("div", { className: "border-border space-y-3 border-t px-3 py-3", children: [_jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2", children: [_jsx(Labeled, { label: "Label", children: _jsx("input", { type: "text", value: field.label, onChange: (e) => {
|
|
103
|
+
const label = e.target.value;
|
|
104
|
+
// Auto-derive the key from the label until the form has data and
|
|
105
|
+
// until the user has clearly customised the key.
|
|
106
|
+
const autoKey = slugifyKey(field.label);
|
|
107
|
+
const patch = { label };
|
|
108
|
+
if (!hasSubmissions && (field.key === autoKey || !field.key)) {
|
|
109
|
+
patch.key = slugifyKey(label);
|
|
110
|
+
}
|
|
111
|
+
onUpdate(patch);
|
|
112
|
+
}, className: "border-border bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-2.5 py-1.5 text-sm focus-visible:ring-2 focus-visible:outline-none" }) }), _jsx(Labeled, { label: "Key", hint: hasSubmissions ? 'Renaming affects existing entries & exports' : undefined, children: _jsx("input", { type: "text", value: field.key, onChange: (e) => onUpdate({ key: slugifyKey(e.target.value) }), className: "border-border bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-2.5 py-1.5 font-mono text-sm focus-visible:ring-2 focus-visible:outline-none" }) }), _jsx(Labeled, { label: "Type", children: _jsx("select", { value: field.type, onChange: (e) => onUpdate({ type: e.target.value }), className: "border-border bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-2.5 py-1.5 text-sm focus-visible:ring-2 focus-visible:outline-none", children: FIELD_TYPES.map((t) => (_jsx("option", { value: t.value, children: t.label }, t.value))) }) }), _jsx(Labeled, { label: "Placeholder", children: _jsx("input", { type: "text", value: field.placeholder ?? '', onChange: (e) => onUpdate({ placeholder: e.target.value }), className: "border-border bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-2.5 py-1.5 text-sm focus-visible:ring-2 focus-visible:outline-none" }) })] }), _jsx(Labeled, { label: "Help text", children: _jsx("input", { type: "text", value: field.helpText ?? '', onChange: (e) => onUpdate({ helpText: e.target.value }), className: "border-border bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-2.5 py-1.5 text-sm focus-visible:ring-2 focus-visible:outline-none" }) }), needsOptions && (_jsx(Labeled, { label: "Options", hint: "One per line", children: _jsx("textarea", { rows: 3, value: optionsText, onChange: (e) => onUpdate({
|
|
113
|
+
options: e.target.value
|
|
114
|
+
.split('\n')
|
|
115
|
+
.map((line) => line.trim())
|
|
116
|
+
.filter(Boolean)
|
|
117
|
+
.map((label) => ({ label, value: slugifyKey(label) })),
|
|
118
|
+
}), className: "border-border bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-2.5 py-1.5 text-sm focus-visible:ring-2 focus-visible:outline-none" }) })), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("label", { htmlFor: reqId, className: "text-foreground text-sm font-medium", children: "Required" }), _jsx(Switch.Root, { id: reqId, checked: field.required, onCheckedChange: (v) => onUpdate({ required: v }), className: "bg-input-background data-[state=checked]:bg-primary focus-visible:ring-ring relative h-[18px] w-8 shrink-0 rounded-full transition-colors focus-visible:ring-2 focus-visible:outline-none", children: _jsx(Switch.Thumb, { className: "bg-background block h-3.5 w-3.5 translate-x-0.5 rounded-full shadow-sm transition-transform data-[state=checked]:translate-x-[14px]" }) })] })] }));
|
|
119
|
+
}
|
|
120
|
+
function Labeled({ label, hint, children, }) {
|
|
121
|
+
return (_jsxs("label", { className: "block", children: [_jsx("span", { className: "text-muted-foreground mb-1 block text-xs font-medium", children: label }), children, hint && _jsx("span", { className: "text-warning mt-1 block text-xs", children: hint })] }));
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=FieldsPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldsPanel.js","sourceRoot":"","sources":["../../../src/components/forms/FieldsPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FormListItem } from '../../lib/forms-service.js';
|
|
2
|
+
export declare function FormSchemaDrawer({ form, open, onOpenChange, onSaved, }: {
|
|
3
|
+
form: FormListItem | null;
|
|
4
|
+
open: boolean;
|
|
5
|
+
onOpenChange: (open: boolean) => void;
|
|
6
|
+
/** Called after a schema/settings change so the list can refetch. */
|
|
7
|
+
onSaved?: () => void;
|
|
8
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
//# sourceMappingURL=FormSchemaDrawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormSchemaDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/forms/FormSchemaDrawer.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAe9D,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,OAAO,GACR,EAAE;IACD,IAAI,EAAE,YAAY,GAAG,IAAI,CAAA;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,kDA+IA"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Form Schema drawer — the right-side panel opened from the Forms list "Schema"
|
|
5
|
+
* action. Three tabs: Fields (versioned schema editor), Embed (public snippets
|
|
6
|
+
* + domain restrictions), Notifications (per-form notification settings).
|
|
7
|
+
*
|
|
8
|
+
* Saving the Fields tab creates a new schema version server-side; existing
|
|
9
|
+
* submissions keep referencing the version they were captured against, so
|
|
10
|
+
* historical entries never break when the schema changes.
|
|
11
|
+
*/
|
|
12
|
+
import * as Tabs from '@radix-ui/react-tabs';
|
|
13
|
+
import { useEffect, useState } from 'react';
|
|
14
|
+
import { toast } from 'sonner';
|
|
15
|
+
import { fetchFormSchema, saveFormSchema } from '../../lib/forms-service.js';
|
|
16
|
+
import { emitFormsChanged } from '../../lib/forms-events.js';
|
|
17
|
+
import { ConfirmDialog } from '../ui/ConfirmDialog.js';
|
|
18
|
+
import { Drawer } from './Drawer.js';
|
|
19
|
+
import { FieldsPanel } from './FieldsPanel.js';
|
|
20
|
+
import { EmbedPanel } from './EmbedPanel.js';
|
|
21
|
+
import { NotificationsPanel } from './NotificationsPanel.js';
|
|
22
|
+
import { FormsErrorState, FormsLoading, btnPrimary, btnSecondary } from './primitives.js';
|
|
23
|
+
const TABS = [
|
|
24
|
+
{ id: 'fields', label: 'Fields' },
|
|
25
|
+
{ id: 'embed', label: 'Embed' },
|
|
26
|
+
{ id: 'notifications', label: 'Notifications' },
|
|
27
|
+
];
|
|
28
|
+
export function FormSchemaDrawer({ form, open, onOpenChange, onSaved, }) {
|
|
29
|
+
const [tab, setTab] = useState('fields');
|
|
30
|
+
const [fields, setFields] = useState([]);
|
|
31
|
+
const [loading, setLoading] = useState(false);
|
|
32
|
+
const [error, setError] = useState(null);
|
|
33
|
+
const [dirty, setDirty] = useState(false);
|
|
34
|
+
const [saving, setSaving] = useState(false);
|
|
35
|
+
const [confirmDiscard, setConfirmDiscard] = useState(false);
|
|
36
|
+
const formId = form?.id ?? null;
|
|
37
|
+
const hasSubmissions = (form?.totalEntries ?? 0) > 0;
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!open || !formId)
|
|
40
|
+
return;
|
|
41
|
+
setTab('fields');
|
|
42
|
+
setDirty(false);
|
|
43
|
+
setLoading(true);
|
|
44
|
+
setError(null);
|
|
45
|
+
let active = true;
|
|
46
|
+
fetchFormSchema(formId)
|
|
47
|
+
.then((schema) => {
|
|
48
|
+
if (active)
|
|
49
|
+
setFields(schema.fields);
|
|
50
|
+
})
|
|
51
|
+
.catch((e) => {
|
|
52
|
+
if (active)
|
|
53
|
+
setError(e instanceof Error ? e.message : 'Failed to load schema');
|
|
54
|
+
})
|
|
55
|
+
.finally(() => {
|
|
56
|
+
if (active)
|
|
57
|
+
setLoading(false);
|
|
58
|
+
});
|
|
59
|
+
return () => {
|
|
60
|
+
active = false;
|
|
61
|
+
};
|
|
62
|
+
}, [open, formId]);
|
|
63
|
+
function handleFieldsChange(next) {
|
|
64
|
+
setFields(next);
|
|
65
|
+
setDirty(true);
|
|
66
|
+
}
|
|
67
|
+
async function handleSave() {
|
|
68
|
+
if (!formId)
|
|
69
|
+
return;
|
|
70
|
+
setSaving(true);
|
|
71
|
+
const res = await saveFormSchema(formId, fields.map((f, i) => ({ ...f, sortOrder: i })));
|
|
72
|
+
setSaving(false);
|
|
73
|
+
if (res.error) {
|
|
74
|
+
toast.error(res.error);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
setDirty(false);
|
|
78
|
+
toast.success('Schema saved.');
|
|
79
|
+
emitFormsChanged();
|
|
80
|
+
onSaved?.();
|
|
81
|
+
}
|
|
82
|
+
function requestClose(next) {
|
|
83
|
+
if (!next && dirty) {
|
|
84
|
+
setConfirmDiscard(true);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
onOpenChange(next);
|
|
88
|
+
}
|
|
89
|
+
if (!form)
|
|
90
|
+
return null;
|
|
91
|
+
return (_jsxs(_Fragment, { children: [_jsx(Drawer, { open: open, onOpenChange: requestClose, title: form.name, description: `/${form.slug}`, width: "max-w-2xl", footer: tab === 'fields' ? (_jsxs(_Fragment, { children: [_jsx("button", { className: btnSecondary, onClick: () => requestClose(false), children: "Close" }), _jsx("button", { className: btnPrimary, onClick: handleSave, disabled: saving || loading, children: saving ? 'Saving…' : 'Save Schema' })] })) : undefined, children: _jsxs(Tabs.Root, { value: tab, onValueChange: setTab, children: [_jsx(Tabs.List, { className: "border-border mb-4 flex gap-1 border-b", "aria-label": "Form schema sections", children: TABS.map((t) => (_jsx(Tabs.Trigger, { value: t.id, className: "text-muted-foreground hover:text-foreground data-[state=active]:text-foreground data-[state=active]:border-primary focus-visible:ring-ring -mb-px border-b-2 border-transparent px-3 py-2 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none", children: t.label }, t.id))) }), _jsx(Tabs.Content, { value: "fields", tabIndex: -1, children: loading ? (_jsx(FormsLoading, { label: "Loading schema\u2026" })) : error ? (_jsx(FormsErrorState, { message: error, onRetry: () => formId && setTab('fields') })) : (_jsx(FieldsPanel, { fields: fields, onChange: handleFieldsChange, hasSubmissions: hasSubmissions })) }), _jsx(Tabs.Content, { value: "embed", tabIndex: -1, children: formId && _jsx(EmbedPanel, { formId: formId, slug: form.slug, status: form.status }) }), _jsx(Tabs.Content, { value: "notifications", tabIndex: -1, children: formId && _jsx(NotificationsPanel, { formId: formId, onChanged: onSaved }) })] }) }), _jsx(ConfirmDialog, { open: confirmDiscard, onClose: () => setConfirmDiscard(false), onConfirm: () => {
|
|
92
|
+
setDirty(false);
|
|
93
|
+
onOpenChange(false);
|
|
94
|
+
}, title: "Discard unsaved changes?", description: "You have unsaved schema changes. Closing now will discard them.", confirmLabel: "Discard", cancelLabel: "Keep editing", destructive: true })] }));
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=FormSchemaDrawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormSchemaDrawer.js","sourceRoot":"","sources":["../../../src/components/forms/FormSchemaDrawer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function NotificationsPanel({ formId, onChanged, }: {
|
|
2
|
+
formId: string;
|
|
3
|
+
/** Called after a successful save so the list can refresh the notify state. */
|
|
4
|
+
onChanged?: () => void;
|
|
5
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
//# sourceMappingURL=NotificationsPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotificationsPanel.d.ts","sourceRoot":"","sources":["../../../src/components/forms/NotificationsPanel.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,SAAS,GACV,EAAE;IACD,MAAM,EAAE,MAAM,CAAA;IACd,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB,kDAmKA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Notifications tab of the Form Schema drawer. Persists per-form notification
|
|
5
|
+
* settings (recipients, reply-to, subject/message templates, field inclusion,
|
|
6
|
+
* autoresponder). Actual email/webhook delivery + the "send test" action are
|
|
7
|
+
* wired in a later phase (PR 6); this panel owns the configuration only.
|
|
8
|
+
*/
|
|
9
|
+
import { useEffect, useState } from 'react';
|
|
10
|
+
import * as Switch from '@radix-ui/react-switch';
|
|
11
|
+
import { toast } from 'sonner';
|
|
12
|
+
import { fetchNotificationSettings, updateNotificationSettings, } from '../../lib/forms-service.js';
|
|
13
|
+
import { emitFormsChanged } from '../../lib/forms-events.js';
|
|
14
|
+
import { FormsErrorState, FormsLoading, btnPrimary } from './primitives.js';
|
|
15
|
+
const inputCls = 'border-border bg-input-background text-foreground focus-visible:ring-ring w-full rounded-md border px-2.5 py-1.5 text-sm focus-visible:ring-2 focus-visible:outline-none';
|
|
16
|
+
export function NotificationsPanel({ formId, onChanged, }) {
|
|
17
|
+
const [settings, setSettings] = useState(null);
|
|
18
|
+
const [loading, setLoading] = useState(true);
|
|
19
|
+
const [error, setError] = useState(null);
|
|
20
|
+
const [saving, setSaving] = useState(false);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
let active = true;
|
|
23
|
+
setLoading(true);
|
|
24
|
+
setError(null);
|
|
25
|
+
fetchNotificationSettings(formId)
|
|
26
|
+
.then((s) => {
|
|
27
|
+
if (active)
|
|
28
|
+
setSettings(s);
|
|
29
|
+
})
|
|
30
|
+
.catch((e) => {
|
|
31
|
+
if (active)
|
|
32
|
+
setError(e instanceof Error ? e.message : 'Failed to load notification settings');
|
|
33
|
+
})
|
|
34
|
+
.finally(() => {
|
|
35
|
+
if (active)
|
|
36
|
+
setLoading(false);
|
|
37
|
+
});
|
|
38
|
+
return () => {
|
|
39
|
+
active = false;
|
|
40
|
+
};
|
|
41
|
+
}, [formId]);
|
|
42
|
+
function patch(p) {
|
|
43
|
+
setSettings((cur) => (cur ? { ...cur, ...p } : cur));
|
|
44
|
+
}
|
|
45
|
+
async function save() {
|
|
46
|
+
if (!settings)
|
|
47
|
+
return;
|
|
48
|
+
setSaving(true);
|
|
49
|
+
const res = await updateNotificationSettings(formId, settings);
|
|
50
|
+
setSaving(false);
|
|
51
|
+
if (res.error) {
|
|
52
|
+
toast.error(res.error);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (res.data)
|
|
56
|
+
setSettings(res.data);
|
|
57
|
+
toast.success('Notification settings saved.');
|
|
58
|
+
emitFormsChanged();
|
|
59
|
+
onChanged?.();
|
|
60
|
+
}
|
|
61
|
+
if (loading)
|
|
62
|
+
return _jsx(FormsLoading, { label: "Loading notification settings\u2026" });
|
|
63
|
+
if (error)
|
|
64
|
+
return _jsx(FormsErrorState, { message: error });
|
|
65
|
+
if (!settings)
|
|
66
|
+
return null;
|
|
67
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsx(ToggleRow, { label: "Enable notifications", help: "Email the recipients below when a new entry arrives.", checked: settings.enabled, onChange: (v) => patch({ enabled: v }) }), _jsxs("fieldset", { disabled: !settings.enabled, className: "space-y-4 transition-opacity disabled:opacity-50", children: [_jsx(Field, { label: "Recipients", hint: "Comma-separated email addresses", children: _jsx("input", { type: "text", value: settings.recipients.join(', '), onChange: (e) => patch({
|
|
68
|
+
recipients: e.target.value
|
|
69
|
+
.split(',')
|
|
70
|
+
.map((s) => s.trim())
|
|
71
|
+
.filter(Boolean),
|
|
72
|
+
}), placeholder: "team@example.com", className: inputCls }) }), _jsx(Field, { label: "Reply-to field key", hint: "Field whose value is used as the reply-to address", children: _jsx("input", { type: "text", value: settings.replyToFieldKey ?? '', onChange: (e) => patch({ replyToFieldKey: e.target.value || null }), placeholder: "email", className: inputCls }) }), _jsx(Field, { label: "Subject template", children: _jsx("input", { type: "text", value: settings.subjectTemplate ?? '', onChange: (e) => patch({ subjectTemplate: e.target.value }), placeholder: "New submission from {{name}}", className: inputCls }) }), _jsx(Field, { label: "Message template", children: _jsx("textarea", { rows: 3, value: settings.messageTemplate ?? '', onChange: (e) => patch({ messageTemplate: e.target.value }), className: inputCls }) }), _jsx(ToggleRow, { label: "Include all fields", help: "Append every submitted field to the notification body.", checked: settings.includeFields ?? true, onChange: (v) => patch({ includeFields: v }) }), _jsx(ToggleRow, { label: "Exclude sensitive fields", help: "Omit fields marked as sensitive/PII from the email.", checked: settings.excludeSensitiveFields ?? false, onChange: (v) => patch({ excludeSensitiveFields: v }) }), _jsxs("div", { className: "border-border border-t pt-4", children: [_jsx(ToggleRow, { label: "Auto-response email", help: "Send a confirmation email back to the submitter.", checked: settings.autoresponderEnabled ?? false, onChange: (v) => patch({ autoresponderEnabled: v }) }), settings.autoresponderEnabled && (_jsxs("div", { className: "mt-3 space-y-3", children: [_jsx(Field, { label: "Auto-response subject", children: _jsx("input", { type: "text", value: settings.autoresponderSubject ?? '', onChange: (e) => patch({ autoresponderSubject: e.target.value }), className: inputCls }) }), _jsx(Field, { label: "Auto-response body", children: _jsx("textarea", { rows: 3, value: settings.autoresponderBody ?? '', onChange: (e) => patch({ autoresponderBody: e.target.value }), className: inputCls }) })] }))] })] }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Email & webhook delivery (including the test action) is wired in an upcoming release. Settings saved here apply automatically once delivery is enabled." }), _jsx("div", { className: "flex justify-end", children: _jsx("button", { className: btnPrimary, onClick: save, disabled: saving, children: saving ? 'Saving…' : 'Save notifications' }) })] }));
|
|
73
|
+
}
|
|
74
|
+
function ToggleRow({ label, help, checked, onChange, }) {
|
|
75
|
+
return (_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "text-foreground block text-sm font-medium", children: label }), _jsx("span", { className: "text-muted-foreground block text-sm", children: help })] }), _jsx(Switch.Root, { checked: checked, onCheckedChange: onChange, "aria-label": label, className: "bg-destructive data-[state=checked]:bg-success focus-visible:ring-ring relative h-[18px] w-8 shrink-0 rounded-full transition-colors focus-visible:ring-2 focus-visible:outline-none", children: _jsx(Switch.Thumb, { className: "bg-background block h-3.5 w-3.5 translate-x-0.5 rounded-full shadow-sm transition-transform data-[state=checked]:translate-x-[14px]" }) })] }));
|
|
76
|
+
}
|
|
77
|
+
function Field({ label, hint, children, }) {
|
|
78
|
+
return (_jsxs("label", { className: "block", children: [_jsx("span", { className: "text-foreground mb-1 block text-sm font-medium", children: label }), children, hint && _jsx("span", { className: "text-muted-foreground mt-1 block text-xs", children: hint })] }));
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=NotificationsPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotificationsPanel.js","sourceRoot":"","sources":["../../../src/components/forms/NotificationsPanel.tsx"],"names":[],"mappings":"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"}
|