@orion-studios/payload-studio 0.6.0-beta.17 → 0.6.0-beta.19

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.
@@ -1171,6 +1171,9 @@ __export(client_exports, {
1171
1171
  AdminStudioContactFormView: () => AdminStudioContactFormView,
1172
1172
  AdminStudioDashboard: () => AdminStudioDashboard,
1173
1173
  AdminStudioFooterGlobalView: () => AdminStudioFooterGlobalView,
1174
+ AdminStudioFormDetailView: () => AdminStudioFormDetailView,
1175
+ AdminStudioFormSubmissionView: () => AdminStudioFormSubmissionView,
1176
+ AdminStudioFormUploadView: () => AdminStudioFormUploadView,
1174
1177
  AdminStudioFormsView: () => AdminStudioFormsView,
1175
1178
  AdminStudioGlobalsView: () => AdminStudioGlobalsView,
1176
1179
  AdminStudioHeaderGlobalView: () => AdminStudioHeaderGlobalView,
@@ -1196,6 +1199,7 @@ __export(client_exports, {
1196
1199
  StatusBadge: () => StatusBadge,
1197
1200
  StudioBackBreadcrumb: () => StudioBackBreadcrumb,
1198
1201
  StudioContactFormRedirect: () => StudioContactFormRedirect,
1202
+ StudioDocumentRedirect: () => StudioDocumentRedirect,
1199
1203
  StudioSectionLayout: () => StudioSectionLayout,
1200
1204
  ThemeProvider: () => ThemeProvider,
1201
1205
  ThemeSwitcher: () => ThemeSwitcher,
@@ -7723,14 +7727,10 @@ function AdminStudioFormsView(props) {
7723
7727
  "formSubmissionsCollectionSlug",
7724
7728
  "form-submissions"
7725
7729
  );
7726
- const formUploadsCollectionSlug = getPropString13(props, "formUploadsCollectionSlug", "form-uploads");
7727
7730
  const adminBasePath = useAdminBasePath();
7728
- const rawFormsPath = resolveAdminPath(adminBasePath, `/collections/${formsCollectionSlug}`);
7729
- const rawSubmissionsPath = resolveAdminPath(
7730
- adminBasePath,
7731
- `/collections/${formSubmissionsCollectionSlug}`
7732
- );
7733
- const rawUploadsPath = resolveAdminPath(adminBasePath, `/collections/${formUploadsCollectionSlug}`);
7731
+ const studioFormsPath = resolveAdminPath(adminBasePath, "/forms");
7732
+ const studioSubmissionsPath = resolveAdminPath(adminBasePath, "/forms/submissions");
7733
+ const studioUploadsPath = resolveAdminPath(adminBasePath, "/forms/uploads");
7734
7734
  const [forms, setForms] = (0, import_react31.useState)([]);
7735
7735
  const [submissions, setSubmissions] = (0, import_react31.useState)([]);
7736
7736
  const [loading, setLoading] = (0, import_react31.useState)(true);
@@ -7890,7 +7890,7 @@ function AdminStudioFormsView(props) {
7890
7890
  import_link3.default,
7891
7891
  {
7892
7892
  className: "orion-admin-action-button orion-admin-action-button--soft",
7893
- href: `${rawFormsPath}/${id}`,
7893
+ href: `${studioFormsPath}/${id}`,
7894
7894
  children: "Open Form"
7895
7895
  }
7896
7896
  )
@@ -7992,7 +7992,7 @@ function AdminStudioFormsView(props) {
7992
7992
  import_link3.default,
7993
7993
  {
7994
7994
  className: "orion-admin-upload-chip",
7995
- href: `${rawUploadsPath}/${uploadID}`,
7995
+ href: `${studioUploadsPath}/${uploadID}`,
7996
7996
  children: uploadLabel
7997
7997
  },
7998
7998
  uploadID
@@ -8009,7 +8009,7 @@ function AdminStudioFormsView(props) {
8009
8009
  import_link3.default,
8010
8010
  {
8011
8011
  className: "orion-admin-action-button orion-admin-action-button--ghost",
8012
- href: `${rawSubmissionsPath}/${submissionID}`,
8012
+ href: `${studioSubmissionsPath}/${submissionID}`,
8013
8013
  children: "Open"
8014
8014
  }
8015
8015
  )
@@ -8029,94 +8029,1359 @@ function AdminStudioFormsView(props) {
8029
8029
  ) });
8030
8030
  }
8031
8031
 
8032
- // src/admin/components/studio/AdminStudioToolsView.tsx
8032
+ // src/admin/components/studio/AdminStudioFormDetailView.tsx
8033
+ var import_link4 = __toESM(require("next/link"));
8033
8034
  var import_react32 = require("react");
8034
- var import_ui12 = require("@payloadcms/ui");
8035
+
8036
+ // src/admin/components/studio/formsStudioShared.ts
8037
+ var FORM_TONES2 = [
8038
+ {
8039
+ accent: "var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent)))",
8040
+ accentBorder: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 24%, transparent)",
8041
+ accentMist: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 12%, transparent)",
8042
+ accentSoft: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 7%, transparent)"
8043
+ },
8044
+ {
8045
+ accent: "var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent)))",
8046
+ accentBorder: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 24%, transparent)",
8047
+ accentMist: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 13%, transparent)",
8048
+ accentSoft: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 8%, transparent)"
8049
+ },
8050
+ {
8051
+ accent: "var(--orion-cms-tone-3, color-mix(in srgb, var(--orion-cms-accent, var(--orion-admin-accent)) 72%, #5f816b))",
8052
+ accentBorder: "color-mix(in srgb, var(--orion-cms-tone-3, color-mix(in srgb, var(--orion-cms-accent, var(--orion-admin-accent)) 72%, #5f816b)) 24%, transparent)",
8053
+ accentMist: "color-mix(in srgb, var(--orion-cms-tone-3, color-mix(in srgb, var(--orion-cms-accent, var(--orion-admin-accent)) 72%, #5f816b)) 12%, transparent)",
8054
+ accentSoft: "color-mix(in srgb, var(--orion-cms-tone-3, color-mix(in srgb, var(--orion-cms-accent, var(--orion-admin-accent)) 72%, #5f816b)) 8%, transparent)"
8055
+ },
8056
+ {
8057
+ accent: "var(--orion-cms-tone-4, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 72%, #7a652e))",
8058
+ accentBorder: "color-mix(in srgb, var(--orion-cms-tone-4, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 72%, #7a652e)) 24%, transparent)",
8059
+ accentMist: "color-mix(in srgb, var(--orion-cms-tone-4, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 72%, #7a652e)) 13%, transparent)",
8060
+ accentSoft: "color-mix(in srgb, var(--orion-cms-tone-4, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 72%, #7a652e)) 8%, transparent)"
8061
+ },
8062
+ {
8063
+ accent: "var(--orion-cms-tone-5, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 68%, #8d4a40))",
8064
+ accentBorder: "color-mix(in srgb, var(--orion-cms-tone-5, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 68%, #8d4a40)) 24%, transparent)",
8065
+ accentMist: "color-mix(in srgb, var(--orion-cms-tone-5, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 68%, #8d4a40)) 13%, transparent)",
8066
+ accentSoft: "color-mix(in srgb, var(--orion-cms-tone-5, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 68%, #8d4a40)) 8%, transparent)"
8067
+ }
8068
+ ];
8069
+ var FORM_TONE_OVERRIDES2 = {
8070
+ "basket-request": FORM_TONES2[1],
8071
+ contact: FORM_TONES2[2],
8072
+ "vendor-inquiry": FORM_TONES2[0]
8073
+ };
8074
+ var IDENTITY_KEYS2 = /* @__PURE__ */ new Set(["contactEmail", "email", "firstName", "lastName", "name"]);
8075
+ var RESPONSE_FIELD_PREVIEW_LIMIT2 = 3;
8076
+ var getPropString14 = (props, key, fallback) => {
8077
+ if (!props || typeof props !== "object") return fallback;
8078
+ const direct = props[key];
8079
+ if (typeof direct === "string" && direct.length > 0) return direct;
8080
+ const clientProps = props.clientProps;
8081
+ if (clientProps && typeof clientProps === "object") {
8082
+ const nested = clientProps[key];
8083
+ if (typeof nested === "string" && nested.length > 0) return nested;
8084
+ }
8085
+ return fallback;
8086
+ };
8087
+ var getParam3 = (params, key) => {
8088
+ if (!params || typeof params !== "object") return null;
8089
+ const value = params[key];
8090
+ if (typeof value === "string") return value;
8091
+ if (Array.isArray(value) && typeof value[0] === "string") return value[0];
8092
+ return null;
8093
+ };
8094
+ var getIDFromPathname = (pathname, marker) => {
8095
+ const markerIndex = pathname.indexOf(marker);
8096
+ if (markerIndex < 0) return null;
8097
+ const id = pathname.slice(markerIndex + marker.length).split("/")[0];
8098
+ return id ? decodeURIComponent(id) : null;
8099
+ };
8100
+ var formatDate2 = (value) => {
8101
+ if (typeof value !== "string" || value.length === 0) return "Unknown date";
8102
+ const date = new Date(value);
8103
+ if (Number.isNaN(date.getTime())) return value;
8104
+ return date.toLocaleString();
8105
+ };
8106
+ var formatFileSize4 = (value) => {
8107
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return null;
8108
+ if (value < 1024) return `${value} B`;
8109
+ if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)} KB`;
8110
+ return `${(value / (1024 * 1024)).toFixed(1)} MB`;
8111
+ };
8112
+ var getFieldCount2 = (form) => Array.isArray(form.steps) ? form.steps.reduce((count, step) => {
8113
+ if (!step || typeof step !== "object") return count;
8114
+ const fields = step.fields;
8115
+ return count + (Array.isArray(fields) ? fields.length : 0);
8116
+ }, 0) : 0;
8117
+ var getFormID3 = (value) => {
8118
+ if (typeof value === "string" || typeof value === "number") return String(value);
8119
+ if (value && typeof value === "object") {
8120
+ const id = value.id;
8121
+ if (typeof id === "string" || typeof id === "number") return String(id);
8122
+ }
8123
+ return "";
8124
+ };
8125
+ var getUploads2 = (value) => Array.isArray(value) ? value.map((entry) => {
8126
+ if (typeof entry === "string" || typeof entry === "number") {
8127
+ return { id: entry };
8128
+ }
8129
+ return entry && typeof entry === "object" ? entry : null;
8130
+ }).filter((entry) => Boolean(entry)) : [];
8131
+ var getNameAndEmail2 = (data) => {
8132
+ if (!data || typeof data !== "object") return {};
8133
+ const record = data;
8134
+ const email = typeof record.email === "string" ? record.email : typeof record.contactEmail === "string" ? record.contactEmail : void 0;
8135
+ const firstName = typeof record.firstName === "string" ? record.firstName : void 0;
8136
+ const lastName = typeof record.lastName === "string" ? record.lastName : void 0;
8137
+ const fallbackName = typeof record.name === "string" ? record.name : void 0;
8138
+ const joinedName = [firstName, lastName].filter(Boolean).join(" ").trim();
8139
+ return {
8140
+ ...email ? { email } : {},
8141
+ ...joinedName ? { name: joinedName } : fallbackName ? { name: fallbackName } : {}
8142
+ };
8143
+ };
8144
+ var humanizeKey2 = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim().replace(/^./, (char) => char.toUpperCase());
8145
+ var buildFieldLabelMap2 = (form) => {
8146
+ const labels = /* @__PURE__ */ new Map();
8147
+ for (const step of Array.isArray(form.steps) ? form.steps : []) {
8148
+ const fields = step && typeof step === "object" ? step.fields : null;
8149
+ for (const field of Array.isArray(fields) ? fields : []) {
8150
+ const name = field && typeof field === "object" && typeof field.name === "string" ? field.name.trim() : "";
8151
+ const label = field && typeof field === "object" && typeof field.label === "string" ? field.label.trim() : "";
8152
+ if (name) {
8153
+ labels.set(name, label || humanizeKey2(name));
8154
+ }
8155
+ }
8156
+ }
8157
+ return labels;
8158
+ };
8159
+ var truncateText2 = (value, maxLength = 64) => {
8160
+ const normalized = value.replace(/\s+/g, " ").trim();
8161
+ if (normalized.length <= maxLength) return normalized;
8162
+ return `${normalized.slice(0, maxLength - 1).trimEnd()}...`;
8163
+ };
8164
+ var formatPreviewValue2 = (value) => {
8165
+ if (value === null || value === void 0) return null;
8166
+ if (typeof value === "boolean") return value ? "Yes" : "No";
8167
+ if (typeof value === "number") return String(value);
8168
+ if (typeof value === "string") {
8169
+ const trimmed = value.trim();
8170
+ return trimmed ? truncateText2(trimmed, 72) : null;
8171
+ }
8172
+ if (Array.isArray(value)) {
8173
+ const joined = value.map((entry) => String(entry).trim()).filter(Boolean).join(", ");
8174
+ return joined ? truncateText2(joined, 72) : null;
8175
+ }
8176
+ if (typeof value === "object") {
8177
+ return truncateText2(JSON.stringify(value), 72);
8178
+ }
8179
+ return truncateText2(String(value), 72);
8180
+ };
8181
+ var getPreviewFields2 = (data, fieldLabels) => {
8182
+ if (!data || typeof data !== "object") return [];
8183
+ return Object.entries(data).filter(([key]) => !IDENTITY_KEYS2.has(key)).map(([key, value]) => {
8184
+ const formatted = formatPreviewValue2(value);
8185
+ if (!formatted) return null;
8186
+ return {
8187
+ label: fieldLabels.get(key) || humanizeKey2(key),
8188
+ value: formatted
8189
+ };
8190
+ }).filter((entry) => Boolean(entry)).slice(0, RESPONSE_FIELD_PREVIEW_LIMIT2);
8191
+ };
8192
+ var getInitials3 = (...values) => {
8193
+ const source = values.find((value) => typeof value === "string" && value.trim().length > 0);
8194
+ if (!source) return "FM";
8195
+ const cleaned = source.replace(/[^a-z0-9]+/gi, " ").trim();
8196
+ if (!cleaned) return "FM";
8197
+ const parts = cleaned.split(/\s+/).filter(Boolean);
8198
+ if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
8199
+ return `${parts[0][0] || ""}${parts[1][0] || ""}`.toUpperCase();
8200
+ };
8201
+ var getHash2 = (value) => {
8202
+ let hash = 0;
8203
+ for (let index = 0; index < value.length; index += 1) {
8204
+ hash = hash * 31 + value.charCodeAt(index) >>> 0;
8205
+ }
8206
+ return hash;
8207
+ };
8208
+ var normalizeToneKey2 = (value) => value?.trim().toLowerCase() || "";
8209
+ var getFormTone2 = (slug, fallbackSeed) => {
8210
+ const normalizedSlug = normalizeToneKey2(slug);
8211
+ if (normalizedSlug && FORM_TONE_OVERRIDES2[normalizedSlug]) {
8212
+ return FORM_TONE_OVERRIDES2[normalizedSlug];
8213
+ }
8214
+ const normalizedSeed = normalizeToneKey2(fallbackSeed);
8215
+ if (normalizedSeed && FORM_TONE_OVERRIDES2[normalizedSeed]) {
8216
+ return FORM_TONE_OVERRIDES2[normalizedSeed];
8217
+ }
8218
+ return FORM_TONES2[getHash2(slug || fallbackSeed) % FORM_TONES2.length];
8219
+ };
8220
+ var getFormToneStyle2 = (slug, fallbackSeed) => {
8221
+ const tone = getFormTone2(slug, fallbackSeed);
8222
+ return {
8223
+ ["--form-accent"]: tone.accent,
8224
+ ["--form-accent-border"]: tone.accentBorder,
8225
+ ["--form-accent-mist"]: tone.accentMist,
8226
+ ["--form-accent-soft"]: tone.accentSoft
8227
+ };
8228
+ };
8229
+ var getFormTitle2 = (value) => {
8230
+ if (value && typeof value === "object" && typeof value.title === "string") {
8231
+ const title = value.title.trim();
8232
+ if (title.length > 0) return title;
8233
+ }
8234
+ if (typeof value === "string" && value.trim().length > 0) {
8235
+ return value;
8236
+ }
8237
+ return "Untitled Form";
8238
+ };
8239
+
8240
+ // src/admin/components/studio/AdminStudioFormDetailView.tsx
8035
8241
  var import_jsx_runtime41 = require("react/jsx-runtime");
8036
- var userRoles = ["admin", "developer", "editor", "client"];
8037
- var hasAdminAccess4 = (user) => {
8038
- if (!user || typeof user !== "object") return false;
8039
- const role = user.role;
8040
- return typeof role === "string" && (role === "admin" || role === "developer");
8242
+ var getNonEmptyText = (value, fallback = "") => typeof value === "string" && value.trim().length > 0 ? value : fallback;
8243
+ var formatStepsText = (value) => {
8244
+ if (!Array.isArray(value)) {
8245
+ return "[]";
8246
+ }
8247
+ try {
8248
+ return JSON.stringify(value, null, 2);
8249
+ } catch {
8250
+ return "[]";
8251
+ }
8041
8252
  };
8042
- var normalizeRole = (value) => userRoles.includes(value) ? value : "editor";
8043
- function AdminStudioToolsView(props) {
8044
- const { user } = (0, import_ui12.useAuth)();
8253
+ var toEditorState = (doc) => {
8254
+ const emails = doc.emails && typeof doc.emails === "object" ? doc.emails : null;
8255
+ const adminRecipients = Array.isArray(emails?.adminRecipients) ? emails?.adminRecipients.map(
8256
+ (entry) => entry && typeof entry === "object" && typeof entry.email === "string" ? entry.email.trim() : ""
8257
+ ).filter(Boolean) : [];
8258
+ return {
8259
+ adminRecipientsText: adminRecipients.join("\n"),
8260
+ adminSubject: getNonEmptyText(emails?.adminSubject),
8261
+ confirmationHeading: getNonEmptyText(emails?.confirmationHeading),
8262
+ confirmationMessage: getNonEmptyText(emails?.confirmationMessage),
8263
+ confirmationSubject: getNonEmptyText(emails?.confirmationSubject),
8264
+ sendAdmin: emails?.sendAdmin !== false,
8265
+ sendConfirmation: emails?.sendConfirmation !== false,
8266
+ slug: getNonEmptyText(doc.slug),
8267
+ stepsText: formatStepsText(doc.steps),
8268
+ submitLabel: getNonEmptyText(doc.submitLabel, "Submit"),
8269
+ successMessage: getNonEmptyText(doc.successMessage),
8270
+ title: getNonEmptyText(doc.title, "Untitled Form")
8271
+ };
8272
+ };
8273
+ var checkboxLabelStyle = {
8274
+ alignItems: "center",
8275
+ display: "flex",
8276
+ gap: "0.6rem"
8277
+ };
8278
+ var codeStyle = {
8279
+ background: "color-mix(in srgb, var(--orion-admin-card-bg) 82%, black)",
8280
+ border: "1px solid var(--orion-admin-card-border)",
8281
+ borderRadius: "var(--orion-admin-radius-sm)",
8282
+ color: "var(--orion-admin-text)",
8283
+ fontFamily: "ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, monospace",
8284
+ fontSize: "0.86rem",
8285
+ lineHeight: 1.55,
8286
+ margin: 0,
8287
+ maxHeight: "28rem",
8288
+ overflow: "auto",
8289
+ padding: "0.9rem",
8290
+ whiteSpace: "pre-wrap"
8291
+ };
8292
+ var sectionGridStyle = {
8293
+ display: "grid",
8294
+ gap: "1rem",
8295
+ gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
8296
+ };
8297
+ function getFormIDFromPathname(pathname) {
8298
+ const marker = "/forms/";
8299
+ const raw = getIDFromPathname(pathname, marker);
8300
+ if (!raw || raw === "submissions" || raw === "uploads") {
8301
+ return null;
8302
+ }
8303
+ return raw;
8304
+ }
8305
+ function AdminStudioFormDetailView(props) {
8306
+ const formsCollectionSlug = getPropString14(props, "formsCollectionSlug", "forms");
8307
+ const formSubmissionsCollectionSlug = getPropString14(
8308
+ props,
8309
+ "formSubmissionsCollectionSlug",
8310
+ "form-submissions"
8311
+ );
8045
8312
  const adminBasePath = useAdminBasePath();
8046
- const [docs, setDocs] = (0, import_react32.useState)([]);
8313
+ const formsPath = resolveAdminPath(adminBasePath, "/forms");
8314
+ const formIDFromParams = (0, import_react32.useMemo)(() => getParam3(props.params, "id"), [props.params]);
8315
+ const [formID, setFormID] = (0, import_react32.useState)(formIDFromParams);
8316
+ const [didResolvePathFallback, setDidResolvePathFallback] = (0, import_react32.useState)(false);
8317
+ const [doc, setDoc] = (0, import_react32.useState)(null);
8318
+ const [submissions, setSubmissions] = (0, import_react32.useState)([]);
8319
+ const [editorState, setEditorState] = (0, import_react32.useState)(null);
8047
8320
  const [loading, setLoading] = (0, import_react32.useState)(true);
8048
8321
  const [error, setError] = (0, import_react32.useState)(null);
8322
+ const [saving, setSaving] = (0, import_react32.useState)(false);
8049
8323
  const [savedMessage, setSavedMessage] = (0, import_react32.useState)(null);
8050
- const [createSubmitting, setCreateSubmitting] = (0, import_react32.useState)(false);
8051
- const [updatingUserID, setUpdatingUserID] = (0, import_react32.useState)(null);
8052
- if (!hasAdminAccess4(user)) {
8053
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8054
- AdminPage,
8055
- {
8056
- breadcrumbs: [
8057
- { label: "Dashboard", href: adminBasePath },
8058
- { label: "Admin Tools" }
8059
- ],
8060
- description: "You do not have access to this section.",
8061
- title: "Admin Tools",
8062
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
8063
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Access denied" }),
8064
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "This section is restricted to administrator and developer accounts." })
8065
- ] })
8066
- }
8067
- ) });
8068
- }
8069
- const loadUsers = async () => {
8324
+ (0, import_react32.useEffect)(() => {
8325
+ if (formIDFromParams) {
8326
+ setFormID(formIDFromParams);
8327
+ setDidResolvePathFallback(true);
8328
+ return;
8329
+ }
8330
+ if (typeof window !== "undefined") {
8331
+ setFormID(getFormIDFromPathname(window.location.pathname));
8332
+ }
8333
+ setDidResolvePathFallback(true);
8334
+ }, [formIDFromParams]);
8335
+ const loadDoc = async (id) => {
8070
8336
  setLoading(true);
8071
8337
  setError(null);
8072
8338
  try {
8073
- const params = new URLSearchParams({
8074
- depth: "0",
8075
- draft: "true",
8076
- limit: "200",
8077
- sort: "email"
8078
- });
8079
- const response = await fetch(`/api/users?${params.toString()}`, {
8080
- credentials: "include"
8339
+ const submissionsParams = new URLSearchParams({
8340
+ depth: "1",
8341
+ limit: "25",
8342
+ sort: "-submittedAt"
8081
8343
  });
8082
- if (!response.ok) {
8083
- throw new Error(`Failed to load users (${response.status}).`);
8344
+ submissionsParams.set("where[form][equals]", id);
8345
+ const [formResponse, submissionsResponse] = await Promise.all([
8346
+ fetch(`/api/${formsCollectionSlug}/${encodeURIComponent(id)}?depth=0&draft=true`, {
8347
+ credentials: "include"
8348
+ }),
8349
+ fetch(`/api/${formSubmissionsCollectionSlug}?${submissionsParams.toString()}`, {
8350
+ credentials: "include"
8351
+ })
8352
+ ]);
8353
+ if (!formResponse.ok) {
8354
+ throw new Error(`Failed to load form (${formResponse.status}).`);
8084
8355
  }
8085
- const payload = await response.json();
8086
- setDocs(Array.isArray(payload.docs) ? payload.docs : []);
8356
+ if (!submissionsResponse.ok) {
8357
+ throw new Error(`Failed to load submissions (${submissionsResponse.status}).`);
8358
+ }
8359
+ const nextDoc = await formResponse.json();
8360
+ const submissionsPayload = await submissionsResponse.json();
8361
+ const nextSubmissions = Array.isArray(submissionsPayload.docs) ? submissionsPayload.docs : [];
8362
+ setDoc(nextDoc);
8363
+ setEditorState(toEditorState(nextDoc));
8364
+ setSubmissions(nextSubmissions);
8087
8365
  } catch (loadError) {
8088
- setError(loadError instanceof Error ? loadError.message : "Failed to load users.");
8366
+ setError(loadError instanceof Error ? loadError.message : "Failed to load form.");
8367
+ setDoc(null);
8368
+ setEditorState(null);
8369
+ setSubmissions([]);
8089
8370
  } finally {
8090
8371
  setLoading(false);
8091
8372
  }
8092
8373
  };
8093
8374
  (0, import_react32.useEffect)(() => {
8094
- void loadUsers();
8095
- }, []);
8096
- const createUser = async (event) => {
8375
+ if (!formID) {
8376
+ return;
8377
+ }
8378
+ void loadDoc(formID);
8379
+ }, [formID, formsCollectionSlug, formSubmissionsCollectionSlug]);
8380
+ const save = async (event) => {
8097
8381
  event.preventDefault();
8098
- const form = event.currentTarget;
8099
- setCreateSubmitting(true);
8382
+ if (!formID || !editorState) {
8383
+ return;
8384
+ }
8385
+ setSaving(true);
8100
8386
  setError(null);
8101
8387
  setSavedMessage(null);
8102
8388
  try {
8103
- const formData = new FormData(form);
8104
- const email = String(formData.get("email") || "").trim();
8105
- const password = String(formData.get("password") || "");
8106
- const fullName = String(formData.get("fullName") || "").trim();
8107
- const role = normalizeRole(String(formData.get("role") || "editor").trim());
8108
- if (!email || !password) {
8109
- throw new Error("Email and password are required.");
8389
+ const parsedSteps = JSON.parse(editorState.stepsText);
8390
+ if (!Array.isArray(parsedSteps)) {
8391
+ throw new Error("Structure JSON must be an array of steps.");
8110
8392
  }
8111
- const response = await fetch("/api/users", {
8112
- body: JSON.stringify({
8113
- email,
8114
- fullName,
8115
- password,
8116
- role
8117
- }),
8118
- credentials: "include",
8119
- headers: {
8393
+ const payload = {
8394
+ emails: {
8395
+ adminRecipients: editorState.adminRecipientsText.split("\n").map((value) => value.trim()).filter(Boolean).map((email) => ({ email })),
8396
+ adminSubject: editorState.adminSubject.trim(),
8397
+ confirmationHeading: editorState.confirmationHeading.trim(),
8398
+ confirmationMessage: editorState.confirmationMessage,
8399
+ confirmationSubject: editorState.confirmationSubject.trim(),
8400
+ sendAdmin: editorState.sendAdmin,
8401
+ sendConfirmation: editorState.sendConfirmation
8402
+ },
8403
+ slug: editorState.slug.trim(),
8404
+ steps: parsedSteps,
8405
+ submitLabel: editorState.submitLabel.trim(),
8406
+ successMessage: editorState.successMessage,
8407
+ title: editorState.title.trim()
8408
+ };
8409
+ const response = await fetch(`/api/${formsCollectionSlug}/${encodeURIComponent(formID)}`, {
8410
+ body: JSON.stringify(payload),
8411
+ credentials: "include",
8412
+ headers: {
8413
+ "Content-Type": "application/json"
8414
+ },
8415
+ method: "PATCH"
8416
+ });
8417
+ if (!response.ok) {
8418
+ throw new Error(`Failed to save form (${response.status}).`);
8419
+ }
8420
+ const nextDoc = await response.json();
8421
+ setDoc(nextDoc);
8422
+ setEditorState(toEditorState(nextDoc));
8423
+ setSavedMessage("Saved.");
8424
+ } catch (saveError) {
8425
+ setError(saveError instanceof Error ? saveError.message : "Failed to save form.");
8426
+ } finally {
8427
+ setSaving(false);
8428
+ }
8429
+ };
8430
+ if (!formID && !didResolvePathFallback) {
8431
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8432
+ AdminPage,
8433
+ {
8434
+ breadcrumbs: [
8435
+ { label: "Dashboard", href: adminBasePath },
8436
+ { label: "Forms", href: formsPath },
8437
+ { label: "Form" }
8438
+ ],
8439
+ description: "Loading form workspace...",
8440
+ title: "Form",
8441
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_jsx_runtime41.Fragment, {})
8442
+ }
8443
+ ) });
8444
+ }
8445
+ const title = doc && typeof doc.title === "string" && doc.title.trim().length > 0 ? doc.title : "Form";
8446
+ const slug = doc && typeof doc.slug === "string" ? doc.slug : "";
8447
+ const toneStyle = getFormToneStyle2(slug, title || formID || "form");
8448
+ const fieldLabels = doc ? buildFieldLabelMap2(doc) : /* @__PURE__ */ new Map();
8449
+ const latestSubmission = submissions[0];
8450
+ const stepCount = doc && Array.isArray(doc.steps) ? doc.steps.length : 0;
8451
+ const fieldCount = doc ? getFieldCount2(doc) : 0;
8452
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
8453
+ AdminPage,
8454
+ {
8455
+ breadcrumbs: [
8456
+ { label: "Dashboard", href: adminBasePath },
8457
+ { label: "Forms", href: formsPath },
8458
+ { label: title }
8459
+ ],
8460
+ description: "Manage form content and review recent responses without leaving Studio.",
8461
+ title: "Form",
8462
+ children: [
8463
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
8464
+ error ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-error", children: error }) : null,
8465
+ savedMessage ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-success", children: savedMessage }) : null,
8466
+ !loading && !error && doc && editorState && formID ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
8467
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-forms-summary-grid", children: [
8468
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-overview-stat", children: [
8469
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Workflow steps" }),
8470
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: stepCount }),
8471
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { children: "Configured stages in the public form flow." })
8472
+ ] }),
8473
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-overview-stat", children: [
8474
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Fields" }),
8475
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: fieldCount }),
8476
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { children: "Total visible and conditional fields across every step." })
8477
+ ] }),
8478
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-overview-stat", children: [
8479
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Recent submissions" }),
8480
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: submissions.length }),
8481
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { children: latestSubmission ? `Latest response ${formatDate2(latestSubmission.submittedAt)}` : "No responses have been recorded yet." })
8482
+ ] })
8483
+ ] }),
8484
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("section", { className: "orion-admin-form-board", style: toneStyle, children: [
8485
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-header", children: [
8486
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-heading", children: [
8487
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-kicker-row", children: [
8488
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-board-kicker", children: slug || "No slug set" }),
8489
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-board-meta", children: doc.updatedAt ? `Updated ${formatDate2(doc.updatedAt)}` : "Update time unavailable" })
8490
+ ] }),
8491
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-title-row", children: [
8492
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-form-board-mark", children: getInitials3(title, slug) }),
8493
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-copy", children: [
8494
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("h2", { className: "orion-admin-form-board-title", children: title }),
8495
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "orion-admin-form-board-subtitle", children: editorState.successMessage.trim().length > 0 ? editorState.successMessage : "No success message set." })
8496
+ ] })
8497
+ ] })
8498
+ ] }),
8499
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-form-board-actions", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-count", children: [
8500
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-board-count-value", children: submissions.length }),
8501
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-form-board-count-label", children: [
8502
+ "response",
8503
+ submissions.length === 1 ? "" : "s"
8504
+ ] })
8505
+ ] }) })
8506
+ ] }),
8507
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-metrics", children: [
8508
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-form-metric", children: [
8509
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-metric-label", children: "Submit button" }),
8510
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { className: "orion-admin-form-metric-value is-copy", children: editorState.submitLabel || "Submit" })
8511
+ ] }),
8512
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-form-metric", children: [
8513
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-metric-label", children: "Admin notifications" }),
8514
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { className: "orion-admin-form-metric-value", children: editorState.sendAdmin ? "On" : "Off" })
8515
+ ] }),
8516
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-form-metric", children: [
8517
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-metric-label", children: "Confirmation email" }),
8518
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { className: "orion-admin-form-metric-value", children: editorState.sendConfirmation ? "On" : "Off" })
8519
+ ] }),
8520
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-form-metric", children: [
8521
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-metric-label", children: "Latest response" }),
8522
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { className: "orion-admin-form-metric-value is-copy", children: latestSubmission ? formatDate2(latestSubmission.submittedAt) : "No activity yet" })
8523
+ ] })
8524
+ ] })
8525
+ ] }),
8526
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: sectionGridStyle, children: [
8527
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
8528
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
8529
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Step preview" }),
8530
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Review the configured workflow structure before editing the JSON source." }),
8531
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: Array.isArray(doc.steps) && doc.steps.length > 0 ? doc.steps.map((step, stepIndex) => {
8532
+ const record = step && typeof step === "object" && !Array.isArray(step) ? step : null;
8533
+ const fields = Array.isArray(record?.fields) ? record.fields : [];
8534
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form", children: [
8535
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
8536
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("strong", { children: [
8537
+ "Step ",
8538
+ stepIndex + 1,
8539
+ ": ",
8540
+ getNonEmptyText(record?.title, "Untitled Step")
8541
+ ] }),
8542
+ getNonEmptyText(record?.subtitle) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", style: { marginTop: "0.25rem" }, children: getNonEmptyText(record?.subtitle) }) : null
8543
+ ] }),
8544
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-inline-actions", children: [
8545
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-pill", children: [
8546
+ fields.length,
8547
+ " field",
8548
+ fields.length === 1 ? "" : "s"
8549
+ ] }),
8550
+ record?.allowSkip === true ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-pill", children: "Can skip" }) : null,
8551
+ getNonEmptyText(record?.nextLabel) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-pill", children: [
8552
+ "Next: ",
8553
+ getNonEmptyText(record?.nextLabel)
8554
+ ] }) : null
8555
+ ] }),
8556
+ fields.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list", children: fields.map((field, fieldIndex) => {
8557
+ const fieldRecord = field && typeof field === "object" && !Array.isArray(field) ? field : null;
8558
+ const type = getNonEmptyText(fieldRecord?.type, "text");
8559
+ const label = getNonEmptyText(
8560
+ fieldRecord?.label,
8561
+ getNonEmptyText(fieldRecord?.name, `Field ${fieldIndex + 1}`)
8562
+ );
8563
+ const helpText = getNonEmptyText(fieldRecord?.helpText);
8564
+ const condition = fieldRecord?.condition && typeof fieldRecord.condition === "object" && !Array.isArray(fieldRecord.condition) ? fieldRecord.condition : null;
8565
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-item", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
8566
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: label }),
8567
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-list-meta", children: [
8568
+ type,
8569
+ fieldRecord?.required === true ? " \xB7 required" : "",
8570
+ condition?.field && condition?.equals ? ` \xB7 when ${String(condition.field)} = ${String(condition.equals)}` : ""
8571
+ ] }),
8572
+ helpText ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8573
+ "div",
8574
+ {
8575
+ className: "orion-admin-list-meta",
8576
+ style: { marginTop: "0.25rem" },
8577
+ children: helpText
8578
+ }
8579
+ ) : null
8580
+ ] }) }, `field-${fieldIndex}`);
8581
+ }) }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: "This step has no fields." })
8582
+ ] }, `step-${stepIndex}`);
8583
+ }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-empty-state", children: [
8584
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "No steps configured" }),
8585
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Add at least one step in the JSON editor to publish this form." })
8586
+ ] }) })
8587
+ ] }),
8588
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
8589
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Recent submissions" }),
8590
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Jump from the form definition into the latest responses." }),
8591
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: submissions.length > 0 ? submissions.map((submission) => {
8592
+ const submissionID = typeof submission.id === "string" || typeof submission.id === "number" ? String(submission.id) : "";
8593
+ if (!submissionID) return null;
8594
+ const identity = getNameAndEmail2(submission.data);
8595
+ const previewFields = getPreviewFields2(submission.data, fieldLabels);
8596
+ const formSubmissionPath = resolveAdminPath(
8597
+ adminBasePath,
8598
+ `/forms/submissions/${submissionID}`
8599
+ );
8600
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_link4.default, { className: "orion-admin-list-item", href: formSubmissionPath, children: [
8601
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
8602
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: identity.name || identity.email || "Submission" }),
8603
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: formatDate2(submission.submittedAt) }),
8604
+ previewFields.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", style: { marginTop: "0.3rem" }, children: previewFields.map((field) => `${field.label}: ${field.value}`).join(" \xB7 ") }) : null
8605
+ ] }),
8606
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-action-button orion-admin-action-button--ghost", children: "Open" })
8607
+ ] }, submissionID);
8608
+ }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-empty-state", children: [
8609
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "No responses yet" }),
8610
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "This view will populate as soon as the form starts receiving traffic." })
8611
+ ] }) })
8612
+ ] })
8613
+ ] }),
8614
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("form", { className: "orion-admin-form", onSubmit: save, children: [
8615
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Form settings" }),
8616
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8617
+ "Title",
8618
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8619
+ "input",
8620
+ {
8621
+ onChange: (event) => setEditorState(
8622
+ (current) => current ? { ...current, title: event.target.value } : current
8623
+ ),
8624
+ required: true,
8625
+ type: "text",
8626
+ value: editorState.title
8627
+ }
8628
+ )
8629
+ ] }),
8630
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8631
+ "Slug",
8632
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8633
+ "input",
8634
+ {
8635
+ onChange: (event) => setEditorState(
8636
+ (current) => current ? { ...current, slug: event.target.value } : current
8637
+ ),
8638
+ required: true,
8639
+ type: "text",
8640
+ value: editorState.slug
8641
+ }
8642
+ )
8643
+ ] }),
8644
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8645
+ "Submit button",
8646
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8647
+ "input",
8648
+ {
8649
+ onChange: (event) => setEditorState(
8650
+ (current) => current ? { ...current, submitLabel: event.target.value } : current
8651
+ ),
8652
+ type: "text",
8653
+ value: editorState.submitLabel
8654
+ }
8655
+ )
8656
+ ] }),
8657
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8658
+ "Success message",
8659
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8660
+ "textarea",
8661
+ {
8662
+ onChange: (event) => setEditorState(
8663
+ (current) => current ? { ...current, successMessage: event.target.value } : current
8664
+ ),
8665
+ rows: 4,
8666
+ value: editorState.successMessage
8667
+ }
8668
+ )
8669
+ ] }),
8670
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
8671
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Email behavior" }),
8672
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "0.9rem" }, children: [
8673
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { style: checkboxLabelStyle, children: [
8674
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8675
+ "input",
8676
+ {
8677
+ checked: editorState.sendAdmin,
8678
+ onChange: (event) => setEditorState(
8679
+ (current) => current ? { ...current, sendAdmin: event.target.checked } : current
8680
+ ),
8681
+ type: "checkbox"
8682
+ }
8683
+ ),
8684
+ "Send admin notifications"
8685
+ ] }),
8686
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8687
+ "Admin recipients",
8688
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8689
+ "textarea",
8690
+ {
8691
+ onChange: (event) => setEditorState(
8692
+ (current) => current ? { ...current, adminRecipientsText: event.target.value } : current
8693
+ ),
8694
+ placeholder: "one@email.com\ntwo@email.com",
8695
+ rows: 4,
8696
+ value: editorState.adminRecipientsText
8697
+ }
8698
+ )
8699
+ ] }),
8700
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8701
+ "Admin subject",
8702
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8703
+ "input",
8704
+ {
8705
+ onChange: (event) => setEditorState(
8706
+ (current) => current ? { ...current, adminSubject: event.target.value } : current
8707
+ ),
8708
+ type: "text",
8709
+ value: editorState.adminSubject
8710
+ }
8711
+ )
8712
+ ] }),
8713
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { style: checkboxLabelStyle, children: [
8714
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8715
+ "input",
8716
+ {
8717
+ checked: editorState.sendConfirmation,
8718
+ onChange: (event) => setEditorState(
8719
+ (current) => current ? { ...current, sendConfirmation: event.target.checked } : current
8720
+ ),
8721
+ type: "checkbox"
8722
+ }
8723
+ ),
8724
+ "Send confirmation email"
8725
+ ] }),
8726
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8727
+ "Confirmation subject",
8728
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8729
+ "input",
8730
+ {
8731
+ onChange: (event) => setEditorState(
8732
+ (current) => current ? { ...current, confirmationSubject: event.target.value } : current
8733
+ ),
8734
+ type: "text",
8735
+ value: editorState.confirmationSubject
8736
+ }
8737
+ )
8738
+ ] }),
8739
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8740
+ "Confirmation heading",
8741
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8742
+ "input",
8743
+ {
8744
+ onChange: (event) => setEditorState(
8745
+ (current) => current ? { ...current, confirmationHeading: event.target.value } : current
8746
+ ),
8747
+ type: "text",
8748
+ value: editorState.confirmationHeading
8749
+ }
8750
+ )
8751
+ ] }),
8752
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8753
+ "Confirmation message",
8754
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8755
+ "textarea",
8756
+ {
8757
+ onChange: (event) => setEditorState(
8758
+ (current) => current ? { ...current, confirmationMessage: event.target.value } : current
8759
+ ),
8760
+ rows: 4,
8761
+ value: editorState.confirmationMessage
8762
+ }
8763
+ )
8764
+ ] })
8765
+ ] })
8766
+ ] }),
8767
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8768
+ "Structure JSON",
8769
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8770
+ "textarea",
8771
+ {
8772
+ onChange: (event) => setEditorState(
8773
+ (current) => current ? { ...current, stepsText: event.target.value } : current
8774
+ ),
8775
+ rows: 18,
8776
+ spellCheck: false,
8777
+ style: {
8778
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
8779
+ minHeight: "24rem"
8780
+ },
8781
+ value: editorState.stepsText
8782
+ }
8783
+ )
8784
+ ] }),
8785
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: "Edit the public workflow as JSON. The saved payload must remain an array of step objects compatible with the form collection schema." }),
8786
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { disabled: saving, type: "submit", children: saving ? "Saving..." : "Save Form" })
8787
+ ] })
8788
+ ] }),
8789
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
8790
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Current structure payload" }),
8791
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Reference snapshot of the form steps that will be written back on save." }),
8792
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("pre", { style: { ...codeStyle, marginTop: "1rem" }, children: editorState.stepsText })
8793
+ ] })
8794
+ ] }) : null
8795
+ ]
8796
+ }
8797
+ ) });
8798
+ }
8799
+
8800
+ // src/admin/components/studio/AdminStudioFormSubmissionView.tsx
8801
+ var import_link5 = __toESM(require("next/link"));
8802
+ var import_react33 = require("react");
8803
+ var import_jsx_runtime42 = require("react/jsx-runtime");
8804
+ var codeStyle2 = {
8805
+ background: "color-mix(in srgb, var(--orion-admin-card-bg) 82%, black)",
8806
+ border: "1px solid var(--orion-admin-card-border)",
8807
+ borderRadius: "var(--orion-admin-radius-sm)",
8808
+ color: "var(--orion-admin-text)",
8809
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
8810
+ fontSize: "0.86rem",
8811
+ lineHeight: 1.55,
8812
+ margin: 0,
8813
+ maxHeight: "28rem",
8814
+ overflow: "auto",
8815
+ padding: "0.9rem",
8816
+ whiteSpace: "pre-wrap"
8817
+ };
8818
+ var sectionGridStyle2 = {
8819
+ display: "grid",
8820
+ gap: "1rem",
8821
+ gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
8822
+ };
8823
+ var renderFieldValue = (value) => {
8824
+ if (value === null || value === void 0) {
8825
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-list-meta", children: "No value" });
8826
+ }
8827
+ if (typeof value === "boolean") {
8828
+ return value ? "Yes" : "No";
8829
+ }
8830
+ if (typeof value === "number") {
8831
+ return String(value);
8832
+ }
8833
+ if (typeof value === "string") {
8834
+ return value.trim().length > 0 ? value : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-list-meta", children: "No value" });
8835
+ }
8836
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("pre", { style: codeStyle2, children: JSON.stringify(value, null, 2) });
8837
+ };
8838
+ function getSubmissionIDFromPathname(pathname) {
8839
+ return getIDFromPathname(pathname, "/forms/submissions/");
8840
+ }
8841
+ function AdminStudioFormSubmissionView(props) {
8842
+ const formsCollectionSlug = getPropString14(props, "formsCollectionSlug", "forms");
8843
+ const formSubmissionsCollectionSlug = getPropString14(
8844
+ props,
8845
+ "formSubmissionsCollectionSlug",
8846
+ "form-submissions"
8847
+ );
8848
+ const adminBasePath = useAdminBasePath();
8849
+ const formsPath = resolveAdminPath(adminBasePath, "/forms");
8850
+ const submissionIDFromParams = (0, import_react33.useMemo)(() => getParam3(props.params, "id"), [props.params]);
8851
+ const [submissionID, setSubmissionID] = (0, import_react33.useState)(submissionIDFromParams);
8852
+ const [didResolvePathFallback, setDidResolvePathFallback] = (0, import_react33.useState)(false);
8853
+ const [doc, setDoc] = (0, import_react33.useState)(null);
8854
+ const [formDoc, setFormDoc] = (0, import_react33.useState)(null);
8855
+ const [loading, setLoading] = (0, import_react33.useState)(true);
8856
+ const [error, setError] = (0, import_react33.useState)(null);
8857
+ const [confirmDelete, setConfirmDelete] = (0, import_react33.useState)(false);
8858
+ const [deleting, setDeleting] = (0, import_react33.useState)(false);
8859
+ (0, import_react33.useEffect)(() => {
8860
+ if (submissionIDFromParams) {
8861
+ setSubmissionID(submissionIDFromParams);
8862
+ setDidResolvePathFallback(true);
8863
+ return;
8864
+ }
8865
+ if (typeof window !== "undefined") {
8866
+ setSubmissionID(getSubmissionIDFromPathname(window.location.pathname));
8867
+ }
8868
+ setDidResolvePathFallback(true);
8869
+ }, [submissionIDFromParams]);
8870
+ const loadDoc = async (id) => {
8871
+ setLoading(true);
8872
+ setError(null);
8873
+ try {
8874
+ const response = await fetch(
8875
+ `/api/${formSubmissionsCollectionSlug}/${encodeURIComponent(id)}?depth=2&draft=true`,
8876
+ {
8877
+ credentials: "include"
8878
+ }
8879
+ );
8880
+ if (!response.ok) {
8881
+ throw new Error(`Failed to load submission (${response.status}).`);
8882
+ }
8883
+ const nextDoc = await response.json();
8884
+ const relatedForm = nextDoc.form && typeof nextDoc.form === "object" && !Array.isArray(nextDoc.form) ? nextDoc.form : null;
8885
+ let nextFormDoc = relatedForm;
8886
+ const relatedFormID2 = getFormID3(nextDoc.form);
8887
+ if (!nextFormDoc && relatedFormID2) {
8888
+ const formResponse = await fetch(
8889
+ `/api/${formsCollectionSlug}/${encodeURIComponent(relatedFormID2)}?depth=0&draft=true`,
8890
+ {
8891
+ credentials: "include"
8892
+ }
8893
+ );
8894
+ if (formResponse.ok) {
8895
+ nextFormDoc = await formResponse.json();
8896
+ }
8897
+ }
8898
+ setDoc(nextDoc);
8899
+ setFormDoc(nextFormDoc);
8900
+ } catch (loadError) {
8901
+ setError(loadError instanceof Error ? loadError.message : "Failed to load submission.");
8902
+ setDoc(null);
8903
+ setFormDoc(null);
8904
+ } finally {
8905
+ setLoading(false);
8906
+ }
8907
+ };
8908
+ (0, import_react33.useEffect)(() => {
8909
+ if (!submissionID) {
8910
+ return;
8911
+ }
8912
+ void loadDoc(submissionID);
8913
+ }, [formsCollectionSlug, formSubmissionsCollectionSlug, submissionID]);
8914
+ const deleteSubmission = async () => {
8915
+ if (!submissionID) {
8916
+ return;
8917
+ }
8918
+ setDeleting(true);
8919
+ setError(null);
8920
+ try {
8921
+ const response = await fetch(`/api/${formSubmissionsCollectionSlug}/${encodeURIComponent(submissionID)}`, {
8922
+ credentials: "include",
8923
+ method: "DELETE"
8924
+ });
8925
+ if (!response.ok) {
8926
+ throw new Error(`Failed to delete submission (${response.status}).`);
8927
+ }
8928
+ const relatedFormID2 = doc ? getFormID3(doc.form) : "";
8929
+ const targetHref = relatedFormID2 ? resolveAdminPath(adminBasePath, `/forms/${relatedFormID2}`) : formsPath;
8930
+ window.location.assign(targetHref);
8931
+ } catch (deleteError) {
8932
+ setError(deleteError instanceof Error ? deleteError.message : "Failed to delete submission.");
8933
+ setDeleting(false);
8934
+ }
8935
+ };
8936
+ if (!submissionID && !didResolvePathFallback) {
8937
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8938
+ AdminPage,
8939
+ {
8940
+ breadcrumbs: [
8941
+ { label: "Dashboard", href: adminBasePath },
8942
+ { label: "Forms", href: formsPath },
8943
+ { label: "Submission" }
8944
+ ],
8945
+ description: "Loading submission workspace...",
8946
+ title: "Submission",
8947
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_jsx_runtime42.Fragment, {})
8948
+ }
8949
+ ) });
8950
+ }
8951
+ const relatedFormID = doc ? getFormID3(doc.form) : "";
8952
+ const formPath = relatedFormID ? resolveAdminPath(adminBasePath, `/forms/${relatedFormID}`) : formsPath;
8953
+ const formTitle = formDoc ? getFormTitle2(formDoc) : getFormTitle2(doc?.formSlug);
8954
+ const uploads = doc ? getUploads2(doc.files) : [];
8955
+ const identity = doc ? getNameAndEmail2(doc.data) : {};
8956
+ const fieldLabels = formDoc ? buildFieldLabelMap2(formDoc) : /* @__PURE__ */ new Map();
8957
+ const previewFields = doc ? getPreviewFields2(doc.data, fieldLabels) : [];
8958
+ const answerEntries = doc && doc.data && typeof doc.data === "object" ? Object.entries(doc.data) : [];
8959
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
8960
+ AdminPage,
8961
+ {
8962
+ breadcrumbs: [
8963
+ { label: "Dashboard", href: adminBasePath },
8964
+ { label: "Forms", href: formsPath },
8965
+ ...relatedFormID ? [{ label: formTitle, href: formPath }] : [{ label: formTitle }],
8966
+ { label: "Submission" }
8967
+ ],
8968
+ description: "Review the submitted answers, related files, and linked form details.",
8969
+ title: "Submission",
8970
+ children: [
8971
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
8972
+ error ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "orion-admin-error", children: error }) : null,
8973
+ !loading && !error && doc && submissionID ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
8974
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-forms-summary-grid", children: [
8975
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("article", { className: "orion-admin-overview-stat", children: [
8976
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Submitted" }),
8977
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: formatDate2(doc.submittedAt) }),
8978
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { children: "Captured timestamp for this response." })
8979
+ ] }),
8980
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("article", { className: "orion-admin-overview-stat", children: [
8981
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Uploads" }),
8982
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: uploads.length }),
8983
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { children: "Files attached by the submitter." })
8984
+ ] }),
8985
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("article", { className: "orion-admin-overview-stat", children: [
8986
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Highlighted answers" }),
8987
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: previewFields.length }),
8988
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { children: "Readable answer previews surfaced from the structured payload." })
8989
+ ] })
8990
+ ] }),
8991
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: sectionGridStyle2, children: [
8992
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
8993
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card", children: [
8994
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "Response details" }),
8995
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "Formatted answers using the current form field labels when available." }),
8996
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: answerEntries.length > 0 ? answerEntries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-form", children: [
8997
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { children: [
8998
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: fieldLabels.get(key) || humanizeKey2(key) }),
8999
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "orion-admin-list-meta", children: key })
9000
+ ] }),
9001
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { children: renderFieldValue(value) })
9002
+ ] }, key)) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-empty-state", children: [
9003
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "No response payload" }),
9004
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "This submission does not contain a structured data object." })
9005
+ ] }) })
9006
+ ] }),
9007
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card", children: [
9008
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "Raw payload" }),
9009
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "Verbatim submission data for troubleshooting or export checks." }),
9010
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("pre", { style: { ...codeStyle2, marginTop: "1rem" }, children: JSON.stringify(doc.data ?? {}, null, 2) })
9011
+ ] })
9012
+ ] }),
9013
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
9014
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card orion-admin-meta-table", children: [
9015
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
9016
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: "Form" }),
9017
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: relatedFormID ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_link5.default, { href: formPath, children: formTitle }) : formTitle })
9018
+ ] }),
9019
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
9020
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: "Primary contact" }),
9021
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: identity.name || identity.email || "Unknown" })
9022
+ ] }),
9023
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
9024
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: "Email" }),
9025
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: identity.email || "Not provided" })
9026
+ ] }),
9027
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
9028
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: "Submission ID" }),
9029
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: submissionID })
9030
+ ] }),
9031
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
9032
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: "Form slug" }),
9033
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: typeof doc.formSlug === "string" && doc.formSlug.trim().length > 0 ? doc.formSlug : "Unavailable" })
9034
+ ] })
9035
+ ] }),
9036
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card", children: [
9037
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "Attached uploads" }),
9038
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "Files linked to this response remain inside the Studio workspace." }),
9039
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { display: "grid", gap: "0.75rem", marginTop: "1rem" }, children: uploads.length > 0 ? uploads.map((upload) => {
9040
+ const uploadID = typeof upload.id === "string" || typeof upload.id === "number" ? String(upload.id) : "";
9041
+ if (!uploadID) return null;
9042
+ const uploadPath = resolveAdminPath(adminBasePath, `/forms/uploads/${uploadID}`);
9043
+ const meta = [formatFileSize4(upload.filesize), typeof upload.mimeType === "string" ? upload.mimeType : null].filter(Boolean).join(" \xB7 ");
9044
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_link5.default, { className: "orion-admin-list-item", href: uploadPath, children: [
9045
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { children: [
9046
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: typeof upload.filename === "string" && upload.filename.trim().length > 0 ? upload.filename : `Upload ${uploadID}` }),
9047
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "orion-admin-list-meta", children: meta || "Open file details" })
9048
+ ] }),
9049
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-action-button orion-admin-action-button--ghost", children: "Open" })
9050
+ ] }, uploadID);
9051
+ }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-empty-state", children: [
9052
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "No files attached" }),
9053
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "This response did not include any uploads." })
9054
+ ] }) })
9055
+ ] }),
9056
+ confirmDelete ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
9057
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { style: { fontWeight: 700, margin: 0 }, children: "Delete this submission?" }),
9058
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "orion-admin-list-meta", style: { margin: 0 }, children: "This action cannot be undone and will remove the stored response." }),
9059
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-inline-actions", children: [
9060
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { disabled: deleting, onClick: deleteSubmission, type: "button", children: deleting ? "Deleting..." : "Yes, Delete" }),
9061
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { onClick: () => setConfirmDelete(false), type: "button", children: "Cancel" })
9062
+ ] })
9063
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
9064
+ "button",
9065
+ {
9066
+ className: "orion-admin-action-button",
9067
+ onClick: () => setConfirmDelete(true),
9068
+ style: { background: "#b42318" },
9069
+ type: "button",
9070
+ children: "Delete Submission"
9071
+ }
9072
+ )
9073
+ ] })
9074
+ ] })
9075
+ ] }) : null
9076
+ ]
9077
+ }
9078
+ ) });
9079
+ }
9080
+
9081
+ // src/admin/components/studio/AdminStudioFormUploadView.tsx
9082
+ var import_react34 = require("react");
9083
+ var import_jsx_runtime43 = require("react/jsx-runtime");
9084
+ var previewStyle = {
9085
+ borderRadius: 14,
9086
+ display: "block",
9087
+ maxHeight: "28rem",
9088
+ objectFit: "contain",
9089
+ width: "100%"
9090
+ };
9091
+ function getUploadIDFromPathname(pathname) {
9092
+ return getIDFromPathname(pathname, "/forms/uploads/");
9093
+ }
9094
+ function AdminStudioFormUploadView(props) {
9095
+ const formUploadsCollectionSlug = getPropString14(props, "formUploadsCollectionSlug", "form-uploads");
9096
+ const adminBasePath = useAdminBasePath();
9097
+ const formsPath = resolveAdminPath(adminBasePath, "/forms");
9098
+ const uploadIDFromParams = (0, import_react34.useMemo)(() => getParam3(props.params, "id"), [props.params]);
9099
+ const [uploadID, setUploadID] = (0, import_react34.useState)(uploadIDFromParams);
9100
+ const [didResolvePathFallback, setDidResolvePathFallback] = (0, import_react34.useState)(false);
9101
+ const [doc, setDoc] = (0, import_react34.useState)(null);
9102
+ const [loading, setLoading] = (0, import_react34.useState)(true);
9103
+ const [error, setError] = (0, import_react34.useState)(null);
9104
+ const [savedMessage, setSavedMessage] = (0, import_react34.useState)(null);
9105
+ const [saving, setSaving] = (0, import_react34.useState)(false);
9106
+ const [confirmDelete, setConfirmDelete] = (0, import_react34.useState)(false);
9107
+ const [deleting, setDeleting] = (0, import_react34.useState)(false);
9108
+ (0, import_react34.useEffect)(() => {
9109
+ if (uploadIDFromParams) {
9110
+ setUploadID(uploadIDFromParams);
9111
+ setDidResolvePathFallback(true);
9112
+ return;
9113
+ }
9114
+ if (typeof window !== "undefined") {
9115
+ setUploadID(getUploadIDFromPathname(window.location.pathname));
9116
+ }
9117
+ setDidResolvePathFallback(true);
9118
+ }, [uploadIDFromParams]);
9119
+ const loadDoc = async (id) => {
9120
+ setLoading(true);
9121
+ setError(null);
9122
+ try {
9123
+ const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(id)}?depth=0&draft=true`, {
9124
+ credentials: "include"
9125
+ });
9126
+ if (!response.ok) {
9127
+ throw new Error(`Failed to load upload (${response.status}).`);
9128
+ }
9129
+ const nextDoc = await response.json();
9130
+ setDoc(nextDoc);
9131
+ } catch (loadError) {
9132
+ setError(loadError instanceof Error ? loadError.message : "Failed to load upload.");
9133
+ setDoc(null);
9134
+ } finally {
9135
+ setLoading(false);
9136
+ }
9137
+ };
9138
+ (0, import_react34.useEffect)(() => {
9139
+ if (!uploadID) {
9140
+ return;
9141
+ }
9142
+ void loadDoc(uploadID);
9143
+ }, [formUploadsCollectionSlug, uploadID]);
9144
+ const save = async (event) => {
9145
+ event.preventDefault();
9146
+ if (!uploadID) {
9147
+ return;
9148
+ }
9149
+ setSaving(true);
9150
+ setError(null);
9151
+ setSavedMessage(null);
9152
+ try {
9153
+ const formData = new FormData(event.currentTarget);
9154
+ const alt = String(formData.get("alt") || "").trim();
9155
+ const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(uploadID)}`, {
9156
+ body: JSON.stringify({ alt }),
9157
+ credentials: "include",
9158
+ headers: {
9159
+ "Content-Type": "application/json"
9160
+ },
9161
+ method: "PATCH"
9162
+ });
9163
+ if (!response.ok) {
9164
+ throw new Error(`Failed to save upload (${response.status}).`);
9165
+ }
9166
+ const nextDoc = await response.json();
9167
+ setDoc(nextDoc);
9168
+ setSavedMessage("Saved.");
9169
+ } catch (saveError) {
9170
+ setError(saveError instanceof Error ? saveError.message : "Failed to save upload.");
9171
+ } finally {
9172
+ setSaving(false);
9173
+ }
9174
+ };
9175
+ const deleteUpload = async () => {
9176
+ if (!uploadID) {
9177
+ return;
9178
+ }
9179
+ setDeleting(true);
9180
+ setError(null);
9181
+ try {
9182
+ const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(uploadID)}`, {
9183
+ credentials: "include",
9184
+ method: "DELETE"
9185
+ });
9186
+ if (!response.ok) {
9187
+ throw new Error(`Failed to delete upload (${response.status}).`);
9188
+ }
9189
+ window.location.assign(formsPath);
9190
+ } catch (deleteError) {
9191
+ setError(deleteError instanceof Error ? deleteError.message : "Failed to delete upload.");
9192
+ setDeleting(false);
9193
+ }
9194
+ };
9195
+ if (!uploadID && !didResolvePathFallback) {
9196
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
9197
+ AdminPage,
9198
+ {
9199
+ breadcrumbs: [
9200
+ { label: "Dashboard", href: adminBasePath },
9201
+ { label: "Forms", href: formsPath },
9202
+ { label: "Upload" }
9203
+ ],
9204
+ description: "Loading upload workspace...",
9205
+ title: "Upload",
9206
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_jsx_runtime43.Fragment, {})
9207
+ }
9208
+ ) });
9209
+ }
9210
+ const filename = doc && typeof doc.filename === "string" && doc.filename.trim().length > 0 ? doc.filename : uploadID ? `Upload ${uploadID}` : "Upload";
9211
+ const mimeType = doc && typeof doc.mimeType === "string" ? doc.mimeType : "";
9212
+ const sourceURL = doc && typeof doc.url === "string" && doc.url.trim().length > 0 ? doc.url : null;
9213
+ const canPreview = Boolean(sourceURL && mimeType.startsWith("image/"));
9214
+ const createdAt = doc?.createdAt ?? doc?.updatedAt;
9215
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
9216
+ AdminPage,
9217
+ {
9218
+ breadcrumbs: [
9219
+ { label: "Dashboard", href: adminBasePath },
9220
+ { label: "Forms", href: formsPath },
9221
+ { label: filename }
9222
+ ],
9223
+ description: "Review file metadata, update alt text, and remove private uploads from Studio.",
9224
+ title: "Upload",
9225
+ children: [
9226
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
9227
+ error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "orion-admin-error", children: error }) : null,
9228
+ savedMessage ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "orion-admin-success", children: savedMessage }) : null,
9229
+ !loading && !error && doc && uploadID ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-grid", style: { alignItems: "start" }, children: [
9230
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { style: { display: "grid", gap: "0.8rem" }, children: [
9231
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "orion-admin-card", children: canPreview && sourceURL ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("img", { alt: filename, src: sourceURL, style: previewStyle }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
9232
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("strong", { children: "No inline preview" }),
9233
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: mimeType ? `Preview unavailable for ${mimeType}.` : "Preview unavailable for this file." })
9234
+ ] }) }),
9235
+ sourceURL ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("a", { className: "orion-admin-action-button", href: sourceURL, rel: "noreferrer", target: "_blank", children: "Open File" }) : null
9236
+ ] }),
9237
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { style: { display: "grid", gap: "0.8rem" }, children: [
9238
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-card orion-admin-meta-table", children: [
9239
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-meta-row", children: [
9240
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-label", children: "Filename" }),
9241
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-value", children: filename })
9242
+ ] }),
9243
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-meta-row", children: [
9244
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-label", children: "File size" }),
9245
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-value", children: formatFileSize4(doc.filesize) || "Unavailable" })
9246
+ ] }),
9247
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-meta-row", children: [
9248
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-label", children: "Type" }),
9249
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-value", children: mimeType || "Unavailable" })
9250
+ ] }),
9251
+ typeof doc.width === "number" && typeof doc.height === "number" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-meta-row", children: [
9252
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-label", children: "Dimensions" }),
9253
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "orion-admin-meta-value", children: [
9254
+ doc.width,
9255
+ " x ",
9256
+ doc.height,
9257
+ "px"
9258
+ ] })
9259
+ ] }) : null,
9260
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-meta-row", children: [
9261
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-label", children: "Uploaded" }),
9262
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-value", children: formatDate2(createdAt) })
9263
+ ] })
9264
+ ] }),
9265
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("form", { className: "orion-admin-form", onSubmit: save, children: [
9266
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("strong", { children: "Asset details" }),
9267
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { children: [
9268
+ "Alt text",
9269
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("input", { defaultValue: typeof doc.alt === "string" ? doc.alt : "", name: "alt", type: "text" })
9270
+ ] }),
9271
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { disabled: saving, type: "submit", children: saving ? "Saving..." : "Save Upload" })
9272
+ ] }),
9273
+ confirmDelete ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
9274
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { style: { fontWeight: 700, margin: 0 }, children: "Delete this upload?" }),
9275
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "orion-admin-list-meta", style: { margin: 0 }, children: "This removes the stored file and any linked submission attachment references." }),
9276
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-inline-actions", children: [
9277
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { disabled: deleting, onClick: deleteUpload, type: "button", children: deleting ? "Deleting..." : "Yes, Delete" }),
9278
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { onClick: () => setConfirmDelete(false), type: "button", children: "Cancel" })
9279
+ ] })
9280
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
9281
+ "button",
9282
+ {
9283
+ className: "orion-admin-action-button",
9284
+ onClick: () => setConfirmDelete(true),
9285
+ style: { background: "#b42318" },
9286
+ type: "button",
9287
+ children: "Delete Upload"
9288
+ }
9289
+ )
9290
+ ] })
9291
+ ] }) : null
9292
+ ]
9293
+ }
9294
+ ) });
9295
+ }
9296
+
9297
+ // src/admin/components/studio/AdminStudioToolsView.tsx
9298
+ var import_react35 = require("react");
9299
+ var import_ui12 = require("@payloadcms/ui");
9300
+ var import_jsx_runtime44 = require("react/jsx-runtime");
9301
+ var userRoles = ["admin", "developer", "editor", "client"];
9302
+ var hasAdminAccess4 = (user) => {
9303
+ if (!user || typeof user !== "object") return false;
9304
+ const role = user.role;
9305
+ return typeof role === "string" && (role === "admin" || role === "developer");
9306
+ };
9307
+ var normalizeRole = (value) => userRoles.includes(value) ? value : "editor";
9308
+ function AdminStudioToolsView(props) {
9309
+ const { user } = (0, import_ui12.useAuth)();
9310
+ const adminBasePath = useAdminBasePath();
9311
+ const [docs, setDocs] = (0, import_react35.useState)([]);
9312
+ const [loading, setLoading] = (0, import_react35.useState)(true);
9313
+ const [error, setError] = (0, import_react35.useState)(null);
9314
+ const [savedMessage, setSavedMessage] = (0, import_react35.useState)(null);
9315
+ const [createSubmitting, setCreateSubmitting] = (0, import_react35.useState)(false);
9316
+ const [updatingUserID, setUpdatingUserID] = (0, import_react35.useState)(null);
9317
+ if (!hasAdminAccess4(user)) {
9318
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
9319
+ AdminPage,
9320
+ {
9321
+ breadcrumbs: [
9322
+ { label: "Dashboard", href: adminBasePath },
9323
+ { label: "Admin Tools" }
9324
+ ],
9325
+ description: "You do not have access to this section.",
9326
+ title: "Admin Tools",
9327
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "orion-admin-card", children: [
9328
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("strong", { children: "Access denied" }),
9329
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { children: "This section is restricted to administrator and developer accounts." })
9330
+ ] })
9331
+ }
9332
+ ) });
9333
+ }
9334
+ const loadUsers = async () => {
9335
+ setLoading(true);
9336
+ setError(null);
9337
+ try {
9338
+ const params = new URLSearchParams({
9339
+ depth: "0",
9340
+ draft: "true",
9341
+ limit: "200",
9342
+ sort: "email"
9343
+ });
9344
+ const response = await fetch(`/api/users?${params.toString()}`, {
9345
+ credentials: "include"
9346
+ });
9347
+ if (!response.ok) {
9348
+ throw new Error(`Failed to load users (${response.status}).`);
9349
+ }
9350
+ const payload = await response.json();
9351
+ setDocs(Array.isArray(payload.docs) ? payload.docs : []);
9352
+ } catch (loadError) {
9353
+ setError(loadError instanceof Error ? loadError.message : "Failed to load users.");
9354
+ } finally {
9355
+ setLoading(false);
9356
+ }
9357
+ };
9358
+ (0, import_react35.useEffect)(() => {
9359
+ void loadUsers();
9360
+ }, []);
9361
+ const createUser = async (event) => {
9362
+ event.preventDefault();
9363
+ const form = event.currentTarget;
9364
+ setCreateSubmitting(true);
9365
+ setError(null);
9366
+ setSavedMessage(null);
9367
+ try {
9368
+ const formData = new FormData(form);
9369
+ const email = String(formData.get("email") || "").trim();
9370
+ const password = String(formData.get("password") || "");
9371
+ const fullName = String(formData.get("fullName") || "").trim();
9372
+ const role = normalizeRole(String(formData.get("role") || "editor").trim());
9373
+ if (!email || !password) {
9374
+ throw new Error("Email and password are required.");
9375
+ }
9376
+ const response = await fetch("/api/users", {
9377
+ body: JSON.stringify({
9378
+ email,
9379
+ fullName,
9380
+ password,
9381
+ role
9382
+ }),
9383
+ credentials: "include",
9384
+ headers: {
8120
9385
  "Content-Type": "application/json"
8121
9386
  },
8122
9387
  method: "POST"
@@ -8162,7 +9427,7 @@ function AdminStudioToolsView(props) {
8162
9427
  setUpdatingUserID(null);
8163
9428
  }
8164
9429
  };
8165
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
9430
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
8166
9431
  AdminPage,
8167
9432
  {
8168
9433
  breadcrumbs: [
@@ -8172,44 +9437,44 @@ function AdminStudioToolsView(props) {
8172
9437
  description: "Manage users and fallback links to Payload native admin.",
8173
9438
  title: "Admin Tools",
8174
9439
  children: [
8175
- error ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-error", style: { marginBottom: "1rem" }, children: error }) : null,
8176
- savedMessage ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-success", style: { marginBottom: "1rem" }, children: savedMessage }) : null,
8177
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("form", { className: "orion-admin-form", onSubmit: createUser, style: { marginBottom: "1rem" }, children: [
8178
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Create User" }),
8179
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9440
+ error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "orion-admin-error", style: { marginBottom: "1rem" }, children: error }) : null,
9441
+ savedMessage ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "orion-admin-success", style: { marginBottom: "1rem" }, children: savedMessage }) : null,
9442
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("form", { className: "orion-admin-form", onSubmit: createUser, style: { marginBottom: "1rem" }, children: [
9443
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("strong", { children: "Create User" }),
9444
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
8180
9445
  "Email",
8181
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("input", { name: "email", required: true, type: "email" })
9446
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { name: "email", required: true, type: "email" })
8182
9447
  ] }),
8183
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9448
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
8184
9449
  "Full Name",
8185
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("input", { name: "fullName", type: "text" })
9450
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { name: "fullName", type: "text" })
8186
9451
  ] }),
8187
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9452
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
8188
9453
  "Password",
8189
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("input", { name: "password", required: true, type: "password" })
9454
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { name: "password", required: true, type: "password" })
8190
9455
  ] }),
8191
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9456
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
8192
9457
  "Role",
8193
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("select", { defaultValue: "editor", name: "role", children: userRoles.map((role) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: role, children: role }, role)) })
9458
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("select", { defaultValue: "editor", name: "role", children: userRoles.map((role) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: role, children: role }, role)) })
8194
9459
  ] }),
8195
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { disabled: createSubmitting, type: "submit", children: createSubmitting ? "Creating..." : "Create User" })
9460
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { disabled: createSubmitting, type: "submit", children: createSubmitting ? "Creating..." : "Create User" })
8196
9461
  ] }),
8197
- loading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
8198
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list", children: docs.map((doc) => {
9462
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
9463
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "orion-admin-list", children: docs.map((doc) => {
8199
9464
  const id = typeof doc.id === "string" || typeof doc.id === "number" ? String(doc.id) : "";
8200
9465
  if (!id) return null;
8201
9466
  const email = typeof doc.email === "string" ? doc.email : `user-${id}`;
8202
9467
  const fullName = typeof doc.fullName === "string" ? doc.fullName : "";
8203
9468
  const currentRole = typeof doc.role === "string" ? normalizeRole(doc.role) : "editor";
8204
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-list-item", children: [
8205
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
8206
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: email }),
8207
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: fullName || "No full name set" })
9469
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "orion-admin-list-item", children: [
9470
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { children: [
9471
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("strong", { children: email }),
9472
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "orion-admin-list-meta", children: fullName || "No full name set" })
8208
9473
  ] }),
8209
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("form", { className: "orion-admin-inline-actions", onSubmit: updateUserRole, children: [
8210
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("input", { name: "id", type: "hidden", value: id }),
8211
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("select", { defaultValue: currentRole, name: "role", children: userRoles.map((role) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: role, children: role }, role)) }),
8212
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { disabled: updatingUserID === id, type: "submit", children: updatingUserID === id ? "Updating..." : "Update" })
9474
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("form", { className: "orion-admin-inline-actions", onSubmit: updateUserRole, children: [
9475
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { name: "id", type: "hidden", value: id }),
9476
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("select", { defaultValue: currentRole, name: "role", children: userRoles.map((role) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: role, children: role }, role)) }),
9477
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { disabled: updatingUserID === id, type: "submit", children: updatingUserID === id ? "Updating..." : "Update" })
8213
9478
  ] })
8214
9479
  ] }, id);
8215
9480
  }) })
@@ -8220,14 +9485,14 @@ function AdminStudioToolsView(props) {
8220
9485
 
8221
9486
  // src/admin/components/studio/OpenInStudioMenuItem.tsx
8222
9487
  var import_ui13 = require("@payloadcms/ui");
8223
- var import_jsx_runtime42 = require("react/jsx-runtime");
9488
+ var import_jsx_runtime45 = require("react/jsx-runtime");
8224
9489
  function OpenInStudioMenuItem({ pagesPathBase = "/pages" }) {
8225
9490
  const documentInfo = (0, import_ui13.useDocumentInfo)();
8226
9491
  const id = documentInfo?.id;
8227
9492
  if (!id) {
8228
9493
  return null;
8229
9494
  }
8230
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
9495
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
8231
9496
  "a",
8232
9497
  {
8233
9498
  href: `${pagesPathBase}/${id}`,
@@ -8246,19 +9511,19 @@ function OpenInStudioMenuItem({ pagesPathBase = "/pages" }) {
8246
9511
  }
8247
9512
 
8248
9513
  // src/admin/components/studio/PageEditRedirectToStudio.tsx
8249
- var import_react33 = require("react");
9514
+ var import_react36 = require("react");
8250
9515
  var import_ui14 = require("@payloadcms/ui");
8251
- var import_jsx_runtime43 = require("react/jsx-runtime");
9516
+ var import_jsx_runtime46 = require("react/jsx-runtime");
8252
9517
  function PageEditRedirectToStudio({ pagesPathBase = "/pages" }) {
8253
9518
  const documentInfo = (0, import_ui14.useDocumentInfo)();
8254
9519
  const id = documentInfo?.id;
8255
- (0, import_react33.useEffect)(() => {
9520
+ (0, import_react36.useEffect)(() => {
8256
9521
  if (!id) {
8257
9522
  return;
8258
9523
  }
8259
9524
  window.location.replace(`${pagesPathBase}/${id}`);
8260
9525
  }, [id, pagesPathBase]);
8261
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
9526
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
8262
9527
  "div",
8263
9528
  {
8264
9529
  style: {
@@ -8270,18 +9535,61 @@ function PageEditRedirectToStudio({ pagesPathBase = "/pages" }) {
8270
9535
  minHeight: "50vh"
8271
9536
  },
8272
9537
  children: [
8273
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h2", { style: { margin: 0 }, children: "Opening Editor..." }),
8274
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { style: { color: "var(--theme-elevation-600)", margin: 0 }, children: "Redirecting to the custom page editor." }),
8275
- id ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("a", { href: `${pagesPathBase}/${id}`, children: "Continue to Editor" }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("a", { href: pagesPathBase, children: "Open Pages" })
9538
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h2", { style: { margin: 0 }, children: "Opening Editor..." }),
9539
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { style: { color: "var(--theme-elevation-600)", margin: 0 }, children: "Redirecting to the custom page editor." }),
9540
+ id ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("a", { href: `${pagesPathBase}/${id}`, children: "Continue to Editor" }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("a", { href: pagesPathBase, children: "Open Pages" })
8276
9541
  ]
8277
9542
  }
8278
9543
  );
8279
9544
  }
8280
9545
 
8281
- // src/admin/components/studio/StudioBackBreadcrumb.tsx
8282
- var import_react34 = require("react");
9546
+ // src/admin/components/studio/StudioDocumentRedirect.tsx
9547
+ var import_react37 = require("react");
8283
9548
  var import_ui15 = require("@payloadcms/ui");
8284
- var import_jsx_runtime44 = require("react/jsx-runtime");
9549
+ var import_jsx_runtime47 = require("react/jsx-runtime");
9550
+ function StudioDocumentRedirect({
9551
+ description = "Redirecting to the Studio view.",
9552
+ emptyHref,
9553
+ emptyLabel = "Open Studio",
9554
+ pathBase = "/forms",
9555
+ title = "Opening Studio..."
9556
+ }) {
9557
+ const adminBasePath = useAdminBasePath();
9558
+ const documentInfo = (0, import_ui15.useDocumentInfo)();
9559
+ const id = documentInfo?.id;
9560
+ const fallbackHref = resolveAdminPath(adminBasePath, emptyHref || pathBase);
9561
+ (0, import_react37.useEffect)(() => {
9562
+ if (!id) {
9563
+ return;
9564
+ }
9565
+ const targetHref = resolveAdminPath(adminBasePath, `${pathBase}/${encodeURIComponent(String(id))}`);
9566
+ window.location.replace(targetHref);
9567
+ }, [adminBasePath, id, pathBase]);
9568
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9569
+ "div",
9570
+ {
9571
+ style: {
9572
+ alignItems: "center",
9573
+ display: "flex",
9574
+ flexDirection: "column",
9575
+ gap: "0.75rem",
9576
+ justifyContent: "center",
9577
+ minHeight: "50vh",
9578
+ textAlign: "center"
9579
+ },
9580
+ children: [
9581
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h2", { style: { margin: 0 }, children: title }),
9582
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { style: { color: "var(--theme-elevation-600)", margin: 0 }, children: description }),
9583
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("a", { href: fallbackHref, children: emptyLabel })
9584
+ ]
9585
+ }
9586
+ );
9587
+ }
9588
+
9589
+ // src/admin/components/studio/StudioBackBreadcrumb.tsx
9590
+ var import_react38 = require("react");
9591
+ var import_ui16 = require("@payloadcms/ui");
9592
+ var import_jsx_runtime48 = require("react/jsx-runtime");
8285
9593
  var toTitle = (slug) => slug.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
8286
9594
  var buildNav = (pathname, adminBasePath) => {
8287
9595
  if (pathname.includes("/globals/")) {
@@ -8326,8 +9634,8 @@ var buildNav = (pathname, adminBasePath) => {
8326
9634
  };
8327
9635
  function StudioBackBreadcrumb() {
8328
9636
  const adminBasePath = useAdminBasePath();
8329
- const [pathname, setPathname] = (0, import_react34.useState)("");
8330
- (0, import_react34.useEffect)(() => {
9637
+ const [pathname, setPathname] = (0, import_react38.useState)("");
9638
+ (0, import_react38.useEffect)(() => {
8331
9639
  const update = () => setPathname(window.location.pathname);
8332
9640
  update();
8333
9641
  window.addEventListener("popstate", update);
@@ -8335,13 +9643,13 @@ function StudioBackBreadcrumb() {
8335
9643
  }, []);
8336
9644
  const nav = buildNav(pathname, adminBasePath);
8337
9645
  if (!nav) return null;
8338
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_ui15.SetStepNav, { nav });
9646
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui16.SetStepNav, { nav });
8339
9647
  }
8340
9648
 
8341
9649
  // src/admin/components/studio/StudioContactFormRedirect.tsx
8342
- var import_react35 = require("react");
8343
- var import_jsx_runtime45 = require("react/jsx-runtime");
8344
- var getPropString14 = (props, key, fallback) => {
9650
+ var import_react39 = require("react");
9651
+ var import_jsx_runtime49 = require("react/jsx-runtime");
9652
+ var getPropString15 = (props, key, fallback) => {
8345
9653
  if (!props || typeof props !== "object") return fallback;
8346
9654
  const direct = props[key];
8347
9655
  if (typeof direct === "string" && direct.length > 0) return direct;
@@ -8354,13 +9662,13 @@ var getPropString14 = (props, key, fallback) => {
8354
9662
  };
8355
9663
  function StudioContactFormRedirect(props) {
8356
9664
  const adminBasePath = useAdminBasePath();
8357
- const studioContactFormPath = getPropString14(props, "studioContactFormPath", "/contact-form");
9665
+ const studioContactFormPath = getPropString15(props, "studioContactFormPath", "/contact-form");
8358
9666
  const targetPath = resolveAdminPath(adminBasePath, studioContactFormPath);
8359
- (0, import_react35.useEffect)(() => {
9667
+ (0, import_react39.useEffect)(() => {
8360
9668
  if (window.location.pathname === targetPath) return;
8361
9669
  window.location.replace(targetPath);
8362
9670
  }, [targetPath]);
8363
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
9671
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
8364
9672
  "div",
8365
9673
  {
8366
9674
  style: {
@@ -8373,8 +9681,8 @@ function StudioContactFormRedirect(props) {
8373
9681
  minHeight: "40vh"
8374
9682
  },
8375
9683
  children: [
8376
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("h2", { style: { margin: 0 }, children: "Opening Contact Form Editor..." }),
8377
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("a", { href: targetPath, children: "Continue" })
9684
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("h2", { style: { margin: 0 }, children: "Opening Contact Form Editor..." }),
9685
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("a", { href: targetPath, children: "Continue" })
8378
9686
  ]
8379
9687
  }
8380
9688
  );
@@ -8386,6 +9694,9 @@ function StudioContactFormRedirect(props) {
8386
9694
  AdminStudioContactFormView,
8387
9695
  AdminStudioDashboard,
8388
9696
  AdminStudioFooterGlobalView,
9697
+ AdminStudioFormDetailView,
9698
+ AdminStudioFormSubmissionView,
9699
+ AdminStudioFormUploadView,
8389
9700
  AdminStudioFormsView,
8390
9701
  AdminStudioGlobalsView,
8391
9702
  AdminStudioHeaderGlobalView,
@@ -8411,6 +9722,7 @@ function StudioContactFormRedirect(props) {
8411
9722
  StatusBadge,
8412
9723
  StudioBackBreadcrumb,
8413
9724
  StudioContactFormRedirect,
9725
+ StudioDocumentRedirect,
8414
9726
  StudioSectionLayout,
8415
9727
  ThemeProvider,
8416
9728
  ThemeSwitcher,