@nextlyhq/plugin-form-builder 0.0.2-alpha.34 → 0.0.2-alpha.35
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/README.md +4 -5
- package/dist/admin/index.d.ts +101 -303
- package/dist/admin/index.js +3600 -3243
- package/dist/admin/index.js.map +1 -1
- package/dist/chunk-I4VFGPNR.js +506 -0
- package/dist/chunk-I4VFGPNR.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +417 -571
- package/dist/index.js.map +1 -1
- package/dist/{index-BRumOEsE.d.ts → types-C-DcuYGF.d.ts} +61 -93
- package/package.json +22 -30
- package/dist/CheckboxFieldEditor-K4T6QX52.js +0 -121
- package/dist/CheckboxFieldEditor-K4T6QX52.js.map +0 -1
- package/dist/DateFieldEditor-JFJFAVOH.js +0 -187
- package/dist/DateFieldEditor-JFJFAVOH.js.map +0 -1
- package/dist/EmailFieldEditor-ZZ4VSKKB.js +0 -138
- package/dist/EmailFieldEditor-ZZ4VSKKB.js.map +0 -1
- package/dist/NumberFieldEditor-UISAYR6Z.js +0 -175
- package/dist/NumberFieldEditor-UISAYR6Z.js.map +0 -1
- package/dist/RadioFieldEditor-6UQFH4WT.js +0 -165
- package/dist/RadioFieldEditor-6UQFH4WT.js.map +0 -1
- package/dist/SelectFieldEditor-PSO4KHV4.js +0 -213
- package/dist/SelectFieldEditor-PSO4KHV4.js.map +0 -1
- package/dist/TextFieldEditor-5EU64EA5.js +0 -187
- package/dist/TextFieldEditor-5EU64EA5.js.map +0 -1
- package/dist/TextareaFieldEditor-773G3LNM.js +0 -190
- package/dist/TextareaFieldEditor-773G3LNM.js.map +0 -1
- package/dist/admin/index.css +0 -91
- package/dist/admin/index.css.map +0 -1
- package/dist/chunk-2LLUO3TV.js +0 -547
- package/dist/chunk-2LLUO3TV.js.map +0 -1
- package/dist/chunk-XTCEPJ7B.js +0 -256
- package/dist/chunk-XTCEPJ7B.js.map +0 -1
- package/dist/components/index.d.ts +0 -3
- package/dist/components/index.js +0 -9
- package/dist/components/index.js.map +0 -1
- package/dist/styles/form-builder.css +0 -128
- package/dist/styles/submissions-filter.css +0 -74
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/admin/fields/TextareaFieldEditor.tsx"],"sourcesContent":["/**\n * Textarea Field Editor\n *\n * Editor component for configuring textarea field properties.\n * Includes general settings (label, name, placeholder, rows, required) and\n * validation options (minLength, maxLength).\n *\n * @module admin/fields/TextareaFieldEditor\n * @since 0.1.0\n */\n\n\"use client\";\n\nimport { Input } from \"@nextlyhq/ui\";\n\nimport type { TextareaFormField } from \"../../types\";\n\nimport type { FieldEditorProps } from \"./index\";\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * TextareaFieldEditor - Configure textarea field properties\n *\n * Provides configuration options for:\n * - Label: Display text shown above the field\n * - Field Name: Key used in submission data (auto-formatted)\n * - Placeholder: Hint text shown when field is empty\n * - Help Text: Additional guidance shown below the field\n * - Rows: Number of visible text rows (height)\n * - Required: Whether the field must be filled\n * - Validation: minLength, maxLength, error message\n *\n * @example\n * ```tsx\n * <TextareaFieldEditor\n * field={textareaField}\n * allFields={formFields}\n * onUpdate={(updates) => handleUpdate(updates)}\n * />\n * ```\n */\nexport function TextareaFieldEditor({\n field,\n onUpdate,\n}: FieldEditorProps<TextareaFormField>) {\n // Helper to update validation properties\n const updateValidation = (key: string, value: unknown) => {\n onUpdate({\n validation: {\n ...field.validation,\n [key]: value,\n },\n });\n };\n\n return (\n <div className=\"textarea-field-editor\">\n {/* General Settings Section */}\n <div className=\"textarea-field-editor__section\">\n <h4 className=\"textarea-field-editor__section-title\">General</h4>\n\n {/* Label */}\n <div className=\"textarea-field-editor__field\">\n <label className=\"textarea-field-editor__label\" htmlFor=\"field-label\">\n Label\n </label>\n <Input\n id=\"field-label\"\n type=\"text\"\n value={field.label || \"\"}\n onChange={e => onUpdate({ label: e.target.value })}\n placeholder=\"Enter field label\"\n />\n </div>\n\n {/* Field Name */}\n <div className=\"textarea-field-editor__field\">\n <label className=\"textarea-field-editor__label\" htmlFor=\"field-name\">\n Field Name\n </label>\n <Input\n id=\"field-name\"\n type=\"text\"\n value={field.name || \"\"}\n onChange={e =>\n onUpdate({\n name: e.target.value\n .replace(/\\s+/g, \"_\")\n .replace(/[^a-zA-Z0-9_]/g, \"\")\n .toLowerCase(),\n })\n }\n placeholder=\"field_name\"\n className=\"textarea-field-editor__input--mono\"\n />\n <p className=\"textarea-field-editor__hint\">\n Used as the key in submission data. Only letters, numbers, and\n underscores.\n </p>\n </div>\n\n {/* Placeholder */}\n <div className=\"textarea-field-editor__field\">\n <label\n className=\"textarea-field-editor__label\"\n htmlFor=\"field-placeholder\"\n >\n Placeholder\n </label>\n <Input\n id=\"field-placeholder\"\n type=\"text\"\n value={field.placeholder || \"\"}\n onChange={e => onUpdate({ placeholder: e.target.value })}\n placeholder=\"Enter placeholder text\"\n />\n </div>\n\n {/* Help Text */}\n <div className=\"textarea-field-editor__field\">\n <label className=\"textarea-field-editor__label\" htmlFor=\"field-help\">\n Help Text\n </label>\n <Input\n id=\"field-help\"\n type=\"text\"\n value={field.helpText || \"\"}\n onChange={e => onUpdate({ helpText: e.target.value })}\n placeholder=\"Additional guidance for users\"\n />\n <p className=\"textarea-field-editor__hint\">\n Displayed below the field\n </p>\n </div>\n\n {/* Rows */}\n <div className=\"textarea-field-editor__field\">\n <label className=\"textarea-field-editor__label\" htmlFor=\"field-rows\">\n Rows\n </label>\n <Input\n id=\"field-rows\"\n type=\"number\"\n min={2}\n max={20}\n value={field.rows ?? 4}\n onChange={e =>\n onUpdate({\n rows: e.target.value ? parseInt(e.target.value, 10) : 4,\n })\n }\n placeholder=\"4\"\n />\n <p className=\"textarea-field-editor__hint\">\n Number of visible text rows (2-20)\n </p>\n </div>\n\n {/* Required */}\n <div className=\"textarea-field-editor__field textarea-field-editor__field--inline\">\n <label className=\"textarea-field-editor__checkbox-label\">\n <input\n type=\"checkbox\"\n checked={field.required || false}\n onChange={e => onUpdate({ required: e.target.checked })}\n className=\"textarea-field-editor__checkbox\"\n />\n <span>Required field</span>\n </label>\n </div>\n </div>\n\n {/* Validation Section */}\n <div className=\"textarea-field-editor__section\">\n <h4 className=\"textarea-field-editor__section-title\">Validation</h4>\n\n {/* Min/Max Length */}\n <div className=\"textarea-field-editor__field-row\">\n <div className=\"textarea-field-editor__field textarea-field-editor__field--half\">\n <label\n className=\"textarea-field-editor__label\"\n htmlFor=\"field-minlength\"\n >\n Min Length\n </label>\n <Input\n id=\"field-minlength\"\n type=\"number\"\n min={0}\n value={field.validation?.minLength ?? \"\"}\n onChange={e =>\n updateValidation(\n \"minLength\",\n e.target.value ? parseInt(e.target.value, 10) : undefined\n )\n }\n placeholder=\"0\"\n />\n </div>\n <div className=\"textarea-field-editor__field textarea-field-editor__field--half\">\n <label\n className=\"textarea-field-editor__label\"\n htmlFor=\"field-maxlength\"\n >\n Max Length\n </label>\n <Input\n id=\"field-maxlength\"\n type=\"number\"\n min={0}\n value={field.validation?.maxLength ?? \"\"}\n onChange={e =>\n updateValidation(\n \"maxLength\",\n e.target.value ? parseInt(e.target.value, 10) : undefined\n )\n }\n placeholder=\"No limit\"\n />\n </div>\n </div>\n\n {/* Error Message */}\n <div className=\"textarea-field-editor__field\">\n <label className=\"textarea-field-editor__label\" htmlFor=\"field-error\">\n Error Message\n </label>\n <Input\n id=\"field-error\"\n type=\"text\"\n value={field.validation?.errorMessage || \"\"}\n onChange={e =>\n updateValidation(\"errorMessage\", e.target.value || undefined)\n }\n placeholder=\"Please enter a valid value\"\n />\n <p className=\"textarea-field-editor__hint\">\n Custom message shown when validation fails\n </p>\n </div>\n </div>\n </div>\n );\n}\n\nexport default TextareaFieldEditor;\n"],"mappings":"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","names":[]}
|
package/dist/admin/index.css
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/* src/styles/form-builder.css */
|
|
2
|
-
.fb-builder-panel {
|
|
3
|
-
width: 360px;
|
|
4
|
-
}
|
|
5
|
-
@container content (max-width: 800px) {
|
|
6
|
-
.fb-builder-shell {
|
|
7
|
-
flex-direction: column;
|
|
8
|
-
}
|
|
9
|
-
.fb-builder-panel {
|
|
10
|
-
width: 100%;
|
|
11
|
-
border-left: 0;
|
|
12
|
-
border-top: 1px solid var(--border);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
.form-notifications-tab {
|
|
16
|
-
max-width: 800px;
|
|
17
|
-
}
|
|
18
|
-
.form-notifications-list {
|
|
19
|
-
display: flex;
|
|
20
|
-
flex-direction: column;
|
|
21
|
-
gap: 16px;
|
|
22
|
-
}
|
|
23
|
-
.form-integration-card {
|
|
24
|
-
display: flex;
|
|
25
|
-
align-items: center;
|
|
26
|
-
justify-content: space-between;
|
|
27
|
-
gap: 16px;
|
|
28
|
-
padding: 14px 16px;
|
|
29
|
-
background: var(--card);
|
|
30
|
-
border: 1px solid var(--border);
|
|
31
|
-
border-radius: var(--radius);
|
|
32
|
-
transition: border-color 0.15s ease;
|
|
33
|
-
}
|
|
34
|
-
.form-integration-card:hover {
|
|
35
|
-
border-color: var(--border-strong);
|
|
36
|
-
}
|
|
37
|
-
.form-integration-card--disabled {
|
|
38
|
-
opacity: 0.55;
|
|
39
|
-
}
|
|
40
|
-
.form-integration-card-left {
|
|
41
|
-
display: flex;
|
|
42
|
-
align-items: center;
|
|
43
|
-
gap: 12px;
|
|
44
|
-
flex: 1;
|
|
45
|
-
min-width: 0;
|
|
46
|
-
}
|
|
47
|
-
.form-integration-card-info {
|
|
48
|
-
display: flex;
|
|
49
|
-
flex-direction: column;
|
|
50
|
-
gap: 4px;
|
|
51
|
-
min-width: 0;
|
|
52
|
-
}
|
|
53
|
-
.form-integration-card-name {
|
|
54
|
-
font-size: 0.9375rem;
|
|
55
|
-
font-weight: 600;
|
|
56
|
-
color: var(--foreground);
|
|
57
|
-
white-space: nowrap;
|
|
58
|
-
overflow: hidden;
|
|
59
|
-
text-overflow: ellipsis;
|
|
60
|
-
}
|
|
61
|
-
.form-integration-provider-badge {
|
|
62
|
-
font-size: 0.75rem;
|
|
63
|
-
color: var(--muted-foreground);
|
|
64
|
-
}
|
|
65
|
-
.form-integration-card-actions {
|
|
66
|
-
display: flex;
|
|
67
|
-
gap: 8px;
|
|
68
|
-
flex-shrink: 0;
|
|
69
|
-
}
|
|
70
|
-
.form-integration-btn {
|
|
71
|
-
padding: 6px 12px;
|
|
72
|
-
font-size: 0.75rem;
|
|
73
|
-
font-weight: 500;
|
|
74
|
-
color: var(--muted-foreground);
|
|
75
|
-
background: transparent;
|
|
76
|
-
border: 1px solid var(--border);
|
|
77
|
-
border-radius: var(--radius);
|
|
78
|
-
cursor: pointer;
|
|
79
|
-
transition: all 0.15s ease;
|
|
80
|
-
}
|
|
81
|
-
.form-integration-btn--edit:hover {
|
|
82
|
-
color: var(--primary);
|
|
83
|
-
border-color: var(--primary);
|
|
84
|
-
background: color-mix(in srgb, var(--primary) 10%, transparent);
|
|
85
|
-
}
|
|
86
|
-
.form-integration-btn--delete:hover {
|
|
87
|
-
color: var(--destructive);
|
|
88
|
-
border-color: var(--destructive);
|
|
89
|
-
background: color-mix(in srgb, var(--destructive) 10%, transparent);
|
|
90
|
-
}
|
|
91
|
-
/*# sourceMappingURL=index.css.map */
|
package/dist/admin/index.css.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/styles/form-builder.css"],"sourcesContent":["/**\n * Form Builder styles\n *\n * The builder UI is driven by Tailwind utilities and @nextlyhq/ui components in its\n * React components. This file holds only the few bespoke rules those can't express:\n * 1. The two-pane builder shell (fixed inspector panel; stacks in a narrow panel)\n * 2. Notifications tab: email-integration card list (hover/variant states)\n *\n * Colors read the admin design tokens directly (`var(--token)`), so the UI looks native\n * and inherits dark mode automatically (the admin flips the tokens under `.adminapp.dark`).\n *\n * @module styles/form-builder\n * @since 0.1.0\n */\n\n/* ---------------------------------------------------------- builder shell */\n\n/* Fixed-width inspector panel beside the fluid canvas. */\n.fb-builder-panel {\n width: 360px;\n}\n\n/* Stack the canvas and inspector when the content panel itself gets narrow\n (`content` is the admin content-area container). */\n@container content (max-width: 800px) {\n .fb-builder-shell {\n flex-direction: column;\n }\n\n .fb-builder-panel {\n width: 100%;\n border-left: 0;\n border-top: 1px solid var(--border);\n }\n}\n\n/* ------------------------------------------------------- notifications tab */\n\n.form-notifications-tab {\n max-width: 800px;\n}\n\n.form-notifications-list {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n/* --------------------------------------------------- email integration cards */\n\n.form-integration-card {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 14px 16px;\n background: var(--card);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n transition: border-color 0.15s ease;\n}\n\n.form-integration-card:hover {\n border-color: var(--border-strong);\n}\n\n.form-integration-card--disabled {\n opacity: 0.55;\n}\n\n.form-integration-card-left {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n\n.form-integration-card-info {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.form-integration-card-name {\n font-size: 0.9375rem;\n font-weight: 600;\n color: var(--foreground);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.form-integration-provider-badge {\n font-size: 0.75rem;\n color: var(--muted-foreground);\n}\n\n.form-integration-card-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.form-integration-btn {\n padding: 6px 12px;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--muted-foreground);\n background: transparent;\n border: 1px solid var(--border);\n border-radius: var(--radius);\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.form-integration-btn--edit:hover {\n color: var(--primary);\n border-color: var(--primary);\n background: color-mix(in srgb, var(--primary) 10%, transparent);\n}\n\n.form-integration-btn--delete:hover {\n color: var(--destructive);\n border-color: var(--destructive);\n background: color-mix(in srgb, var(--destructive) 10%, transparent);\n}\n"],"mappings":";AAkBA,CAAC;AACC,SAAO;AACT;AAIA,WAAW,QAAQ,CAAC,SAAS,EAAE;AAC7B,GAAC;AACC,oBAAgB;AAClB;AAEA,GAXD;AAYG,WAAO;AACP,iBAAa;AACb,gBAAY,IAAI,MAAM,IAAI;AAC5B;AACF;AAIA,CAAC;AACC,aAAW;AACb;AAEA,CAAC;AACC,WAAS;AACT,kBAAgB;AAChB,OAAK;AACP;AAIA,CAAC;AACC,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,OAAK;AACL,WAAS,KAAK;AACd,cAAY,IAAI;AAChB,UAAQ,IAAI,MAAM,IAAI;AACtB,iBAAe,IAAI;AACnB,cAAY,aAAa,MAAM;AACjC;AAEA,CAZC,qBAYqB;AACpB,gBAAc,IAAI;AACpB;AAEA,CAAC;AACC,WAAS;AACX;AAEA,CAAC;AACC,WAAS;AACT,eAAa;AACb,OAAK;AACL,QAAM;AACN,aAAW;AACb;AAEA,CAAC;AACC,WAAS;AACT,kBAAgB;AAChB,OAAK;AACL,aAAW;AACb;AAEA,CAAC;AACC,aAAW;AACX,eAAa;AACb,SAAO,IAAI;AACX,eAAa;AACb,YAAU;AACV,iBAAe;AACjB;AAEA,CAAC;AACC,aAAW;AACX,SAAO,IAAI;AACb;AAEA,CAAC;AACC,WAAS;AACT,OAAK;AACL,eAAa;AACf;AAEA,CAAC;AACC,WAAS,IAAI;AACb,aAAW;AACX,eAAa;AACb,SAAO,IAAI;AACX,cAAY;AACZ,UAAQ,IAAI,MAAM,IAAI;AACtB,iBAAe,IAAI;AACnB,UAAQ;AACR,cAAY,IAAI,MAAM;AACxB;AAEA,CAAC,0BAA0B;AACzB,SAAO,IAAI;AACX,gBAAc,IAAI;AAClB,cAAY,UAAU,GAAG,IAAI,EAAE,IAAI,WAAW,GAAG,EAAE;AACrD;AAEA,CAAC,4BAA4B;AAC3B,SAAO,IAAI;AACX,gBAAc,IAAI;AAClB,cAAY,UAAU,GAAG,IAAI,EAAE,IAAI,eAAe,GAAG,EAAE;AACzD;","names":[]}
|
package/dist/chunk-2LLUO3TV.js
DELETED
|
@@ -1,547 +0,0 @@
|
|
|
1
|
-
// src/components/submissions/SubmissionList.tsx
|
|
2
|
-
import { DataTableView } from "@nextlyhq/plugin-sdk/admin";
|
|
3
|
-
import { useState, useCallback, useMemo } from "react";
|
|
4
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
function formatValue(value) {
|
|
6
|
-
if (value === null || value === void 0) return "-";
|
|
7
|
-
if (Array.isArray(value)) return value.join(", ");
|
|
8
|
-
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
9
|
-
if (value instanceof Date) return value.toLocaleDateString();
|
|
10
|
-
let str;
|
|
11
|
-
if (typeof value === "object") {
|
|
12
|
-
str = JSON.stringify(value);
|
|
13
|
-
} else {
|
|
14
|
-
str = String(value);
|
|
15
|
-
}
|
|
16
|
-
return str.length > 50 ? str.slice(0, 50) + "..." : str;
|
|
17
|
-
}
|
|
18
|
-
function formatDate(date) {
|
|
19
|
-
const d = typeof date === "string" ? new Date(date) : date;
|
|
20
|
-
return d.toLocaleString();
|
|
21
|
-
}
|
|
22
|
-
function SubmissionList({
|
|
23
|
-
form,
|
|
24
|
-
submissions,
|
|
25
|
-
isLoading = false,
|
|
26
|
-
onStatusChange,
|
|
27
|
-
onDelete,
|
|
28
|
-
onBulkDelete,
|
|
29
|
-
onBulkStatusChange,
|
|
30
|
-
onExport,
|
|
31
|
-
onViewDetail
|
|
32
|
-
}) {
|
|
33
|
-
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
34
|
-
const [filter, setFilter] = useState("all");
|
|
35
|
-
const [processingIds, setProcessingIds] = useState(/* @__PURE__ */ new Set());
|
|
36
|
-
const displayFields = useMemo(() => {
|
|
37
|
-
return form.fields.filter((f) => f.type !== "hidden").slice(0, 3);
|
|
38
|
-
}, [form.fields]);
|
|
39
|
-
const filteredSubmissions = useMemo(() => {
|
|
40
|
-
if (filter === "all") return submissions;
|
|
41
|
-
return submissions.filter((sub) => sub.status === filter);
|
|
42
|
-
}, [submissions, filter]);
|
|
43
|
-
const someSelected = selectedIds.size > 0;
|
|
44
|
-
const toggleSelect = useCallback((id) => {
|
|
45
|
-
setSelectedIds((prev) => {
|
|
46
|
-
const next = new Set(prev);
|
|
47
|
-
if (next.has(id)) {
|
|
48
|
-
next.delete(id);
|
|
49
|
-
} else {
|
|
50
|
-
next.add(id);
|
|
51
|
-
}
|
|
52
|
-
return next;
|
|
53
|
-
});
|
|
54
|
-
}, []);
|
|
55
|
-
const handleStatusChange = useCallback(
|
|
56
|
-
async (id, status) => {
|
|
57
|
-
if (!onStatusChange) return;
|
|
58
|
-
setProcessingIds((prev) => new Set(prev).add(id));
|
|
59
|
-
try {
|
|
60
|
-
await onStatusChange(id, status);
|
|
61
|
-
} finally {
|
|
62
|
-
setProcessingIds((prev) => {
|
|
63
|
-
const next = new Set(prev);
|
|
64
|
-
next.delete(id);
|
|
65
|
-
return next;
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
[onStatusChange]
|
|
70
|
-
);
|
|
71
|
-
const handleDelete = useCallback(
|
|
72
|
-
async (id) => {
|
|
73
|
-
if (!onDelete) return;
|
|
74
|
-
if (!window.confirm("Are you sure you want to delete this submission?")) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
setProcessingIds((prev) => new Set(prev).add(id));
|
|
78
|
-
try {
|
|
79
|
-
await onDelete(id);
|
|
80
|
-
setSelectedIds((prev) => {
|
|
81
|
-
const next = new Set(prev);
|
|
82
|
-
next.delete(id);
|
|
83
|
-
return next;
|
|
84
|
-
});
|
|
85
|
-
} finally {
|
|
86
|
-
setProcessingIds((prev) => {
|
|
87
|
-
const next = new Set(prev);
|
|
88
|
-
next.delete(id);
|
|
89
|
-
return next;
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
[onDelete]
|
|
94
|
-
);
|
|
95
|
-
const handleBulkDelete = useCallback(async () => {
|
|
96
|
-
if (!onBulkDelete || selectedIds.size === 0) return;
|
|
97
|
-
if (!window.confirm(
|
|
98
|
-
`Are you sure you want to delete ${selectedIds.size} submission(s)?`
|
|
99
|
-
)) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const ids = Array.from(selectedIds);
|
|
103
|
-
ids.forEach((id) => setProcessingIds((prev) => new Set(prev).add(id)));
|
|
104
|
-
try {
|
|
105
|
-
await onBulkDelete(ids);
|
|
106
|
-
setSelectedIds(/* @__PURE__ */ new Set());
|
|
107
|
-
} finally {
|
|
108
|
-
setProcessingIds(/* @__PURE__ */ new Set());
|
|
109
|
-
}
|
|
110
|
-
}, [onBulkDelete, selectedIds]);
|
|
111
|
-
const handleBulkStatusChange = useCallback(
|
|
112
|
-
async (status) => {
|
|
113
|
-
if (!onBulkStatusChange || selectedIds.size === 0) return;
|
|
114
|
-
const ids = Array.from(selectedIds);
|
|
115
|
-
ids.forEach((id) => setProcessingIds((prev) => new Set(prev).add(id)));
|
|
116
|
-
try {
|
|
117
|
-
await onBulkStatusChange(ids, status);
|
|
118
|
-
setSelectedIds(/* @__PURE__ */ new Set());
|
|
119
|
-
} finally {
|
|
120
|
-
setProcessingIds(/* @__PURE__ */ new Set());
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
[onBulkStatusChange, selectedIds]
|
|
124
|
-
);
|
|
125
|
-
const columns = useMemo(() => {
|
|
126
|
-
const base = [
|
|
127
|
-
{
|
|
128
|
-
name: "id",
|
|
129
|
-
header: "ID",
|
|
130
|
-
cell: ({ row }) => /* @__PURE__ */ jsxs("code", { className: "font-mono text-xs text-muted-foreground", children: [
|
|
131
|
-
row.id.slice(0, 8),
|
|
132
|
-
"..."
|
|
133
|
-
] })
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
name: "status",
|
|
137
|
-
header: "Status",
|
|
138
|
-
cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-none border border-border bg-muted px-2 py-0.5 text-[11px] font-medium capitalize text-foreground", children: row.status })
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
name: "submittedAt",
|
|
142
|
-
header: "Submitted",
|
|
143
|
-
hideOnMobile: true,
|
|
144
|
-
cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap text-sm text-muted-foreground", children: formatDate(row.submittedAt) })
|
|
145
|
-
}
|
|
146
|
-
];
|
|
147
|
-
const fieldColumns = displayFields.map(
|
|
148
|
-
(field) => ({
|
|
149
|
-
name: `field:${field.name}`,
|
|
150
|
-
header: field.label,
|
|
151
|
-
hideOnMobile: true,
|
|
152
|
-
cell: ({ row }) => /* @__PURE__ */ jsx("span", { className: "text-sm", children: formatValue(row.data[field.name]) })
|
|
153
|
-
})
|
|
154
|
-
);
|
|
155
|
-
return [...base, ...fieldColumns];
|
|
156
|
-
}, [displayFields]);
|
|
157
|
-
const selection = useMemo(
|
|
158
|
-
() => ({
|
|
159
|
-
selectedIds: Array.from(selectedIds),
|
|
160
|
-
onToggle: (submission) => toggleSelect(submission.id),
|
|
161
|
-
onToggleAll: (rows, allChecked) => {
|
|
162
|
-
const ids = rows.map((r) => r.id);
|
|
163
|
-
setSelectedIds((prev) => {
|
|
164
|
-
const next = new Set(prev);
|
|
165
|
-
if (allChecked) ids.forEach((id) => next.delete(id));
|
|
166
|
-
else ids.forEach((id) => next.add(id));
|
|
167
|
-
return next;
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
}),
|
|
171
|
-
[selectedIds, toggleSelect]
|
|
172
|
-
);
|
|
173
|
-
const rowActions = useCallback(() => {
|
|
174
|
-
const actions = [];
|
|
175
|
-
if (onStatusChange) {
|
|
176
|
-
actions.push(
|
|
177
|
-
{
|
|
178
|
-
id: "mark-read",
|
|
179
|
-
label: "Mark Read",
|
|
180
|
-
isVisible: (r) => r.status !== "read",
|
|
181
|
-
isDisabled: (r) => processingIds.has(r.id),
|
|
182
|
-
onSelect: (r) => void handleStatusChange(r.id, "read")
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
id: "archive",
|
|
186
|
-
label: "Archive",
|
|
187
|
-
isVisible: (r) => r.status !== "archived",
|
|
188
|
-
isDisabled: (r) => processingIds.has(r.id),
|
|
189
|
-
onSelect: (r) => void handleStatusChange(r.id, "archived")
|
|
190
|
-
}
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
if (onDelete) {
|
|
194
|
-
actions.push({
|
|
195
|
-
id: "delete",
|
|
196
|
-
label: "Delete",
|
|
197
|
-
destructive: true,
|
|
198
|
-
isDisabled: (r) => processingIds.has(r.id),
|
|
199
|
-
onSelect: (r) => void handleDelete(r.id)
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
return actions;
|
|
203
|
-
}, [
|
|
204
|
-
onStatusChange,
|
|
205
|
-
onDelete,
|
|
206
|
-
processingIds,
|
|
207
|
-
handleStatusChange,
|
|
208
|
-
handleDelete
|
|
209
|
-
]);
|
|
210
|
-
return /* @__PURE__ */ jsxs("div", { className: "submission-list", children: [
|
|
211
|
-
/* @__PURE__ */ jsxs("div", { className: "submission-list__toolbar", children: [
|
|
212
|
-
/* @__PURE__ */ jsx("div", { className: "submission-list__filters", children: /* @__PURE__ */ jsxs(
|
|
213
|
-
"select",
|
|
214
|
-
{
|
|
215
|
-
value: filter,
|
|
216
|
-
onChange: (e) => setFilter(e.target.value),
|
|
217
|
-
className: "submission-list__filter-select",
|
|
218
|
-
"aria-label": "Filter by status",
|
|
219
|
-
children: [
|
|
220
|
-
/* @__PURE__ */ jsxs("option", { value: "all", children: [
|
|
221
|
-
"All Submissions (",
|
|
222
|
-
submissions.length,
|
|
223
|
-
")"
|
|
224
|
-
] }),
|
|
225
|
-
/* @__PURE__ */ jsxs("option", { value: "new", children: [
|
|
226
|
-
"New (",
|
|
227
|
-
submissions.filter((s) => s.status === "new").length,
|
|
228
|
-
")"
|
|
229
|
-
] }),
|
|
230
|
-
/* @__PURE__ */ jsxs("option", { value: "read", children: [
|
|
231
|
-
"Read (",
|
|
232
|
-
submissions.filter((s) => s.status === "read").length,
|
|
233
|
-
")"
|
|
234
|
-
] }),
|
|
235
|
-
/* @__PURE__ */ jsxs("option", { value: "archived", children: [
|
|
236
|
-
"Archived (",
|
|
237
|
-
submissions.filter((s) => s.status === "archived").length,
|
|
238
|
-
")"
|
|
239
|
-
] })
|
|
240
|
-
]
|
|
241
|
-
}
|
|
242
|
-
) }),
|
|
243
|
-
/* @__PURE__ */ jsxs("div", { className: "submission-list__actions", children: [
|
|
244
|
-
someSelected && /* @__PURE__ */ jsxs("div", { className: "submission-list__bulk-actions", children: [
|
|
245
|
-
/* @__PURE__ */ jsxs("span", { className: "submission-list__selected-count", children: [
|
|
246
|
-
selectedIds.size,
|
|
247
|
-
" selected"
|
|
248
|
-
] }),
|
|
249
|
-
onBulkStatusChange && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
250
|
-
/* @__PURE__ */ jsx(
|
|
251
|
-
"button",
|
|
252
|
-
{
|
|
253
|
-
type: "button",
|
|
254
|
-
onClick: () => void handleBulkStatusChange("read"),
|
|
255
|
-
className: "submission-list__action-btn",
|
|
256
|
-
children: "Mark Read"
|
|
257
|
-
}
|
|
258
|
-
),
|
|
259
|
-
/* @__PURE__ */ jsx(
|
|
260
|
-
"button",
|
|
261
|
-
{
|
|
262
|
-
type: "button",
|
|
263
|
-
onClick: () => void handleBulkStatusChange("archived"),
|
|
264
|
-
className: "submission-list__action-btn",
|
|
265
|
-
children: "Archive"
|
|
266
|
-
}
|
|
267
|
-
)
|
|
268
|
-
] }),
|
|
269
|
-
onBulkDelete && /* @__PURE__ */ jsx(
|
|
270
|
-
"button",
|
|
271
|
-
{
|
|
272
|
-
type: "button",
|
|
273
|
-
onClick: () => void handleBulkDelete(),
|
|
274
|
-
className: "submission-list__action-btn submission-list__action-btn--danger",
|
|
275
|
-
children: "Delete"
|
|
276
|
-
}
|
|
277
|
-
)
|
|
278
|
-
] }),
|
|
279
|
-
onExport && /* @__PURE__ */ jsxs("div", { className: "submission-list__export-actions", children: [
|
|
280
|
-
/* @__PURE__ */ jsx(
|
|
281
|
-
"button",
|
|
282
|
-
{
|
|
283
|
-
type: "button",
|
|
284
|
-
onClick: () => onExport("csv"),
|
|
285
|
-
className: "submission-list__export-btn",
|
|
286
|
-
children: "Export CSV"
|
|
287
|
-
}
|
|
288
|
-
),
|
|
289
|
-
/* @__PURE__ */ jsx(
|
|
290
|
-
"button",
|
|
291
|
-
{
|
|
292
|
-
type: "button",
|
|
293
|
-
onClick: () => onExport("json"),
|
|
294
|
-
className: "submission-list__export-btn",
|
|
295
|
-
children: "Export JSON"
|
|
296
|
-
}
|
|
297
|
-
)
|
|
298
|
-
] })
|
|
299
|
-
] })
|
|
300
|
-
] }),
|
|
301
|
-
/* @__PURE__ */ jsx(
|
|
302
|
-
DataTableView,
|
|
303
|
-
{
|
|
304
|
-
columns,
|
|
305
|
-
rows: filteredSubmissions,
|
|
306
|
-
loading: isLoading,
|
|
307
|
-
selection,
|
|
308
|
-
rowActions,
|
|
309
|
-
onRowClick: onViewDetail ? (submission) => onViewDetail(submission) : void 0,
|
|
310
|
-
registryKey: "form-submissions",
|
|
311
|
-
ariaLabel: "Form submissions table",
|
|
312
|
-
emptyMessage: "No submissions found"
|
|
313
|
-
}
|
|
314
|
-
),
|
|
315
|
-
/* @__PURE__ */ jsxs("div", { className: "submission-list__summary", children: [
|
|
316
|
-
"Showing ",
|
|
317
|
-
filteredSubmissions.length,
|
|
318
|
-
" of ",
|
|
319
|
-
submissions.length,
|
|
320
|
-
" submissions"
|
|
321
|
-
] })
|
|
322
|
-
] });
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// src/components/submissions/SubmissionDetail.tsx
|
|
326
|
-
import { useState as useState2, useCallback as useCallback2 } from "react";
|
|
327
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
328
|
-
function safeString(value) {
|
|
329
|
-
if (typeof value === "object" && value !== null) {
|
|
330
|
-
return JSON.stringify(value);
|
|
331
|
-
}
|
|
332
|
-
return String(value);
|
|
333
|
-
}
|
|
334
|
-
function formatFieldValue(value, field) {
|
|
335
|
-
if (value === null || value === void 0) return "-";
|
|
336
|
-
switch (field.type) {
|
|
337
|
-
case "checkbox":
|
|
338
|
-
return value ? "Yes" : "No";
|
|
339
|
-
case "select":
|
|
340
|
-
if (Array.isArray(value)) {
|
|
341
|
-
return value.join(", ");
|
|
342
|
-
}
|
|
343
|
-
return safeString(value);
|
|
344
|
-
case "file":
|
|
345
|
-
if (Array.isArray(value)) {
|
|
346
|
-
return value.map((v) => safeString(v)).join(", ");
|
|
347
|
-
}
|
|
348
|
-
return safeString(value);
|
|
349
|
-
case "date":
|
|
350
|
-
if (value instanceof Date) {
|
|
351
|
-
return value.toLocaleDateString();
|
|
352
|
-
}
|
|
353
|
-
if (typeof value === "string") {
|
|
354
|
-
return new Date(value).toLocaleDateString();
|
|
355
|
-
}
|
|
356
|
-
return safeString(value);
|
|
357
|
-
case "time":
|
|
358
|
-
return safeString(value);
|
|
359
|
-
default:
|
|
360
|
-
return safeString(value);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
function formatDate2(date) {
|
|
364
|
-
const d = typeof date === "string" ? new Date(date) : date;
|
|
365
|
-
return d.toLocaleString();
|
|
366
|
-
}
|
|
367
|
-
var STATUS_OPTIONS = [
|
|
368
|
-
{ value: "new", label: "New" },
|
|
369
|
-
{ value: "read", label: "Read" },
|
|
370
|
-
{ value: "archived", label: "Archived" }
|
|
371
|
-
];
|
|
372
|
-
function SubmissionDetail({
|
|
373
|
-
form,
|
|
374
|
-
submission,
|
|
375
|
-
onStatusChange,
|
|
376
|
-
onNotesUpdate,
|
|
377
|
-
onBack,
|
|
378
|
-
onDelete
|
|
379
|
-
}) {
|
|
380
|
-
const [isProcessing, setIsProcessing] = useState2(false);
|
|
381
|
-
const [notes, setNotes] = useState2(
|
|
382
|
-
submission.notes || ""
|
|
383
|
-
);
|
|
384
|
-
const [notesModified, setNotesModified] = useState2(false);
|
|
385
|
-
const handleStatusChange = useCallback2(
|
|
386
|
-
async (event) => {
|
|
387
|
-
if (!onStatusChange) return;
|
|
388
|
-
const newStatus = event.target.value;
|
|
389
|
-
setIsProcessing(true);
|
|
390
|
-
try {
|
|
391
|
-
await onStatusChange(newStatus);
|
|
392
|
-
} finally {
|
|
393
|
-
setIsProcessing(false);
|
|
394
|
-
}
|
|
395
|
-
},
|
|
396
|
-
[onStatusChange]
|
|
397
|
-
);
|
|
398
|
-
const handleNotesChange = useCallback2(
|
|
399
|
-
(event) => {
|
|
400
|
-
setNotes(event.target.value);
|
|
401
|
-
setNotesModified(true);
|
|
402
|
-
},
|
|
403
|
-
[]
|
|
404
|
-
);
|
|
405
|
-
const handleNotesSave = useCallback2(async () => {
|
|
406
|
-
if (!onNotesUpdate || !notesModified) return;
|
|
407
|
-
setIsProcessing(true);
|
|
408
|
-
try {
|
|
409
|
-
await onNotesUpdate(notes);
|
|
410
|
-
setNotesModified(false);
|
|
411
|
-
} finally {
|
|
412
|
-
setIsProcessing(false);
|
|
413
|
-
}
|
|
414
|
-
}, [onNotesUpdate, notes, notesModified]);
|
|
415
|
-
const handleDelete = useCallback2(async () => {
|
|
416
|
-
if (!onDelete) return;
|
|
417
|
-
if (!window.confirm("Are you sure you want to delete this submission?")) {
|
|
418
|
-
return;
|
|
419
|
-
}
|
|
420
|
-
setIsProcessing(true);
|
|
421
|
-
try {
|
|
422
|
-
await onDelete();
|
|
423
|
-
} finally {
|
|
424
|
-
setIsProcessing(false);
|
|
425
|
-
}
|
|
426
|
-
}, [onDelete]);
|
|
427
|
-
const displayFields = form.fields;
|
|
428
|
-
const data = submission.data;
|
|
429
|
-
return /* @__PURE__ */ jsxs2("div", { className: "submission-detail", children: [
|
|
430
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__header", children: [
|
|
431
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__header-left", children: [
|
|
432
|
-
onBack && /* @__PURE__ */ jsx2(
|
|
433
|
-
"button",
|
|
434
|
-
{
|
|
435
|
-
type: "button",
|
|
436
|
-
onClick: onBack,
|
|
437
|
-
className: "submission-detail__back-btn",
|
|
438
|
-
disabled: isProcessing,
|
|
439
|
-
children: "\u2190 Back to List"
|
|
440
|
-
}
|
|
441
|
-
),
|
|
442
|
-
/* @__PURE__ */ jsx2("h2", { className: "submission-detail__title", children: "Submission Details" })
|
|
443
|
-
] }),
|
|
444
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__header-right", children: [
|
|
445
|
-
onStatusChange && /* @__PURE__ */ jsxs2("div", { className: "submission-detail__status-control", children: [
|
|
446
|
-
/* @__PURE__ */ jsx2("label", { htmlFor: "submission-status", children: "Status:" }),
|
|
447
|
-
/* @__PURE__ */ jsx2(
|
|
448
|
-
"select",
|
|
449
|
-
{
|
|
450
|
-
id: "submission-status",
|
|
451
|
-
value: submission.status,
|
|
452
|
-
onChange: (e) => void handleStatusChange(e),
|
|
453
|
-
disabled: isProcessing,
|
|
454
|
-
className: "submission-detail__status-select",
|
|
455
|
-
children: STATUS_OPTIONS.map((option) => /* @__PURE__ */ jsx2("option", { value: option.value, children: option.label }, option.value))
|
|
456
|
-
}
|
|
457
|
-
)
|
|
458
|
-
] }),
|
|
459
|
-
onDelete && /* @__PURE__ */ jsx2(
|
|
460
|
-
"button",
|
|
461
|
-
{
|
|
462
|
-
type: "button",
|
|
463
|
-
onClick: () => void handleDelete(),
|
|
464
|
-
disabled: isProcessing,
|
|
465
|
-
className: "submission-detail__delete-btn",
|
|
466
|
-
children: "Delete"
|
|
467
|
-
}
|
|
468
|
-
)
|
|
469
|
-
] })
|
|
470
|
-
] }),
|
|
471
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__id", children: [
|
|
472
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__id-label", children: "Submission ID:" }),
|
|
473
|
-
/* @__PURE__ */ jsx2("code", { className: "submission-detail__id-value", children: submission.id })
|
|
474
|
-
] }),
|
|
475
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__section", children: [
|
|
476
|
-
/* @__PURE__ */ jsx2("h3", { className: "submission-detail__section-title", children: "Submitted Data" }),
|
|
477
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__fields", children: [
|
|
478
|
-
displayFields.map((field) => /* @__PURE__ */ jsxs2("div", { className: "submission-detail__field", children: [
|
|
479
|
-
/* @__PURE__ */ jsx2("div", { className: "submission-detail__field-label", children: field.label }),
|
|
480
|
-
/* @__PURE__ */ jsx2("div", { className: "submission-detail__field-value", children: formatFieldValue(data[field.name], field) })
|
|
481
|
-
] }, field.name)),
|
|
482
|
-
displayFields.length === 0 && /* @__PURE__ */ jsx2("div", { className: "submission-detail__empty", children: "No fields to display" })
|
|
483
|
-
] })
|
|
484
|
-
] }),
|
|
485
|
-
onNotesUpdate && /* @__PURE__ */ jsxs2("div", { className: "submission-detail__section", children: [
|
|
486
|
-
/* @__PURE__ */ jsx2("h3", { className: "submission-detail__section-title", children: "Internal Notes" }),
|
|
487
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__notes", children: [
|
|
488
|
-
/* @__PURE__ */ jsx2(
|
|
489
|
-
"textarea",
|
|
490
|
-
{
|
|
491
|
-
value: notes,
|
|
492
|
-
onChange: handleNotesChange,
|
|
493
|
-
placeholder: "Add internal notes about this submission...",
|
|
494
|
-
disabled: isProcessing,
|
|
495
|
-
className: "submission-detail__notes-textarea",
|
|
496
|
-
rows: 4
|
|
497
|
-
}
|
|
498
|
-
),
|
|
499
|
-
notesModified && /* @__PURE__ */ jsx2(
|
|
500
|
-
"button",
|
|
501
|
-
{
|
|
502
|
-
type: "button",
|
|
503
|
-
onClick: () => void handleNotesSave(),
|
|
504
|
-
disabled: isProcessing,
|
|
505
|
-
className: "submission-detail__notes-save-btn",
|
|
506
|
-
children: "Save Notes"
|
|
507
|
-
}
|
|
508
|
-
)
|
|
509
|
-
] })
|
|
510
|
-
] }),
|
|
511
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__section", children: [
|
|
512
|
-
/* @__PURE__ */ jsx2("h3", { className: "submission-detail__section-title", children: "Metadata" }),
|
|
513
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__metadata", children: [
|
|
514
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__metadata-item", children: [
|
|
515
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__metadata-label", children: "Submitted At:" }),
|
|
516
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__metadata-value", children: formatDate2(submission.submittedAt) })
|
|
517
|
-
] }),
|
|
518
|
-
submission.ipAddress && /* @__PURE__ */ jsxs2("div", { className: "submission-detail__metadata-item", children: [
|
|
519
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__metadata-label", children: "IP Address:" }),
|
|
520
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__metadata-value", children: /* @__PURE__ */ jsx2("code", { children: submission.ipAddress }) })
|
|
521
|
-
] }),
|
|
522
|
-
submission.userAgent && /* @__PURE__ */ jsxs2("div", { className: "submission-detail__metadata-item", children: [
|
|
523
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__metadata-label", children: "User Agent:" }),
|
|
524
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__metadata-value submission-detail__metadata-value--truncate", children: submission.userAgent })
|
|
525
|
-
] }),
|
|
526
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__metadata-item", children: [
|
|
527
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__metadata-label", children: "Created At:" }),
|
|
528
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__metadata-value", children: formatDate2(submission.createdAt) })
|
|
529
|
-
] }),
|
|
530
|
-
/* @__PURE__ */ jsxs2("div", { className: "submission-detail__metadata-item", children: [
|
|
531
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__metadata-label", children: "Updated At:" }),
|
|
532
|
-
/* @__PURE__ */ jsx2("span", { className: "submission-detail__metadata-value", children: formatDate2(submission.updatedAt) })
|
|
533
|
-
] })
|
|
534
|
-
] })
|
|
535
|
-
] }),
|
|
536
|
-
/* @__PURE__ */ jsxs2("details", { className: "submission-detail__raw-data", children: [
|
|
537
|
-
/* @__PURE__ */ jsx2("summary", { className: "submission-detail__raw-data-summary", children: "View Raw JSON Data" }),
|
|
538
|
-
/* @__PURE__ */ jsx2("pre", { className: "submission-detail__raw-data-content", children: JSON.stringify(submission.data, null, 2) })
|
|
539
|
-
] })
|
|
540
|
-
] });
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
export {
|
|
544
|
-
SubmissionList,
|
|
545
|
-
SubmissionDetail
|
|
546
|
-
};
|
|
547
|
-
//# sourceMappingURL=chunk-2LLUO3TV.js.map
|