@orion-studios/payload-studio 0.6.0-beta.16 → 0.6.0-beta.18

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,45 +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
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-inline-actions", style: { marginBottom: "1rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("a", { className: "orion-admin-action-button", href: "/admin-core", target: "_blank", children: "Open Payload Core Admin" }) }),
8176
- error ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-error", style: { marginBottom: "1rem" }, children: error }) : null,
8177
- savedMessage ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-success", style: { marginBottom: "1rem" }, children: savedMessage }) : null,
8178
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("form", { className: "orion-admin-form", onSubmit: createUser, style: { marginBottom: "1rem" }, children: [
8179
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Create User" }),
8180
- /* @__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: [
8181
9445
  "Email",
8182
- /* @__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" })
8183
9447
  ] }),
8184
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9448
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
8185
9449
  "Full Name",
8186
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("input", { name: "fullName", type: "text" })
9450
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { name: "fullName", type: "text" })
8187
9451
  ] }),
8188
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9452
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
8189
9453
  "Password",
8190
- /* @__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" })
8191
9455
  ] }),
8192
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9456
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
8193
9457
  "Role",
8194
- /* @__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)) })
8195
9459
  ] }),
8196
- /* @__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" })
8197
9461
  ] }),
8198
- loading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
8199
- /* @__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) => {
8200
9464
  const id = typeof doc.id === "string" || typeof doc.id === "number" ? String(doc.id) : "";
8201
9465
  if (!id) return null;
8202
9466
  const email = typeof doc.email === "string" ? doc.email : `user-${id}`;
8203
9467
  const fullName = typeof doc.fullName === "string" ? doc.fullName : "";
8204
9468
  const currentRole = typeof doc.role === "string" ? normalizeRole(doc.role) : "editor";
8205
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-list-item", children: [
8206
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
8207
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: email }),
8208
- /* @__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" })
8209
9473
  ] }),
8210
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("form", { className: "orion-admin-inline-actions", onSubmit: updateUserRole, children: [
8211
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("input", { name: "id", type: "hidden", value: id }),
8212
- /* @__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)) }),
8213
- /* @__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" })
8214
9478
  ] })
8215
9479
  ] }, id);
8216
9480
  }) })
@@ -8221,14 +9485,14 @@ function AdminStudioToolsView(props) {
8221
9485
 
8222
9486
  // src/admin/components/studio/OpenInStudioMenuItem.tsx
8223
9487
  var import_ui13 = require("@payloadcms/ui");
8224
- var import_jsx_runtime42 = require("react/jsx-runtime");
9488
+ var import_jsx_runtime45 = require("react/jsx-runtime");
8225
9489
  function OpenInStudioMenuItem({ pagesPathBase = "/pages" }) {
8226
9490
  const documentInfo = (0, import_ui13.useDocumentInfo)();
8227
9491
  const id = documentInfo?.id;
8228
9492
  if (!id) {
8229
9493
  return null;
8230
9494
  }
8231
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
9495
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
8232
9496
  "a",
8233
9497
  {
8234
9498
  href: `${pagesPathBase}/${id}`,
@@ -8247,19 +9511,19 @@ function OpenInStudioMenuItem({ pagesPathBase = "/pages" }) {
8247
9511
  }
8248
9512
 
8249
9513
  // src/admin/components/studio/PageEditRedirectToStudio.tsx
8250
- var import_react33 = require("react");
9514
+ var import_react36 = require("react");
8251
9515
  var import_ui14 = require("@payloadcms/ui");
8252
- var import_jsx_runtime43 = require("react/jsx-runtime");
9516
+ var import_jsx_runtime46 = require("react/jsx-runtime");
8253
9517
  function PageEditRedirectToStudio({ pagesPathBase = "/pages" }) {
8254
9518
  const documentInfo = (0, import_ui14.useDocumentInfo)();
8255
9519
  const id = documentInfo?.id;
8256
- (0, import_react33.useEffect)(() => {
9520
+ (0, import_react36.useEffect)(() => {
8257
9521
  if (!id) {
8258
9522
  return;
8259
9523
  }
8260
9524
  window.location.replace(`${pagesPathBase}/${id}`);
8261
9525
  }, [id, pagesPathBase]);
8262
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
9526
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
8263
9527
  "div",
8264
9528
  {
8265
9529
  style: {
@@ -8271,18 +9535,61 @@ function PageEditRedirectToStudio({ pagesPathBase = "/pages" }) {
8271
9535
  minHeight: "50vh"
8272
9536
  },
8273
9537
  children: [
8274
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h2", { style: { margin: 0 }, children: "Opening Editor..." }),
8275
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { style: { color: "var(--theme-elevation-600)", margin: 0 }, children: "Redirecting to the custom page editor." }),
8276
- 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" })
8277
9541
  ]
8278
9542
  }
8279
9543
  );
8280
9544
  }
8281
9545
 
8282
- // src/admin/components/studio/StudioBackBreadcrumb.tsx
8283
- var import_react34 = require("react");
9546
+ // src/admin/components/studio/StudioDocumentRedirect.tsx
9547
+ var import_react37 = require("react");
8284
9548
  var import_ui15 = require("@payloadcms/ui");
8285
- 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");
8286
9593
  var toTitle = (slug) => slug.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
8287
9594
  var buildNav = (pathname, adminBasePath) => {
8288
9595
  if (pathname.includes("/globals/")) {
@@ -8327,8 +9634,8 @@ var buildNav = (pathname, adminBasePath) => {
8327
9634
  };
8328
9635
  function StudioBackBreadcrumb() {
8329
9636
  const adminBasePath = useAdminBasePath();
8330
- const [pathname, setPathname] = (0, import_react34.useState)("");
8331
- (0, import_react34.useEffect)(() => {
9637
+ const [pathname, setPathname] = (0, import_react38.useState)("");
9638
+ (0, import_react38.useEffect)(() => {
8332
9639
  const update = () => setPathname(window.location.pathname);
8333
9640
  update();
8334
9641
  window.addEventListener("popstate", update);
@@ -8336,13 +9643,13 @@ function StudioBackBreadcrumb() {
8336
9643
  }, []);
8337
9644
  const nav = buildNav(pathname, adminBasePath);
8338
9645
  if (!nav) return null;
8339
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_ui15.SetStepNav, { nav });
9646
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui16.SetStepNav, { nav });
8340
9647
  }
8341
9648
 
8342
9649
  // src/admin/components/studio/StudioContactFormRedirect.tsx
8343
- var import_react35 = require("react");
8344
- var import_jsx_runtime45 = require("react/jsx-runtime");
8345
- 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) => {
8346
9653
  if (!props || typeof props !== "object") return fallback;
8347
9654
  const direct = props[key];
8348
9655
  if (typeof direct === "string" && direct.length > 0) return direct;
@@ -8355,13 +9662,13 @@ var getPropString14 = (props, key, fallback) => {
8355
9662
  };
8356
9663
  function StudioContactFormRedirect(props) {
8357
9664
  const adminBasePath = useAdminBasePath();
8358
- const studioContactFormPath = getPropString14(props, "studioContactFormPath", "/contact-form");
9665
+ const studioContactFormPath = getPropString15(props, "studioContactFormPath", "/contact-form");
8359
9666
  const targetPath = resolveAdminPath(adminBasePath, studioContactFormPath);
8360
- (0, import_react35.useEffect)(() => {
9667
+ (0, import_react39.useEffect)(() => {
8361
9668
  if (window.location.pathname === targetPath) return;
8362
9669
  window.location.replace(targetPath);
8363
9670
  }, [targetPath]);
8364
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
9671
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
8365
9672
  "div",
8366
9673
  {
8367
9674
  style: {
@@ -8374,8 +9681,8 @@ function StudioContactFormRedirect(props) {
8374
9681
  minHeight: "40vh"
8375
9682
  },
8376
9683
  children: [
8377
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("h2", { style: { margin: 0 }, children: "Opening Contact Form Editor..." }),
8378
- /* @__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" })
8379
9686
  ]
8380
9687
  }
8381
9688
  );
@@ -8387,6 +9694,9 @@ function StudioContactFormRedirect(props) {
8387
9694
  AdminStudioContactFormView,
8388
9695
  AdminStudioDashboard,
8389
9696
  AdminStudioFooterGlobalView,
9697
+ AdminStudioFormDetailView,
9698
+ AdminStudioFormSubmissionView,
9699
+ AdminStudioFormUploadView,
8390
9700
  AdminStudioFormsView,
8391
9701
  AdminStudioGlobalsView,
8392
9702
  AdminStudioHeaderGlobalView,
@@ -8412,6 +9722,7 @@ function StudioContactFormRedirect(props) {
8412
9722
  StatusBadge,
8413
9723
  StudioBackBreadcrumb,
8414
9724
  StudioContactFormRedirect,
9725
+ StudioDocumentRedirect,
8415
9726
  StudioSectionLayout,
8416
9727
  ThemeProvider,
8417
9728
  ThemeSwitcher,