medusa-contact-us 0.0.11 → 0.0.20
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 +4 -494
- package/.medusa/server/src/admin/index.mjs +6 -496
- package/.medusa/server/src/api/admin/contact-email-subscriptions/route.js +3 -3
- package/.medusa/server/src/api/admin/contact-requests/[id]/route.js +10 -34
- package/.medusa/server/src/api/admin/contact-requests/[id]/status/route.js +24 -0
- package/.medusa/server/src/api/admin/contact-requests/route.js +47 -11
- package/.medusa/server/src/api/admin/contact-requests/validators.js +22 -12
- package/.medusa/server/src/api/store/contact-email-subscriptions/route.js +3 -3
- package/.medusa/server/src/api/store/contact-email-subscriptions/validators.js +2 -2
- package/.medusa/server/src/api/store/contact-requests/route.js +4 -10
- package/.medusa/server/src/api/store/contact-requests/validators.js +4 -8
- package/.medusa/server/src/constants.js +10 -4
- package/.medusa/server/src/helpers/contact-request.js +52 -0
- package/.medusa/server/src/helpers/contact-subscription.js +15 -4
- package/.medusa/server/src/helpers/index.js +5 -4
- package/.medusa/server/src/index.js +16 -13
- package/.medusa/server/src/modules/contact-requests/index.js +4 -5
- package/.medusa/server/src/modules/contact-requests/migrations/Migration20241129163317.js +47 -0
- package/.medusa/server/src/modules/contact-requests/models/contact-request.js +4 -3
- package/.medusa/server/src/modules/contact-requests/service.js +191 -141
- package/.medusa/server/src/modules/contact-requests/utils/resolve-options.js +48 -0
- package/.medusa/server/src/modules/contact-subscriptions/index.js +4 -5
- package/.medusa/server/src/modules/contact-subscriptions/service.js +20 -12
- package/.medusa/server/src/types/contact-request.js +3 -0
- package/.medusa/server/src/types.js +1 -208
- package/.medusa/server/src/workflows/create-contact-request-workflow.js +13 -0
- package/.medusa/server/src/workflows/index.js +5 -5
- package/.medusa/server/src/workflows/steps/create-contact-request-step.js +3 -7
- 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 +7 -7
- package/.medusa/server/src/workflows/update-contact-request-status-workflow.js +33 -0
- package/README.md +329 -211
- package/package.json +2 -2
- package/.medusa/server/src/api/admin/contact-requests/[id]/comments/route.js +0 -22
- package/.medusa/server/src/api/admin/plugin/route.js +0 -11
- package/.medusa/server/src/api/store/plugin/route.js +0 -11
- package/.medusa/server/src/helpers/__tests__/submit-contact-request.test.js +0 -125
- package/.medusa/server/src/helpers/submit-contact-request.js +0 -45
- package/.medusa/server/src/modules/contact-requests/migrations/Migration20241124090000.js +0 -51
- package/.medusa/server/src/modules/contact-requests/models/contact-request-comment.js +0 -11
- package/.medusa/server/src/plugin-options.js +0 -16
- package/.medusa/server/src/types/__tests__/contact-options.test.js +0 -83
- package/.medusa/server/src/utils/__tests__/payload-validator.test.js +0 -81
- package/.medusa/server/src/utils/payload.js +0 -127
- package/.medusa/server/src/workflows/create-contact-request.js +0 -30
- package/.medusa/server/src/workflows/steps/send-contact-notification-step.js +0 -48
- package/.medusa/server/src/workflows/update-contact-request-status.js +0 -32
|
@@ -1,10 +1,9 @@
|
|
|
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
|
|
5
|
-
import { Envelope
|
|
6
|
-
|
|
7
|
-
const useDebounce$1 = (value, delay) => {
|
|
4
|
+
import { Container, Heading, Text, Button, Input, Badge } from "@medusajs/ui";
|
|
5
|
+
import { Envelope } from "@medusajs/icons";
|
|
6
|
+
const useDebounce = (value, delay) => {
|
|
8
7
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
9
8
|
useEffect(() => {
|
|
10
9
|
const handler = setTimeout(() => setDebouncedValue(value), delay);
|
|
@@ -27,7 +26,7 @@ const ContactEmailSubscriptionsPage = () => {
|
|
|
27
26
|
const [items, setItems] = useState([]);
|
|
28
27
|
const [statusFilter, setStatusFilter] = useState("all");
|
|
29
28
|
const [query, setQuery] = useState("");
|
|
30
|
-
const debouncedQuery = useDebounce
|
|
29
|
+
const debouncedQuery = useDebounce(query, 300);
|
|
31
30
|
const [isLoading, setIsLoading] = useState(true);
|
|
32
31
|
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
33
32
|
const [error, setError] = useState(null);
|
|
@@ -165,486 +164,11 @@ const ContactEmailSubscriptionsPage = () => {
|
|
|
165
164
|
) }) : null
|
|
166
165
|
] }) });
|
|
167
166
|
};
|
|
168
|
-
const config$1 = defineRouteConfig({
|
|
169
|
-
label: "Contact email list",
|
|
170
|
-
icon: Envelope
|
|
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 statusBadgeClass = (status) => {
|
|
181
|
-
if (status.includes("close") || status.includes("resolved")) {
|
|
182
|
-
return "bg-ui-tag-green-bg text-ui-tag-green-text";
|
|
183
|
-
}
|
|
184
|
-
if (status.includes("review") || status.includes("progress")) {
|
|
185
|
-
return "bg-ui-tag-orange-bg text-ui-tag-orange-text";
|
|
186
|
-
}
|
|
187
|
-
return "bg-ui-tag-neutral-bg text-ui-tag-neutral-text";
|
|
188
|
-
};
|
|
189
|
-
const ContactRequestsPage = () => {
|
|
190
|
-
const [requests, setRequests] = useState([]);
|
|
191
|
-
const [statuses, setStatuses] = useState([]);
|
|
192
|
-
const [statusFilter, setStatusFilter] = useState("all");
|
|
193
|
-
const [query, setQuery] = useState("");
|
|
194
|
-
const debouncedQuery = useDebounce(query, 300);
|
|
195
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
196
|
-
const [isFetchingMore, setIsFetchingMore] = useState(false);
|
|
197
|
-
const [error, setError] = useState(null);
|
|
198
|
-
const [offset, setOffset] = useState(0);
|
|
199
|
-
const [count, setCount] = useState(0);
|
|
200
|
-
const limit = 20;
|
|
201
|
-
const loadRequests = useCallback(
|
|
202
|
-
async (nextOffset, replace = false) => {
|
|
203
|
-
var _a;
|
|
204
|
-
try {
|
|
205
|
-
if (replace) {
|
|
206
|
-
setIsLoading(true);
|
|
207
|
-
} else {
|
|
208
|
-
setIsFetchingMore(true);
|
|
209
|
-
}
|
|
210
|
-
setError(null);
|
|
211
|
-
const params = new URLSearchParams();
|
|
212
|
-
params.set("limit", String(limit));
|
|
213
|
-
params.set("offset", String(nextOffset));
|
|
214
|
-
if (statusFilter !== "all") {
|
|
215
|
-
params.set("status", statusFilter);
|
|
216
|
-
}
|
|
217
|
-
if (debouncedQuery.trim()) {
|
|
218
|
-
params.set("q", debouncedQuery.trim());
|
|
219
|
-
}
|
|
220
|
-
const response = await fetch(
|
|
221
|
-
`/admin/contact-requests?${params.toString()}`,
|
|
222
|
-
{ credentials: "include" }
|
|
223
|
-
);
|
|
224
|
-
if (!response.ok) {
|
|
225
|
-
const message = await response.text();
|
|
226
|
-
throw new Error(message || "Unable to load contact requests");
|
|
227
|
-
}
|
|
228
|
-
const payload = await response.json();
|
|
229
|
-
setStatuses(payload.statuses ?? []);
|
|
230
|
-
setCount(payload.count ?? 0);
|
|
231
|
-
setOffset(nextOffset + (((_a = payload.contact_requests) == null ? void 0 : _a.length) ?? 0));
|
|
232
|
-
setRequests(
|
|
233
|
-
(prev) => replace ? payload.contact_requests ?? [] : [...prev, ...payload.contact_requests ?? []]
|
|
234
|
-
);
|
|
235
|
-
} catch (loadError) {
|
|
236
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load contact requests";
|
|
237
|
-
setError(message);
|
|
238
|
-
} finally {
|
|
239
|
-
setIsLoading(false);
|
|
240
|
-
setIsFetchingMore(false);
|
|
241
|
-
}
|
|
242
|
-
},
|
|
243
|
-
[statusFilter, debouncedQuery]
|
|
244
|
-
);
|
|
245
|
-
useEffect(() => {
|
|
246
|
-
void loadRequests(0, true);
|
|
247
|
-
}, [statusFilter, debouncedQuery, loadRequests]);
|
|
248
|
-
const hasMore = useMemo(() => offset < count, [offset, count]);
|
|
249
|
-
const displayedStatuses = useMemo(
|
|
250
|
-
() => [{ code: "all", label: "All statuses" }, ...statuses],
|
|
251
|
-
[statuses]
|
|
252
|
-
);
|
|
253
|
-
return /* @__PURE__ */ jsx("div", { className: "w-full p-6", children: /* @__PURE__ */ jsxs(Container, { className: "mx-auto flex w-full max-w-6xl flex-col gap-6 p-6", children: [
|
|
254
|
-
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between", children: [
|
|
255
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
256
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Contact Requests" }),
|
|
257
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Monitor inbound storefront messages and keep track of their statuses without leaving the admin." })
|
|
258
|
-
] }),
|
|
259
|
-
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: () => loadRequests(0, true), children: "Refresh" })
|
|
260
|
-
] }),
|
|
261
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
|
|
262
|
-
/* @__PURE__ */ jsx(
|
|
263
|
-
Input,
|
|
264
|
-
{
|
|
265
|
-
placeholder: "Search by email",
|
|
266
|
-
value: query,
|
|
267
|
-
onChange: (event) => setQuery(event.target.value),
|
|
268
|
-
className: "md:max-w-sm"
|
|
269
|
-
}
|
|
270
|
-
),
|
|
271
|
-
/* @__PURE__ */ jsx(
|
|
272
|
-
"select",
|
|
273
|
-
{
|
|
274
|
-
value: statusFilter,
|
|
275
|
-
onChange: (event) => setStatusFilter(event.target.value),
|
|
276
|
-
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",
|
|
277
|
-
children: displayedStatuses.map((status) => /* @__PURE__ */ jsx("option", { value: status.code, children: status.label }, status.code))
|
|
278
|
-
}
|
|
279
|
-
)
|
|
280
|
-
] }),
|
|
281
|
-
error ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-ui-border-strong p-6 text-center", children: [
|
|
282
|
-
/* @__PURE__ */ jsx(Text, { weight: "plus", className: "text-ui-fg-error", children: error }),
|
|
283
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => loadRequests(0, true), children: "Try again" }) })
|
|
284
|
-
] }) : null,
|
|
285
|
-
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-16", children: /* @__PURE__ */ jsx(Text, { children: "Loading contact requests..." }) }) : requests.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-dashed border-ui-border-strong p-10 text-center", children: [
|
|
286
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-xl", children: "No contact requests yet" }),
|
|
287
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2 text-ui-fg-subtle", children: "The contact form is ready. Share it with your customers and new requests will show up here." })
|
|
288
|
-
] }) : /* @__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: [
|
|
289
|
-
/* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
290
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Email" }),
|
|
291
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Status" }),
|
|
292
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Created" }),
|
|
293
|
-
/* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-right text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Details" })
|
|
294
|
-
] }) }),
|
|
295
|
-
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle", children: requests.map((request) => {
|
|
296
|
-
const statusOption = statuses.find(
|
|
297
|
-
(status) => status.code === request.status
|
|
298
|
-
);
|
|
299
|
-
return /* @__PURE__ */ jsxs("tr", { className: "hover:bg-ui-bg-subtle/60", children: [
|
|
300
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 font-medium text-ui-fg-base", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
301
|
-
/* @__PURE__ */ jsx("span", { children: request.email }),
|
|
302
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: request.id })
|
|
303
|
-
] }) }),
|
|
304
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(
|
|
305
|
-
Badge,
|
|
306
|
-
{
|
|
307
|
-
size: "2xsmall",
|
|
308
|
-
className: `uppercase ${statusBadgeClass(
|
|
309
|
-
request.status
|
|
310
|
-
)}`,
|
|
311
|
-
children: (statusOption == null ? void 0 : statusOption.label) ?? request.status
|
|
312
|
-
}
|
|
313
|
-
) }),
|
|
314
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-ui-fg-subtle", children: new Date(request.created_at).toLocaleString() }),
|
|
315
|
-
/* @__PURE__ */ jsx("td", { className: "px-4 py-4 text-right", children: /* @__PURE__ */ jsx(
|
|
316
|
-
Link,
|
|
317
|
-
{
|
|
318
|
-
to: `/contact-requests/${request.id}`,
|
|
319
|
-
className: "text-ui-fg-interactive underline",
|
|
320
|
-
children: "View"
|
|
321
|
-
}
|
|
322
|
-
) })
|
|
323
|
-
] }, request.id);
|
|
324
|
-
}) })
|
|
325
|
-
] }) }),
|
|
326
|
-
hasMore ? /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(
|
|
327
|
-
Button,
|
|
328
|
-
{
|
|
329
|
-
variant: "secondary",
|
|
330
|
-
isLoading: isFetchingMore,
|
|
331
|
-
onClick: () => loadRequests(offset, false),
|
|
332
|
-
children: "Load more"
|
|
333
|
-
}
|
|
334
|
-
) }) : null
|
|
335
|
-
] }) });
|
|
336
|
-
};
|
|
337
167
|
const config = defineRouteConfig({
|
|
338
|
-
label: "Contact
|
|
168
|
+
label: "Contact email list",
|
|
339
169
|
icon: Envelope
|
|
340
170
|
});
|
|
341
|
-
const
|
|
342
|
-
dateStyle: "medium",
|
|
343
|
-
timeStyle: "short"
|
|
344
|
-
});
|
|
345
|
-
const ContactRequestDetailPage = () => {
|
|
346
|
-
const { id } = useParams();
|
|
347
|
-
const navigate = useNavigate();
|
|
348
|
-
const [request, setRequest] = useState(null);
|
|
349
|
-
const [comments, setComments] = useState([]);
|
|
350
|
-
const [statusOptions, setStatusOptions] = useState([]);
|
|
351
|
-
const [transitions, setTransitions] = useState([]);
|
|
352
|
-
const [statusSelection, setStatusSelection] = useState("");
|
|
353
|
-
const [statusNote, setStatusNote] = useState("");
|
|
354
|
-
const [newComment, setNewComment] = useState("");
|
|
355
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
356
|
-
const [error, setError] = useState(null);
|
|
357
|
-
const [isUpdatingStatus, setIsUpdatingStatus] = useState(false);
|
|
358
|
-
const [isSavingComment, setIsSavingComment] = useState(false);
|
|
359
|
-
const loadDetail = useCallback(async () => {
|
|
360
|
-
if (!id) {
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
setIsLoading(true);
|
|
364
|
-
setError(null);
|
|
365
|
-
try {
|
|
366
|
-
const response = await fetch(`/admin/contact-requests/${id}`, {
|
|
367
|
-
credentials: "include"
|
|
368
|
-
});
|
|
369
|
-
if (!response.ok) {
|
|
370
|
-
const message = await response.text();
|
|
371
|
-
throw new Error(message || "Unable to load contact request");
|
|
372
|
-
}
|
|
373
|
-
const payload = await response.json();
|
|
374
|
-
setRequest(payload.contact_request);
|
|
375
|
-
setComments(payload.comments ?? []);
|
|
376
|
-
setStatusOptions(payload.statuses ?? []);
|
|
377
|
-
setTransitions(payload.transitions ?? []);
|
|
378
|
-
} catch (loadError) {
|
|
379
|
-
const message = loadError instanceof Error ? loadError.message : "Unable to load contact request";
|
|
380
|
-
setError(message);
|
|
381
|
-
} finally {
|
|
382
|
-
setIsLoading(false);
|
|
383
|
-
}
|
|
384
|
-
}, [id]);
|
|
385
|
-
useEffect(() => {
|
|
386
|
-
void loadDetail();
|
|
387
|
-
}, [loadDetail]);
|
|
388
|
-
useEffect(() => {
|
|
389
|
-
if (transitions.length) {
|
|
390
|
-
setStatusSelection(transitions[0]);
|
|
391
|
-
} else {
|
|
392
|
-
setStatusSelection("");
|
|
393
|
-
}
|
|
394
|
-
}, [transitions]);
|
|
395
|
-
const statusLabelMap = useMemo(() => {
|
|
396
|
-
const map = /* @__PURE__ */ new Map();
|
|
397
|
-
statusOptions.forEach((status) => map.set(status.code, status.label));
|
|
398
|
-
return map;
|
|
399
|
-
}, [statusOptions]);
|
|
400
|
-
const orderedHistory = useMemo(() => {
|
|
401
|
-
return [...(request == null ? void 0 : request.status_history) ?? []].sort(
|
|
402
|
-
(a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
|
|
403
|
-
);
|
|
404
|
-
}, [request == null ? void 0 : request.status_history]);
|
|
405
|
-
const handleStatusUpdate = useCallback(async () => {
|
|
406
|
-
if (!id || !statusSelection) {
|
|
407
|
-
toast.error("Select a status to continue");
|
|
408
|
-
return;
|
|
409
|
-
}
|
|
410
|
-
setIsUpdatingStatus(true);
|
|
411
|
-
try {
|
|
412
|
-
const response = await fetch(`/admin/contact-requests/${id}`, {
|
|
413
|
-
method: "PATCH",
|
|
414
|
-
credentials: "include",
|
|
415
|
-
headers: {
|
|
416
|
-
"Content-Type": "application/json"
|
|
417
|
-
},
|
|
418
|
-
body: JSON.stringify({
|
|
419
|
-
status: statusSelection,
|
|
420
|
-
note: statusNote || void 0
|
|
421
|
-
})
|
|
422
|
-
});
|
|
423
|
-
if (!response.ok) {
|
|
424
|
-
const message = await response.text();
|
|
425
|
-
throw new Error(message || "Unable to update status");
|
|
426
|
-
}
|
|
427
|
-
const payload = await response.json();
|
|
428
|
-
setRequest(payload.contact_request);
|
|
429
|
-
setTransitions(payload.transitions ?? []);
|
|
430
|
-
setStatusNote("");
|
|
431
|
-
toast.success("Status updated");
|
|
432
|
-
} catch (updateError) {
|
|
433
|
-
const message = updateError instanceof Error ? updateError.message : "Unable to update status";
|
|
434
|
-
toast.error(message);
|
|
435
|
-
} finally {
|
|
436
|
-
setIsUpdatingStatus(false);
|
|
437
|
-
}
|
|
438
|
-
}, [id, statusSelection, statusNote]);
|
|
439
|
-
const handleAddComment = useCallback(async () => {
|
|
440
|
-
if (!id) {
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
if (!newComment.trim()) {
|
|
444
|
-
toast.error("Comment cannot be empty");
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
setIsSavingComment(true);
|
|
448
|
-
try {
|
|
449
|
-
const response = await fetch(
|
|
450
|
-
`/admin/contact-requests/${id}/comments`,
|
|
451
|
-
{
|
|
452
|
-
method: "POST",
|
|
453
|
-
credentials: "include",
|
|
454
|
-
headers: {
|
|
455
|
-
"Content-Type": "application/json"
|
|
456
|
-
},
|
|
457
|
-
body: JSON.stringify({ comment: newComment })
|
|
458
|
-
}
|
|
459
|
-
);
|
|
460
|
-
if (!response.ok) {
|
|
461
|
-
const message = await response.text();
|
|
462
|
-
throw new Error(message || "Unable to add comment");
|
|
463
|
-
}
|
|
464
|
-
const payload = await response.json();
|
|
465
|
-
setComments((prev) => [payload.comment, ...prev]);
|
|
466
|
-
setNewComment("");
|
|
467
|
-
toast.success("Comment added");
|
|
468
|
-
} catch (commentError) {
|
|
469
|
-
const message = commentError instanceof Error ? commentError.message : "Unable to add comment";
|
|
470
|
-
toast.error(message);
|
|
471
|
-
} finally {
|
|
472
|
-
setIsSavingComment(false);
|
|
473
|
-
}
|
|
474
|
-
}, [id, newComment]);
|
|
475
|
-
if (isLoading) {
|
|
476
|
-
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-32", children: /* @__PURE__ */ jsx(Text, { children: "Loading contact request..." }) });
|
|
477
|
-
}
|
|
478
|
-
if (error || !request) {
|
|
479
|
-
return /* @__PURE__ */ jsxs(Container, { className: "mx-auto mt-12 max-w-3xl p-8 text-center", children: [
|
|
480
|
-
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "Unable to load request" }),
|
|
481
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-2 text-ui-fg-subtle", children: error ?? "Unknown error" }),
|
|
482
|
-
/* @__PURE__ */ jsx(
|
|
483
|
-
Button,
|
|
484
|
-
{
|
|
485
|
-
variant: "secondary",
|
|
486
|
-
className: "mt-6",
|
|
487
|
-
onClick: () => navigate("/contact-requests"),
|
|
488
|
-
children: "Back to list"
|
|
489
|
-
}
|
|
490
|
-
)
|
|
491
|
-
] });
|
|
492
|
-
}
|
|
493
|
-
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: [
|
|
494
|
-
/* @__PURE__ */ jsxs(
|
|
495
|
-
"button",
|
|
496
|
-
{
|
|
497
|
-
className: "flex w-fit items-center gap-2 text-ui-fg-interactive",
|
|
498
|
-
onClick: () => navigate("/contact-requests"),
|
|
499
|
-
children: [
|
|
500
|
-
/* @__PURE__ */ jsx(ArrowUturnLeft, { className: "h-4 w-4" }),
|
|
501
|
-
"Back to requests"
|
|
502
|
-
]
|
|
503
|
-
}
|
|
504
|
-
),
|
|
505
|
-
/* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-3", children: [
|
|
506
|
-
/* @__PURE__ */ jsx(Heading, { level: "h1", children: request.email }),
|
|
507
|
-
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
508
|
-
"Request ID ",
|
|
509
|
-
request.id
|
|
510
|
-
] })
|
|
511
|
-
] }),
|
|
512
|
-
/* @__PURE__ */ jsxs("section", { className: "grid gap-6 lg:grid-cols-3", children: [
|
|
513
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-5 lg:col-span-2", children: [
|
|
514
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-lg", children: "Submitted fields" }),
|
|
515
|
-
/* @__PURE__ */ jsx("dl", { className: "mt-4 grid gap-4", children: Object.entries(request.payload ?? {}).length === 0 ? /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No additional fields captured for this request." }) : Object.entries(request.payload ?? {}).map(([key, value]) => /* @__PURE__ */ jsxs(
|
|
516
|
-
"div",
|
|
517
|
-
{
|
|
518
|
-
className: "flex flex-col gap-1 rounded-lg bg-ui-bg-subtle p-3",
|
|
519
|
-
children: [
|
|
520
|
-
/* @__PURE__ */ jsx(Text, { className: "text-xs uppercase text-ui-fg-muted", children: key }),
|
|
521
|
-
/* @__PURE__ */ jsx(Text, { className: "font-medium text-ui-fg-base", children: typeof value === "object" ? JSON.stringify(value, null, 2) : String(value) })
|
|
522
|
-
]
|
|
523
|
-
},
|
|
524
|
-
key
|
|
525
|
-
)) })
|
|
526
|
-
] }),
|
|
527
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-5", children: [
|
|
528
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-lg", children: "Status" }),
|
|
529
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-col gap-3", children: [
|
|
530
|
-
/* @__PURE__ */ jsx(Badge, { className: "w-fit bg-ui-tag-neutral-bg text-ui-tag-neutral-text", children: statusLabelMap.get(request.status) ?? request.status }),
|
|
531
|
-
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
532
|
-
"Created ",
|
|
533
|
-
formatDateTime(request.created_at)
|
|
534
|
-
] }),
|
|
535
|
-
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
536
|
-
"Last updated ",
|
|
537
|
-
formatDateTime(request.updated_at)
|
|
538
|
-
] })
|
|
539
|
-
] }),
|
|
540
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-6 flex flex-col gap-3", children: [
|
|
541
|
-
/* @__PURE__ */ jsx("label", { className: "text-xs font-semibold uppercase tracking-wide text-ui-fg-muted", children: "Next status" }),
|
|
542
|
-
/* @__PURE__ */ jsxs(
|
|
543
|
-
"select",
|
|
544
|
-
{
|
|
545
|
-
value: statusSelection,
|
|
546
|
-
onChange: (event) => setStatusSelection(event.target.value),
|
|
547
|
-
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",
|
|
548
|
-
disabled: !transitions.length,
|
|
549
|
-
children: [
|
|
550
|
-
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: transitions.length ? "Select status" : "No further transitions" }),
|
|
551
|
-
transitions.map((status) => /* @__PURE__ */ jsx("option", { value: status, children: statusLabelMap.get(status) ?? status }, status))
|
|
552
|
-
]
|
|
553
|
-
}
|
|
554
|
-
),
|
|
555
|
-
/* @__PURE__ */ jsx(
|
|
556
|
-
Textarea,
|
|
557
|
-
{
|
|
558
|
-
rows: 3,
|
|
559
|
-
value: statusNote,
|
|
560
|
-
onChange: (event) => setStatusNote(event.target.value),
|
|
561
|
-
placeholder: "Optional note for history"
|
|
562
|
-
}
|
|
563
|
-
),
|
|
564
|
-
/* @__PURE__ */ jsx(
|
|
565
|
-
Button,
|
|
566
|
-
{
|
|
567
|
-
onClick: () => void handleStatusUpdate(),
|
|
568
|
-
disabled: !statusSelection,
|
|
569
|
-
isLoading: isUpdatingStatus,
|
|
570
|
-
children: "Update status"
|
|
571
|
-
}
|
|
572
|
-
)
|
|
573
|
-
] })
|
|
574
|
-
] })
|
|
575
|
-
] }),
|
|
576
|
-
/* @__PURE__ */ jsxs("section", { className: "grid gap-6 lg:grid-cols-3", children: [
|
|
577
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-5 lg:col-span-2", children: [
|
|
578
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-lg", children: "Status history" }),
|
|
579
|
-
/* @__PURE__ */ jsx("div", { className: "mt-4 flex flex-col gap-4", children: orderedHistory.map((entry) => /* @__PURE__ */ jsxs(
|
|
580
|
-
"div",
|
|
581
|
-
{
|
|
582
|
-
className: "rounded-lg border border-ui-border-subtle p-3",
|
|
583
|
-
children: [
|
|
584
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
585
|
-
/* @__PURE__ */ jsx(Text, { weight: "plus", children: statusLabelMap.get(entry.status) ?? entry.status }),
|
|
586
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: formatDateTime(entry.updated_at) })
|
|
587
|
-
] }),
|
|
588
|
-
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: entry.updated_by ? `By ${entry.updated_by}` : "System" }),
|
|
589
|
-
entry.note ? /* @__PURE__ */ jsx(Text, { size: "small", className: "mt-2", children: entry.note }) : null
|
|
590
|
-
]
|
|
591
|
-
},
|
|
592
|
-
`${entry.status}-${entry.updated_at}`
|
|
593
|
-
)) })
|
|
594
|
-
] }),
|
|
595
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-ui-border-base p-5", children: [
|
|
596
|
-
/* @__PURE__ */ jsx(Heading, { level: "h3", className: "text-lg", children: "Admin comments" }),
|
|
597
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-col gap-3", children: [
|
|
598
|
-
/* @__PURE__ */ jsx(
|
|
599
|
-
Textarea,
|
|
600
|
-
{
|
|
601
|
-
rows: 4,
|
|
602
|
-
placeholder: "Leave an internal note",
|
|
603
|
-
value: newComment,
|
|
604
|
-
onChange: (event) => setNewComment(event.target.value)
|
|
605
|
-
}
|
|
606
|
-
),
|
|
607
|
-
/* @__PURE__ */ jsx(
|
|
608
|
-
Button,
|
|
609
|
-
{
|
|
610
|
-
variant: "secondary",
|
|
611
|
-
onClick: () => void handleAddComment(),
|
|
612
|
-
isLoading: isSavingComment,
|
|
613
|
-
children: "Add comment"
|
|
614
|
-
}
|
|
615
|
-
)
|
|
616
|
-
] }),
|
|
617
|
-
/* @__PURE__ */ jsx("div", { className: "mt-6 flex flex-col gap-4", children: comments.length === 0 ? /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "No comments yet." }) : comments.map((comment) => /* @__PURE__ */ jsxs(
|
|
618
|
-
"div",
|
|
619
|
-
{
|
|
620
|
-
className: "rounded-lg bg-ui-bg-subtle p-3",
|
|
621
|
-
children: [
|
|
622
|
-
/* @__PURE__ */ jsxs(Text, { size: "small", className: "text-ui-fg-subtle", children: [
|
|
623
|
-
comment.actor_id ?? "Admin",
|
|
624
|
-
" •",
|
|
625
|
-
" ",
|
|
626
|
-
formatDateTime(comment.created_at)
|
|
627
|
-
] }),
|
|
628
|
-
/* @__PURE__ */ jsx(Text, { className: "mt-2", children: comment.comment })
|
|
629
|
-
]
|
|
630
|
-
},
|
|
631
|
-
comment.id
|
|
632
|
-
)) })
|
|
633
|
-
] })
|
|
634
|
-
] })
|
|
635
|
-
] }) });
|
|
636
|
-
};
|
|
637
|
-
defineRouteConfig({
|
|
638
|
-
parentRoute: "/contact-requests"
|
|
639
|
-
});
|
|
640
|
-
const en = {
|
|
641
|
-
"contact-requests.title": "Contact Requests",
|
|
642
|
-
"contact-requests.subtitle": "Monitor submissions and keep track of every response.",
|
|
643
|
-
"contact-requests.empty": "No contact requests yet.",
|
|
644
|
-
"contact-requests.detail.status": "Status",
|
|
645
|
-
"contact-requests.detail.history": "Status history",
|
|
646
|
-
"contact-requests.detail.comments": "Admin comments"
|
|
647
|
-
};
|
|
171
|
+
const en = {};
|
|
648
172
|
const i18nTranslations0 = {
|
|
649
173
|
en
|
|
650
174
|
};
|
|
@@ -654,14 +178,6 @@ const routeModule = {
|
|
|
654
178
|
{
|
|
655
179
|
Component: ContactEmailSubscriptionsPage,
|
|
656
180
|
path: "/contact-email-subscriptions"
|
|
657
|
-
},
|
|
658
|
-
{
|
|
659
|
-
Component: ContactRequestsPage,
|
|
660
|
-
path: "/contact-requests"
|
|
661
|
-
},
|
|
662
|
-
{
|
|
663
|
-
Component: ContactRequestDetailPage,
|
|
664
|
-
path: "/contact-requests/:id"
|
|
665
181
|
}
|
|
666
182
|
]
|
|
667
183
|
};
|
|
@@ -670,12 +186,6 @@ const menuItemModule = {
|
|
|
670
186
|
{
|
|
671
187
|
label: config.label,
|
|
672
188
|
icon: config.icon,
|
|
673
|
-
path: "/contact-requests",
|
|
674
|
-
nested: void 0
|
|
675
|
-
},
|
|
676
|
-
{
|
|
677
|
-
label: config$1.label,
|
|
678
|
-
icon: config$1.icon,
|
|
679
189
|
path: "/contact-email-subscriptions",
|
|
680
190
|
nested: void 0
|
|
681
191
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GET = void 0;
|
|
4
|
-
const
|
|
4
|
+
const contact_subscriptions_1 = require("../../../modules/contact-subscriptions");
|
|
5
5
|
const validators_1 = require("./validators");
|
|
6
6
|
const GET = async (req, res) => {
|
|
7
7
|
const query = validators_1.AdminListContactEmailSubscriptionsSchema.parse(req.query ?? {});
|
|
8
|
-
const service = req.scope.resolve(
|
|
8
|
+
const service = req.scope.resolve(contact_subscriptions_1.CONTACT_SUBSCRIPTION_MODULE);
|
|
9
9
|
const selector = {};
|
|
10
10
|
if (query.status) {
|
|
11
11
|
selector.status = query.status;
|
|
@@ -26,4 +26,4 @@ const GET = async (req, res) => {
|
|
|
26
26
|
});
|
|
27
27
|
};
|
|
28
28
|
exports.GET = GET;
|
|
29
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2NvbnRhY3QtZW1haWwtc3Vic2NyaXB0aW9ucy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxrRkFBb0Y7QUFFcEYsNkNBQXVFO0FBRWhFLE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNuRSxNQUFNLEtBQUssR0FBRyxxREFBd0MsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUM3RSxNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FDL0IsbURBQTJCLENBQzVCLENBQUE7SUFFRCxNQUFNLFFBQVEsR0FBNEIsRUFBRSxDQUFBO0lBRTVDLElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2pCLFFBQVEsQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQTtJQUNoQyxDQUFDO0lBQ0QsSUFBSSxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDWixRQUFRLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUE7SUFDL0MsQ0FBQztJQUVELE1BQU0sQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRTtRQUNyRSxJQUFJLEVBQUUsS0FBSyxDQUFDLEtBQUs7UUFDakIsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNO1FBQ2xCLEtBQUssRUFBRSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUU7S0FDOUIsQ0FBQyxDQUFBO0lBRUYsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDbkIsYUFBYTtRQUNiLEtBQUs7UUFDTCxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07UUFDcEIsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLO0tBQ25CLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQTtBQTNCWSxRQUFBLEdBQUcsT0EyQmYifQ==
|
|
@@ -1,41 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
const
|
|
8
|
-
const update_contact_request_status_1 = __importDefault(require("../../../../workflows/update-contact-request-status"));
|
|
9
|
-
const validators_1 = require("../validators");
|
|
3
|
+
exports.GET = void 0;
|
|
4
|
+
const contact_requests_1 = require("../../../../modules/contact-requests");
|
|
10
5
|
const GET = async (req, res) => {
|
|
11
|
-
const
|
|
12
|
-
const
|
|
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);
|
|
13
11
|
res.status(200).json({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
statuses: service.getStatusOptions(),
|
|
17
|
-
transitions: service.getNextStatuses(request.status),
|
|
12
|
+
request,
|
|
13
|
+
next_allowed_statuses: nextAllowedStatuses,
|
|
18
14
|
});
|
|
19
15
|
};
|
|
20
16
|
exports.GET = GET;
|
|
21
|
-
|
|
22
|
-
const body = validators_1.AdminUpdateContactStatusSchema.parse(req.body ?? {});
|
|
23
|
-
const actorId = req.auth_context?.actor_id ||
|
|
24
|
-
req.auth_context?.user_id ||
|
|
25
|
-
"admin";
|
|
26
|
-
const { result } = await (0, update_contact_request_status_1.default)(req.scope).run({
|
|
27
|
-
input: {
|
|
28
|
-
request_id: req.params.id,
|
|
29
|
-
status: body.status,
|
|
30
|
-
note: body.note,
|
|
31
|
-
actor_id: actorId,
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
const service = req.scope.resolve(constants_1.CONTACT_REQUEST_MODULE);
|
|
35
|
-
res.status(200).json({
|
|
36
|
-
contact_request: result.request,
|
|
37
|
-
transitions: service.getNextStatuses(result.request.status),
|
|
38
|
-
});
|
|
39
|
-
};
|
|
40
|
-
exports.PATCH = PATCH;
|
|
41
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2NvbnRhY3QtcmVxdWVzdHMvW2lkXS9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQSxxREFBOEQ7QUFFOUQsd0hBQW9HO0FBQ3BHLDhDQUE4RDtBQUV2RCxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDbkUsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQy9CLGtDQUFzQixDQUN2QixDQUFBO0lBQ0QsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsR0FBRyxNQUFNLE9BQU8sQ0FBQyxvQkFBb0IsQ0FDOUQsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQ2QsQ0FBQTtJQUVELEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ25CLGVBQWUsRUFBRSxPQUFPO1FBQ3hCLFFBQVE7UUFDUixRQUFRLEVBQUUsT0FBTyxDQUFDLGdCQUFnQixFQUFFO1FBQ3BDLFdBQVcsRUFBRSxPQUFPLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7S0FDckQsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFBO0FBZFksUUFBQSxHQUFHLE9BY2Y7QUFFTSxNQUFNLEtBQUssR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDckUsTUFBTSxJQUFJLEdBQUcsMkNBQThCLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUE7SUFDakUsTUFBTSxPQUFPLEdBQ1YsR0FBVyxDQUFDLFlBQVksRUFBRSxRQUFRO1FBQ2xDLEdBQVcsQ0FBQyxZQUFZLEVBQUUsT0FBTztRQUNsQyxPQUFPLENBQUE7SUFFVCxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxJQUFBLHVDQUFrQyxFQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDekUsS0FBSyxFQUFFO1lBQ0wsVUFBVSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUN6QixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbkIsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO1lBQ2YsUUFBUSxFQUFFLE9BQU87U0FDbEI7S0FDRixDQUFDLENBQUE7SUFFRixNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FDL0Isa0NBQXNCLENBQ3ZCLENBQUE7SUFFRCxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNuQixlQUFlLEVBQUUsTUFBTSxDQUFDLE9BQU87UUFDL0IsV0FBVyxFQUFFLE9BQU8sQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7S0FDNUQsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFBO0FBeEJZLFFBQUEsS0FBSyxTQXdCakIifQ==
|
|
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==
|