medusa-contact-us 0.0.17 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/index.js +493 -4
- package/.medusa/server/src/admin/index.mjs +495 -6
- package/.medusa/server/src/api/admin/contact-requests/[id]/route.js +17 -0
- package/.medusa/server/src/api/admin/contact-requests/[id]/status/route.js +24 -0
- package/.medusa/server/src/api/admin/contact-requests/route.js +67 -0
- package/.medusa/server/src/api/admin/contact-requests/validators.js +29 -0
- package/.medusa/server/src/api/store/contact-requests/route.js +23 -0
- package/.medusa/server/src/api/store/contact-requests/validators.js +11 -0
- package/.medusa/server/src/helpers/contact-request.js +52 -0
- package/.medusa/server/src/helpers/index.js +5 -2
- package/.medusa/server/src/index.js +10 -2
- package/.medusa/server/src/modules/contact-requests/index.js +14 -0
- package/.medusa/server/src/modules/contact-requests/migrations/Migration20241129163317.js +47 -0
- package/.medusa/server/src/modules/contact-requests/models/contact-request.js +15 -0
- package/.medusa/server/src/modules/contact-requests/service.js +236 -0
- package/.medusa/server/src/modules/contact-requests/utils/resolve-options.js +48 -0
- package/.medusa/server/src/types/contact-request.js +3 -0
- package/.medusa/server/src/workflows/create-contact-request-workflow.js +13 -0
- package/.medusa/server/src/workflows/index.js +8 -0
- package/.medusa/server/src/workflows/steps/create-contact-request-step.js +13 -0
- package/.medusa/server/src/workflows/steps/resolve-status-transition-step.js +15 -0
- package/.medusa/server/src/workflows/steps/send-status-notification-step.js +56 -0
- package/.medusa/server/src/workflows/steps/update-contact-request-status-step.js +17 -0
- package/.medusa/server/src/workflows/update-contact-request-status-workflow.js +33 -0
- package/README.md +381 -10
- package/package.json +2 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useCallback, useEffect, useMemo } from "react";
|
|
3
3
|
import { defineRouteConfig } from "@medusajs/admin-sdk";
|
|
4
|
-
import { Container, Heading, Text, Button, Input, Badge } from "@medusajs/ui";
|
|
5
|
-
import { Envelope } from "@medusajs/icons";
|
|
6
|
-
|
|
4
|
+
import { Container, Heading, Text, Button, Input, Badge, Textarea } from "@medusajs/ui";
|
|
5
|
+
import { Envelope, ChatBubbleLeftRight, ArrowLeft } from "@medusajs/icons";
|
|
6
|
+
import { useNavigate, useParams } from "react-router-dom";
|
|
7
|
+
const useDebounce$1 = (value, delay) => {
|
|
7
8
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
8
9
|
useEffect(() => {
|
|
9
10
|
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
@@ -26,7 +27,7 @@ const ContactEmailSubscriptionsPage = () => {
|
|
|
26
27
|
const [items, setItems] = useState([]);
|
|
27
28
|
const [statusFilter, setStatusFilter] = useState("all");
|
|
28
29
|
const [query, setQuery] = useState("");
|
|
29
|
-
const debouncedQuery = useDebounce(query, 300);
|
|
30
|
+
const debouncedQuery = useDebounce$1(query, 300);
|
|
30
31
|
const [isLoading, setIsLoading] = useState(true);
|
|
31
32
|
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
32
33
|
const [error, setError] = useState(null);
|
|
@@ -164,10 +165,478 @@ const ContactEmailSubscriptionsPage = () => {
|
|
|
164
165
|
) }) : null
|
|
165
166
|
] }) });
|
|
166
167
|
};
|
|
167
|
-
const config = defineRouteConfig({
|
|
168
|
+
const config$2 = defineRouteConfig({
|
|
168
169
|
label: "Contact email list",
|
|
169
170
|
icon: Envelope
|
|
170
171
|
});
|
|
172
|
+
const useDebounce = (value, delay) => {
|
|
173
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
176
|
+
return () => clearTimeout(handler);
|
|
177
|
+
}, [value, delay]);
|
|
178
|
+
return debouncedValue;
|
|
179
|
+
};
|
|
180
|
+
const getStatusBadgeClass$1 = (status) => {
|
|
181
|
+
const statusLower = status.toLowerCase();
|
|
182
|
+
if (statusLower === "pending") {
|
|
183
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
184
|
+
}
|
|
185
|
+
if (statusLower === "in_progress") {
|
|
186
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
187
|
+
}
|
|
188
|
+
if (statusLower === "resolved") {
|
|
189
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
190
|
+
}
|
|
191
|
+
if (statusLower === "closed") {
|
|
192
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
193
|
+
}
|
|
194
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
195
|
+
};
|
|
196
|
+
const ContactRequestsPage = () => {
|
|
197
|
+
const navigate = useNavigate();
|
|
198
|
+
const [items, setItems] = useState([]);
|
|
199
|
+
const [statusFilter, setStatusFilter] = useState("all");
|
|
200
|
+
const [emailQuery, setEmailQuery] = useState("");
|
|
201
|
+
const [sourceFilter, setSourceFilter] = useState("all");
|
|
202
|
+
const debouncedEmailQuery = useDebounce(emailQuery, 300);
|
|
203
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
204
|
+
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
205
|
+
const [error, setError] = useState(null);
|
|
206
|
+
const [offset, setOffset] = useState(0);
|
|
207
|
+
const [count, setCount] = useState(0);
|
|
208
|
+
const limit = 50;
|
|
209
|
+
const loadRequests = useCallback(
|
|
210
|
+
async (nextOffset, replace = false) => {
|
|
211
|
+
var _a;
|
|
212
|
+
try {
|
|
213
|
+
if (replace) {
|
|
214
|
+
setIsLoading(true);
|
|
215
|
+
} else {
|
|
216
|
+
setIsFetchingMore(true);
|
|
217
|
+
}
|
|
218
|
+
setError(null);
|
|
219
|
+
const params = new URLSearchParams();
|
|
220
|
+
params.set("limit", String(limit));
|
|
221
|
+
params.set("offset", String(nextOffset));
|
|
222
|
+
if (statusFilter !== "all") {
|
|
223
|
+
params.set("status", statusFilter);
|
|
224
|
+
}
|
|
225
|
+
if (debouncedEmailQuery.trim()) {
|
|
226
|
+
params.set("email", debouncedEmailQuery.trim());
|
|
227
|
+
}
|
|
228
|
+
if (sourceFilter !== "all") {
|
|
229
|
+
params.set("source", sourceFilter);
|
|
230
|
+
}
|
|
231
|
+
params.set("order", "created_at");
|
|
232
|
+
params.set("order_direction", "DESC");
|
|
233
|
+
const response = await fetch(
|
|
234
|
+
`/admin/contact-requests?${params.toString()}`,
|
|
235
|
+
{ credentials: "include" }
|
|
236
|
+
);
|
|
237
|
+
if (!response.ok) {
|
|
238
|
+
const message = await response.text();
|
|
239
|
+
throw new Error(message || "Unable to load contact requests");
|
|
240
|
+
}
|
|
241
|
+
const payload = await response.json();
|
|
242
|
+
setCount(payload.count ?? 0);
|
|
243
|
+
setOffset(nextOffset + (((_a = payload.requests) == null ? void 0 : _a.length) ?? 0));
|
|
244
|
+
setItems(
|
|
245
|
+
(prev) => replace ? payload.requests ?? [] : [...prev, ...payload.requests ?? []]
|
|
246
|
+
);
|
|
247
|
+
} catch (loadError) {
|
|
248
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load contact requests";
|
|
249
|
+
setError(message);
|
|
250
|
+
} finally {
|
|
251
|
+
setIsLoading(false);
|
|
252
|
+
setIsFetchingMore(false);
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
[statusFilter, debouncedEmailQuery, sourceFilter]
|
|
256
|
+
);
|
|
257
|
+
useEffect(() => {
|
|
258
|
+
void loadRequests(0, true);
|
|
259
|
+
}, [statusFilter, debouncedEmailQuery, sourceFilter, loadRequests]);
|
|
260
|
+
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
261
|
+
const availableStatuses = useMemo(() => {
|
|
262
|
+
const statuses = /* @__PURE__ */ new Set();
|
|
263
|
+
items.forEach((item) => statuses.add(item.status));
|
|
264
|
+
return Array.from(statuses).sort();
|
|
265
|
+
}, [items]);
|
|
266
|
+
const availableSources = useMemo(() => {
|
|
267
|
+
const sources = /* @__PURE__ */ new Set();
|
|
268
|
+
items.forEach((item) => {
|
|
269
|
+
if (item.source) {
|
|
270
|
+
sources.add(item.source);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
return Array.from(sources).sort();
|
|
274
|
+
}, [items]);
|
|
275
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-7xl flex-col gap-6 p-6", children: [
|
|
276
|
+
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
277
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
278
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Contact Requests" }),
|
|
279
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Manage and track customer contact requests from the storefront" })
|
|
280
|
+
] }),
|
|
281
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadRequests(0, true), children: "Refresh" })
|
|
282
|
+
] }),
|
|
283
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
284
|
+
/* @__PURE__ */ jsx(
|
|
285
|
+
Input,
|
|
286
|
+
{
|
|
287
|
+
placeholder: "Search by email",
|
|
288
|
+
value: emailQuery,
|
|
289
|
+
onChange: (event) => setEmailQuery(event.target.value),
|
|
290
|
+
className: "md:max-w-sm"
|
|
291
|
+
}
|
|
292
|
+
),
|
|
293
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
294
|
+
/* @__PURE__ */ jsxs(
|
|
295
|
+
"select",
|
|
296
|
+
{
|
|
297
|
+
value: statusFilter,
|
|
298
|
+
onChange: (event) => setStatusFilter(event.target.value),
|
|
299
|
+
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
300
|
+
children: [
|
|
301
|
+
/* @__PURE__ */ jsx("option", { value: "all", children: "All Statuses" }),
|
|
302
|
+
availableStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: status.replace("_", " ").toUpperCase() }, status))
|
|
303
|
+
]
|
|
304
|
+
}
|
|
305
|
+
),
|
|
306
|
+
/* @__PURE__ */ jsxs(
|
|
307
|
+
"select",
|
|
308
|
+
{
|
|
309
|
+
value: sourceFilter,
|
|
310
|
+
onChange: (event) => setSourceFilter(event.target.value),
|
|
311
|
+
className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive md:max-w-xs",
|
|
312
|
+
children: [
|
|
313
|
+
/* @__PURE__ */ jsx("option", { value: "all", children: "All Sources" }),
|
|
314
|
+
availableSources.map((source) => /* @__PURE__ */ jsx("option", { value: source, children: source }, source))
|
|
315
|
+
]
|
|
316
|
+
}
|
|
317
|
+
)
|
|
318
|
+
] })
|
|
319
|
+
] }),
|
|
320
|
+
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
321
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
322
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
323
|
+
Button,
|
|
324
|
+
{
|
|
325
|
+
variant: "secondary",
|
|
326
|
+
onClick: () => loadRequests(0, true),
|
|
327
|
+
children: "Try again"
|
|
328
|
+
}
|
|
329
|
+
) })
|
|
330
|
+
] }) : null,
|
|
331
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading contact requests..." }) }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
332
|
+
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No contact requests yet" }),
|
|
333
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "Contact requests created through the storefront will appear here." })
|
|
334
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-xl border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
|
|
335
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
336
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Email" }),
|
|
337
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
338
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Source" }),
|
|
339
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
340
|
+
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Actions" })
|
|
341
|
+
] }) }),
|
|
342
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: items.map((request) => /* @__PURE__ */ jsxs(
|
|
343
|
+
"tr",
|
|
344
|
+
{
|
|
345
|
+
className: "hover:bg-ui-bg-subtle/60 cursor-pointer",
|
|
346
|
+
onClick: () => navigate(`/contact-requests/${request.id}`),
|
|
347
|
+
children: [
|
|
348
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
349
|
+
/* @__PURE__ */ jsx("span", { children: request.email }),
|
|
350
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: request.id })
|
|
351
|
+
] }) }),
|
|
352
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
353
|
+
Badge,
|
|
354
|
+
{
|
|
355
|
+
size: "2xsmall",
|
|
356
|
+
className: `uppercase ${getStatusBadgeClass$1(request.status)}`,
|
|
357
|
+
children: request.status.replace("_", " ")
|
|
358
|
+
}
|
|
359
|
+
) }),
|
|
360
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: request.source ?? "storefront" }),
|
|
361
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(request.created_at).toLocaleString() }),
|
|
362
|
+
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
363
|
+
Button,
|
|
364
|
+
{
|
|
365
|
+
variant: "transparent",
|
|
366
|
+
size: "small",
|
|
367
|
+
onClick: (e) => {
|
|
368
|
+
e.stopPropagation();
|
|
369
|
+
navigate(`/contact-requests/${request.id}`);
|
|
370
|
+
},
|
|
371
|
+
children: "View"
|
|
372
|
+
}
|
|
373
|
+
) })
|
|
374
|
+
]
|
|
375
|
+
},
|
|
376
|
+
request.id
|
|
377
|
+
)) })
|
|
378
|
+
] }) }),
|
|
379
|
+
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
380
|
+
Button,
|
|
381
|
+
{
|
|
382
|
+
variant: "secondary",
|
|
383
|
+
isLoading: isFetchingMore,
|
|
384
|
+
onClick: () => loadRequests(offset, false),
|
|
385
|
+
children: "Load more"
|
|
386
|
+
}
|
|
387
|
+
) }) : null
|
|
388
|
+
] }) });
|
|
389
|
+
};
|
|
390
|
+
const config$1 = defineRouteConfig({
|
|
391
|
+
label: "Contact Requests",
|
|
392
|
+
icon: ChatBubbleLeftRight
|
|
393
|
+
});
|
|
394
|
+
const getStatusBadgeClass = (status) => {
|
|
395
|
+
const statusLower = status.toLowerCase();
|
|
396
|
+
if (statusLower === "pending") {
|
|
397
|
+
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
398
|
+
}
|
|
399
|
+
if (statusLower === "in_progress") {
|
|
400
|
+
return "bg-ui-tag-blue-bg text-ui-tag-blue-text";
|
|
401
|
+
}
|
|
402
|
+
if (statusLower === "resolved") {
|
|
403
|
+
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
404
|
+
}
|
|
405
|
+
if (statusLower === "closed") {
|
|
406
|
+
return "bg-ui-tag-grey-bg text-ui-tag-grey-text";
|
|
407
|
+
}
|
|
408
|
+
return "bg-ui-tag-purple-bg text-ui-tag-purple-text";
|
|
409
|
+
};
|
|
410
|
+
const ContactRequestDetailPage = () => {
|
|
411
|
+
const navigate = useNavigate();
|
|
412
|
+
const { id } = useParams();
|
|
413
|
+
const [request, setRequest] = useState(null);
|
|
414
|
+
const [nextAllowedStatuses, setNextAllowedStatuses] = useState([]);
|
|
415
|
+
const [selectedStatus, setSelectedStatus] = useState("");
|
|
416
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
417
|
+
const [isUpdating, setIsUpdating] = useState(false);
|
|
418
|
+
const [error, setError] = useState(null);
|
|
419
|
+
const [updateError, setUpdateError] = useState(null);
|
|
420
|
+
const [updateSuccess, setUpdateSuccess] = useState(false);
|
|
421
|
+
useEffect(() => {
|
|
422
|
+
if (!id) {
|
|
423
|
+
navigate("/contact-requests");
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
const loadRequest = async () => {
|
|
427
|
+
try {
|
|
428
|
+
setIsLoading(true);
|
|
429
|
+
setError(null);
|
|
430
|
+
const response = await fetch(`/admin/contact-requests/${id}`, {
|
|
431
|
+
credentials: "include"
|
|
432
|
+
});
|
|
433
|
+
if (!response.ok) {
|
|
434
|
+
const message = await response.text();
|
|
435
|
+
throw new Error(message || "Unable to load contact request");
|
|
436
|
+
}
|
|
437
|
+
const payload = await response.json();
|
|
438
|
+
setRequest(payload.request);
|
|
439
|
+
setNextAllowedStatuses(payload.next_allowed_statuses ?? []);
|
|
440
|
+
setSelectedStatus("");
|
|
441
|
+
} catch (loadError) {
|
|
442
|
+
const message = loadError instanceof Error ? loadError.message : "Unable to load contact request";
|
|
443
|
+
setError(message);
|
|
444
|
+
} finally {
|
|
445
|
+
setIsLoading(false);
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
void loadRequest();
|
|
449
|
+
}, [id, navigate]);
|
|
450
|
+
const handleStatusUpdate = async () => {
|
|
451
|
+
if (!id || !selectedStatus) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
try {
|
|
455
|
+
setIsUpdating(true);
|
|
456
|
+
setUpdateError(null);
|
|
457
|
+
setUpdateSuccess(false);
|
|
458
|
+
const response = await fetch(`/admin/contact-requests/${id}/status`, {
|
|
459
|
+
method: "POST",
|
|
460
|
+
headers: {
|
|
461
|
+
"Content-Type": "application/json"
|
|
462
|
+
},
|
|
463
|
+
credentials: "include",
|
|
464
|
+
body: JSON.stringify({ status: selectedStatus })
|
|
465
|
+
});
|
|
466
|
+
if (!response.ok) {
|
|
467
|
+
const message = await response.text();
|
|
468
|
+
throw new Error(message || "Unable to update status");
|
|
469
|
+
}
|
|
470
|
+
const payload = await response.json();
|
|
471
|
+
setRequest(payload.request);
|
|
472
|
+
setSelectedStatus("");
|
|
473
|
+
setUpdateSuccess(true);
|
|
474
|
+
setTimeout(() => setUpdateSuccess(false), 3e3);
|
|
475
|
+
const detailResponse = await fetch(`/admin/contact-requests/${id}`, {
|
|
476
|
+
credentials: "include"
|
|
477
|
+
});
|
|
478
|
+
if (detailResponse.ok) {
|
|
479
|
+
const detailPayload = await detailResponse.json();
|
|
480
|
+
setNextAllowedStatuses(detailPayload.next_allowed_statuses ?? []);
|
|
481
|
+
}
|
|
482
|
+
} catch (updateErr) {
|
|
483
|
+
const message = updateErr instanceof Error ? updateErr.message : "Unable to update status";
|
|
484
|
+
setUpdateError(message);
|
|
485
|
+
} finally {
|
|
486
|
+
setIsUpdating(false);
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
if (isLoading) {
|
|
490
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsx(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading contact request..." }) }) }) });
|
|
491
|
+
}
|
|
492
|
+
if (error || !request) {
|
|
493
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsx(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
494
|
+
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error || "Contact request not found" }),
|
|
495
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => navigate("/contact-requests"), children: "Back to list" }) })
|
|
496
|
+
] }) }) });
|
|
497
|
+
}
|
|
498
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-5xl flex-col gap-6 p-6", children: [
|
|
499
|
+
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
500
|
+
/* @__PURE__ */ jsxs(
|
|
501
|
+
Button,
|
|
502
|
+
{
|
|
503
|
+
variant: "transparent",
|
|
504
|
+
size: "small",
|
|
505
|
+
onClick: () => navigate("/contact-requests"),
|
|
506
|
+
className: "w-fit",
|
|
507
|
+
children: [
|
|
508
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "mr-2" }),
|
|
509
|
+
"Back to list"
|
|
510
|
+
]
|
|
511
|
+
}
|
|
512
|
+
),
|
|
513
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between", children: [
|
|
514
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
515
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Contact Request Details" }),
|
|
516
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: request.id })
|
|
517
|
+
] }),
|
|
518
|
+
/* @__PURE__ */ jsx(
|
|
519
|
+
Badge,
|
|
520
|
+
{
|
|
521
|
+
size: "small",
|
|
522
|
+
className: `uppercase ${getStatusBadgeClass(request.status)}`,
|
|
523
|
+
children: request.status.replace("_", " ")
|
|
524
|
+
}
|
|
525
|
+
)
|
|
526
|
+
] })
|
|
527
|
+
] }),
|
|
528
|
+
nextAllowedStatuses.length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
529
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Update Status" }),
|
|
530
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-end", children: [
|
|
531
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
532
|
+
/* @__PURE__ */ jsx("label", { className: "mb-2 block text-sm font-medium text-ui-fg-base", children: "New Status" }),
|
|
533
|
+
/* @__PURE__ */ jsxs(
|
|
534
|
+
"select",
|
|
535
|
+
{
|
|
536
|
+
value: selectedStatus,
|
|
537
|
+
onChange: (event) => setSelectedStatus(event.target.value),
|
|
538
|
+
className: "h-9 w-full rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive",
|
|
539
|
+
children: [
|
|
540
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Select new status" }),
|
|
541
|
+
nextAllowedStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: status.replace("_", " ").toUpperCase() }, status))
|
|
542
|
+
]
|
|
543
|
+
}
|
|
544
|
+
)
|
|
545
|
+
] }),
|
|
546
|
+
/* @__PURE__ */ jsx(
|
|
547
|
+
Button,
|
|
548
|
+
{
|
|
549
|
+
variant: "primary",
|
|
550
|
+
onClick: handleStatusUpdate,
|
|
551
|
+
disabled: !selectedStatus || isUpdating,
|
|
552
|
+
isLoading: isUpdating,
|
|
553
|
+
children: "Update Status"
|
|
554
|
+
}
|
|
555
|
+
)
|
|
556
|
+
] }),
|
|
557
|
+
updateError && /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-error", children: updateError }),
|
|
558
|
+
updateSuccess && /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-success", children: "Status updated successfully" })
|
|
559
|
+
] }),
|
|
560
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-6 md:grid-cols-2", children: [
|
|
561
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
562
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Contact Information" }),
|
|
563
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
564
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
565
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Email" }),
|
|
566
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: request.email })
|
|
567
|
+
] }),
|
|
568
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
569
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Source" }),
|
|
570
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: request.source ?? "storefront" })
|
|
571
|
+
] }),
|
|
572
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
573
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Created" }),
|
|
574
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: new Date(request.created_at).toLocaleString() })
|
|
575
|
+
] }),
|
|
576
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
577
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Last Updated" }),
|
|
578
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: new Date(request.updated_at).toLocaleString() })
|
|
579
|
+
] })
|
|
580
|
+
] })
|
|
581
|
+
] }),
|
|
582
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
583
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Status History" }),
|
|
584
|
+
request.status_history && request.status_history.length > 0 ? /* @__PURE__ */ jsx("div", { className: "space-y-2", children: request.status_history.map((entry, index) => /* @__PURE__ */ jsx(
|
|
585
|
+
"div",
|
|
586
|
+
{
|
|
587
|
+
className: "flex items-center justify-between border-b border-ui-border-subtle pb-2 last:border-0",
|
|
588
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
589
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
590
|
+
/* @__PURE__ */ jsx(
|
|
591
|
+
Badge,
|
|
592
|
+
{
|
|
593
|
+
size: "2xsmall",
|
|
594
|
+
className: `uppercase ${getStatusBadgeClass(entry.to)}`,
|
|
595
|
+
children: entry.to.replace("_", " ")
|
|
596
|
+
}
|
|
597
|
+
),
|
|
598
|
+
entry.from && /* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
599
|
+
"from ",
|
|
600
|
+
entry.from.replace("_", " ")
|
|
601
|
+
] })
|
|
602
|
+
] }),
|
|
603
|
+
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
604
|
+
new Date(entry.changed_at).toLocaleString(),
|
|
605
|
+
entry.changed_by && ` by ${entry.changed_by}`
|
|
606
|
+
] })
|
|
607
|
+
] })
|
|
608
|
+
},
|
|
609
|
+
index
|
|
610
|
+
)) }) : /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No status history available" })
|
|
611
|
+
] })
|
|
612
|
+
] }),
|
|
613
|
+
request.payload && Object.keys(request.payload).length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
614
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Request Details" }),
|
|
615
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: Object.entries(request.payload).map(([key, value]) => /* @__PURE__ */ jsxs("div", { children: [
|
|
616
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: key.charAt(0).toUpperCase() + key.slice(1).replace("_", " ") }),
|
|
617
|
+
/* @__PURE__ */ jsx(
|
|
618
|
+
Textarea,
|
|
619
|
+
{
|
|
620
|
+
value: typeof value === "string" ? value : JSON.stringify(value, null, 2),
|
|
621
|
+
readOnly: true,
|
|
622
|
+
className: "mt-1 min-h-[60px]"
|
|
623
|
+
}
|
|
624
|
+
)
|
|
625
|
+
] }, key)) })
|
|
626
|
+
] }),
|
|
627
|
+
request.metadata && Object.keys(request.metadata).length > 0 && /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base p-6", children: [
|
|
628
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", className: "mb-4 text-lg", children: "Metadata" }),
|
|
629
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: Object.entries(request.metadata).map(([key, value]) => /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
630
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: key }),
|
|
631
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "font-medium", children: typeof value === "string" ? value : JSON.stringify(value) })
|
|
632
|
+
] }, key)) })
|
|
633
|
+
] })
|
|
634
|
+
] }) });
|
|
635
|
+
};
|
|
636
|
+
const config = defineRouteConfig({
|
|
637
|
+
label: "Contact Request Details",
|
|
638
|
+
icon: ChatBubbleLeftRight
|
|
639
|
+
});
|
|
171
640
|
const en = {};
|
|
172
641
|
const i18nTranslations0 = {
|
|
173
642
|
en
|
|
@@ -178,15 +647,35 @@ const routeModule = {
|
|
|
178
647
|
{
|
|
179
648
|
Component: ContactEmailSubscriptionsPage,
|
|
180
649
|
path: "/contact-email-subscriptions"
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
Component: ContactRequestsPage,
|
|
653
|
+
path: "/contact-requests"
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
Component: ContactRequestDetailPage,
|
|
657
|
+
path: "/contact-requests/:id"
|
|
181
658
|
}
|
|
182
659
|
]
|
|
183
660
|
};
|
|
184
661
|
const menuItemModule = {
|
|
185
662
|
menuItems: [
|
|
663
|
+
{
|
|
664
|
+
label: config$2.label,
|
|
665
|
+
icon: config$2.icon,
|
|
666
|
+
path: "/contact-email-subscriptions",
|
|
667
|
+
nested: void 0
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
label: config$1.label,
|
|
671
|
+
icon: config$1.icon,
|
|
672
|
+
path: "/contact-requests",
|
|
673
|
+
nested: void 0
|
|
674
|
+
},
|
|
186
675
|
{
|
|
187
676
|
label: config.label,
|
|
188
677
|
icon: config.icon,
|
|
189
|
-
path: "/contact-
|
|
678
|
+
path: "/contact-requests/:id",
|
|
190
679
|
nested: void 0
|
|
191
680
|
}
|
|
192
681
|
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = void 0;
|
|
4
|
+
const contact_requests_1 = require("../../../../modules/contact-requests");
|
|
5
|
+
const GET = async (req, res) => {
|
|
6
|
+
const { id } = req.params;
|
|
7
|
+
const service = req.scope.resolve(contact_requests_1.CONTACT_REQUEST_MODULE);
|
|
8
|
+
const request = await service.getRequest(id);
|
|
9
|
+
// Get next allowed statuses for the admin UI
|
|
10
|
+
const nextAllowedStatuses = service.getNextAllowedStatuses(request.status);
|
|
11
|
+
res.status(200).json({
|
|
12
|
+
request,
|
|
13
|
+
next_allowed_statuses: nextAllowedStatuses,
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
exports.GET = GET;
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2NvbnRhY3QtcmVxdWVzdHMvW2lkXS9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSwyRUFBNkU7QUFHdEUsTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ25FLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFBO0lBRXpCLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUMvQix5Q0FBc0IsQ0FDdkIsQ0FBQTtJQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUU1Qyw2Q0FBNkM7SUFDN0MsTUFBTSxtQkFBbUIsR0FBRyxPQUFPLENBQUMsc0JBQXNCLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBRTFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ25CLE9BQU87UUFDUCxxQkFBcUIsRUFBRSxtQkFBbUI7S0FDM0MsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFBO0FBaEJZLFFBQUEsR0FBRyxPQWdCZiJ9
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.POST = void 0;
|
|
7
|
+
const validators_1 = require("../../validators");
|
|
8
|
+
const update_contact_request_status_workflow_1 = __importDefault(require("../../../../../workflows/update-contact-request-status-workflow"));
|
|
9
|
+
const POST = async (req, res) => {
|
|
10
|
+
const { id } = req.params;
|
|
11
|
+
const body = validators_1.AdminUpdateContactRequestStatusSchema.parse(req.body ?? {});
|
|
12
|
+
const authContext = req.auth_context;
|
|
13
|
+
const actorId = authContext?.actor_id || authContext?.user_id || "admin";
|
|
14
|
+
const { result } = await (0, update_contact_request_status_workflow_1.default)(req.scope).run({
|
|
15
|
+
input: {
|
|
16
|
+
id,
|
|
17
|
+
status: body.status,
|
|
18
|
+
changed_by: actorId,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
res.status(200).json({ request: result.request });
|
|
22
|
+
};
|
|
23
|
+
exports.POST = POST;
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2NvbnRhY3QtcmVxdWVzdHMvW2lkXS9zdGF0dXMvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQ0EsaURBQXdFO0FBQ3hFLDZJQUFnSDtBQUV6RyxNQUFNLElBQUksR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDcEUsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUE7SUFDekIsTUFBTSxJQUFJLEdBQUcsa0RBQXFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUE7SUFFeEUsTUFBTSxXQUFXLEdBQUksR0FFbkIsQ0FBQyxZQUFZLENBQUE7SUFDZixNQUFNLE9BQU8sR0FBRyxXQUFXLEVBQUUsUUFBUSxJQUFJLFdBQVcsRUFBRSxPQUFPLElBQUksT0FBTyxDQUFBO0lBRXhFLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxNQUFNLElBQUEsZ0RBQWtDLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUN6RSxLQUFLLEVBQUU7WUFDTCxFQUFFO1lBQ0YsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLFVBQVUsRUFBRSxPQUFPO1NBQ3BCO0tBQ0YsQ0FBQyxDQUFBO0lBRUYsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7QUFDbkQsQ0FBQyxDQUFBO0FBbEJZLFFBQUEsSUFBSSxRQWtCaEIifQ==
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.POST = exports.GET = void 0;
|
|
7
|
+
const contact_requests_1 = require("../../../modules/contact-requests");
|
|
8
|
+
const validators_1 = require("./validators");
|
|
9
|
+
const create_contact_request_workflow_1 = __importDefault(require("../../../workflows/create-contact-request-workflow"));
|
|
10
|
+
const GET = async (req, res) => {
|
|
11
|
+
const query = validators_1.AdminListContactRequestsSchema.parse(req.query ?? {});
|
|
12
|
+
const service = req.scope.resolve(contact_requests_1.CONTACT_REQUEST_MODULE);
|
|
13
|
+
const selector = {};
|
|
14
|
+
if (query.email) {
|
|
15
|
+
selector.email = { $ilike: `%${query.email}%` };
|
|
16
|
+
}
|
|
17
|
+
if (query.status) {
|
|
18
|
+
selector.status = query.status;
|
|
19
|
+
}
|
|
20
|
+
if (query.source) {
|
|
21
|
+
selector.source = query.source;
|
|
22
|
+
}
|
|
23
|
+
if (query.created_at) {
|
|
24
|
+
selector.created_at = {};
|
|
25
|
+
if (query.created_at.gte) {
|
|
26
|
+
selector.created_at.$gte = new Date(query.created_at.gte);
|
|
27
|
+
}
|
|
28
|
+
if (query.created_at.lte) {
|
|
29
|
+
selector.created_at.$lte = new Date(query.created_at.lte);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const order = {};
|
|
33
|
+
if (query.order) {
|
|
34
|
+
order[query.order] = query.order_direction ?? "DESC";
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
order.created_at = query.order_direction ?? "DESC";
|
|
38
|
+
}
|
|
39
|
+
const [requests, count] = await service.listRequests(selector, {
|
|
40
|
+
take: query.limit,
|
|
41
|
+
skip: query.offset,
|
|
42
|
+
order,
|
|
43
|
+
});
|
|
44
|
+
res.status(200).json({
|
|
45
|
+
requests,
|
|
46
|
+
count,
|
|
47
|
+
offset: query.offset,
|
|
48
|
+
limit: query.limit,
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
exports.GET = GET;
|
|
52
|
+
const POST = async (req, res) => {
|
|
53
|
+
const body = validators_1.AdminCreateContactRequestSchema.parse(req.body ?? {});
|
|
54
|
+
const authContext = req.auth_context;
|
|
55
|
+
const actorId = authContext?.actor_id || authContext?.user_id || "admin";
|
|
56
|
+
const { result } = await (0, create_contact_request_workflow_1.default)(req.scope).run({
|
|
57
|
+
input: {
|
|
58
|
+
email: body.email,
|
|
59
|
+
payload: body.payload,
|
|
60
|
+
metadata: body.metadata,
|
|
61
|
+
source: body.source ?? "admin",
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
res.status(200).json({ request: result.request });
|
|
65
|
+
};
|
|
66
|
+
exports.POST = POST;
|
|
67
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2NvbnRhY3QtcmVxdWVzdHMvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQ0Esd0VBQTBFO0FBRTFFLDZDQUdxQjtBQUNyQix5SEFBNkY7QUFFdEYsTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ25FLE1BQU0sS0FBSyxHQUFHLDJDQUE4QixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFBO0lBQ25FLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUMvQix5Q0FBc0IsQ0FDdkIsQ0FBQTtJQUVELE1BQU0sUUFBUSxHQVFWLEVBQUUsQ0FBQTtJQUVOLElBQUksS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2hCLFFBQVEsQ0FBQyxLQUFLLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxLQUFLLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQTtJQUNqRCxDQUFDO0lBRUQsSUFBSSxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDakIsUUFBUSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFBO0lBQ2hDLENBQUM7SUFFRCxJQUFJLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNqQixRQUFRLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUE7SUFDaEMsQ0FBQztJQUVELElBQUksS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3JCLFFBQVEsQ0FBQyxVQUFVLEdBQUcsRUFBRSxDQUFBO1FBQ3hCLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUN6QixRQUFRLENBQUMsVUFBVSxDQUFDLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQzNELENBQUM7UUFDRCxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDekIsUUFBUSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQTtRQUMzRCxDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sS0FBSyxHQUEyQixFQUFFLENBQUE7SUFDeEMsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDaEIsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsZUFBZSxJQUFJLE1BQU0sQ0FBQTtJQUN0RCxDQUFDO1NBQU0sQ0FBQztRQUNOLEtBQUssQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLGVBQWUsSUFBSSxNQUFNLENBQUE7SUFDcEQsQ0FBQztJQUVELE1BQU0sQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRTtRQUM3RCxJQUFJLEVBQUUsS0FBSyxDQUFDLEtBQUs7UUFDakIsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNO1FBQ2xCLEtBQUs7S0FDTixDQUFDLENBQUE7SUFFRixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNuQixRQUFRO1FBQ1IsS0FBSztRQUNMLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtRQUNwQixLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUs7S0FDbkIsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFBO0FBekRZLFFBQUEsR0FBRyxPQXlEZjtBQUVNLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxNQUFNLElBQUksR0FBRyw0Q0FBK0IsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUVsRSxNQUFNLFdBQVcsR0FBSSxHQUVuQixDQUFDLFlBQVksQ0FBQTtJQUNmLE1BQU0sT0FBTyxHQUFHLFdBQVcsRUFBRSxRQUFRLElBQUksV0FBVyxFQUFFLE9BQU8sSUFBSSxPQUFPLENBQUE7SUFFeEUsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBQSx5Q0FBNEIsRUFBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQ25FLEtBQUssRUFBRTtZQUNMLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztZQUNqQixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDckIsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO1lBQ3ZCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxJQUFJLE9BQU87U0FDL0I7S0FDRixDQUFDLENBQUE7SUFFRixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQTtBQUNuRCxDQUFDLENBQUE7QUFsQlksUUFBQSxJQUFJLFFBa0JoQiJ9
|