medusa-plugin-complaints 0.2.0 → 0.2.1
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/medusa-config.js +3 -3
- package/.medusa/server/src/admin/index.js +260 -260
- package/.medusa/server/src/admin/index.mjs +262 -262
- package/.medusa/server/src/modules/complaint/models/complaint-activity.d.ts +2 -2
- package/.medusa/server/src/modules/complaint/models/complaint-tag.d.ts +2 -2
- package/.medusa/server/src/modules/complaint/models/complaint.d.ts +2 -2
- package/.medusa/server/src/modules/complaint/service.d.ts +49 -12
- package/package.json +13 -13
|
@@ -10,8 +10,8 @@ module.exports = (0, utils_1.defineConfig)({
|
|
|
10
10
|
storeCors: process.env.STORE_CORS || 'http://localhost:5173',
|
|
11
11
|
adminCors: process.env.ADMIN_CORS || 'http://localhost:5173,http://localhost:9000',
|
|
12
12
|
authCors: process.env.AUTH_CORS || 'http://localhost:5173,http://localhost:9000',
|
|
13
|
-
jwtSecret: process.env.JWT_SECRET
|
|
14
|
-
cookieSecret: process.env.COOKIE_SECRET
|
|
13
|
+
jwtSecret: process.env.JWT_SECRET,
|
|
14
|
+
cookieSecret: process.env.COOKIE_SECRET
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
modules: [
|
|
@@ -20,4 +20,4 @@ module.exports = (0, utils_1.defineConfig)({
|
|
|
20
20
|
}
|
|
21
21
|
]
|
|
22
22
|
});
|
|
23
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVkdXNhLWNvbmZpZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL21lZHVzYS1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFBaUU7QUFFakUsSUFBQSxlQUFPLEVBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLElBQUksYUFBYSxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFBO0FBRTdELE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBQSxvQkFBWSxFQUFDO0lBQzdCLGFBQWEsRUFBRTtRQUNkLFFBQVEsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVM7UUFDL0IsV0FBVyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWTtRQUNyQyxJQUFJLEVBQUU7WUFDTCxTQUFTLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksdUJBQXVCO1lBQzVELFNBQVMsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSw2Q0FBNkM7WUFDbEYsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxJQUFJLDZDQUE2QztZQUNoRixTQUFTLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVO1lBQ2pDLFlBQVksRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWE7U0FDdkM7S0FDRDtJQUNELE9BQU8sRUFBRTtRQUNSO1lBQ0MsT0FBTyxFQUFFLHlCQUF5QjtTQUNsQztLQUNEO0NBQ0QsQ0FBQyxDQUFBIn0=
|
|
@@ -6499,6 +6499,258 @@ const ComplaintStatsPage = () => {
|
|
|
6499
6499
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-8", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: () => mutate(void 0, { onSuccess: () => ui.toast.success("Complaint stats updated successfully"), onError: () => ui.toast.error("Failed to update complaint stats") }), isLoading: isPending, children: "Recalculate Complaint Stats" }) })
|
|
6500
6500
|
] });
|
|
6501
6501
|
};
|
|
6502
|
+
const schema$3 = object({
|
|
6503
|
+
description: string().min(1, "Required"),
|
|
6504
|
+
customer_id: string().min(1, "Required"),
|
|
6505
|
+
order_id: string().min(1, "Required"),
|
|
6506
|
+
product_id: string().min(1, "Required"),
|
|
6507
|
+
tag_ids: array(string()).optional()
|
|
6508
|
+
});
|
|
6509
|
+
const CreateComplaintModal = ({
|
|
6510
|
+
open,
|
|
6511
|
+
setOpen,
|
|
6512
|
+
customerId,
|
|
6513
|
+
orderId
|
|
6514
|
+
}) => {
|
|
6515
|
+
var _a2, _b;
|
|
6516
|
+
const navigate = reactRouterDom.useNavigate();
|
|
6517
|
+
const { mutate: createComplaint, isPending } = useCreateComplaint();
|
|
6518
|
+
const prompt = ui.usePrompt();
|
|
6519
|
+
const form = useForm({
|
|
6520
|
+
resolver: t(schema$3),
|
|
6521
|
+
defaultValues: {
|
|
6522
|
+
description: "",
|
|
6523
|
+
customer_id: customerId,
|
|
6524
|
+
order_id: orderId ?? "",
|
|
6525
|
+
product_id: "",
|
|
6526
|
+
tag_ids: []
|
|
6527
|
+
}
|
|
6528
|
+
});
|
|
6529
|
+
const { formState } = form;
|
|
6530
|
+
const { isDirty } = formState;
|
|
6531
|
+
const selectedOrderId = useWatch({ control: form.control, name: "order_id" });
|
|
6532
|
+
const { data: customerData, isLoading: customerLoading } = useCustomerWithOrders(customerId);
|
|
6533
|
+
const customerOrders = (customerData == null ? void 0 : customerData.customer.orders) ?? [];
|
|
6534
|
+
const { data: orderData, isLoading: orderLoading } = useOrder(selectedOrderId);
|
|
6535
|
+
const orderProducts = Object.values(
|
|
6536
|
+
(((_a2 = orderData == null ? void 0 : orderData.order) == null ? void 0 : _a2.items) ?? []).reduce(
|
|
6537
|
+
(acc, item) => {
|
|
6538
|
+
if (item.product_id && !acc[item.product_id]) {
|
|
6539
|
+
acc[item.product_id] = { id: item.product_id, title: item.product_title ?? "" };
|
|
6540
|
+
}
|
|
6541
|
+
return acc;
|
|
6542
|
+
},
|
|
6543
|
+
{}
|
|
6544
|
+
)
|
|
6545
|
+
);
|
|
6546
|
+
const { data: tagsData } = useComplaintTags();
|
|
6547
|
+
const [selectedTagIds, setSelectedTagIds] = React.useState([]);
|
|
6548
|
+
const [tagSelectValue, setTagSelectValue] = React.useState("");
|
|
6549
|
+
const [success, setSuccess] = React.useState(false);
|
|
6550
|
+
let blocker = reactRouterDom.useBlocker(
|
|
6551
|
+
({ currentLocation, nextLocation }) => isDirty && formState.dirtyFields.description === true && currentLocation.pathname !== nextLocation.pathname
|
|
6552
|
+
);
|
|
6553
|
+
const handleNavigate = async () => {
|
|
6554
|
+
if (blocker.state !== "blocked") return;
|
|
6555
|
+
if (success) {
|
|
6556
|
+
blocker.proceed();
|
|
6557
|
+
return;
|
|
6558
|
+
}
|
|
6559
|
+
const confirmed = await prompt({
|
|
6560
|
+
title: "Are you sure you want to leave this form?",
|
|
6561
|
+
description: "You have unsaved changes that will be lost if you exit this form.",
|
|
6562
|
+
confirmText: "Continue",
|
|
6563
|
+
cancelText: "Cancel",
|
|
6564
|
+
variant: "confirmation"
|
|
6565
|
+
});
|
|
6566
|
+
if (confirmed) {
|
|
6567
|
+
blocker.proceed();
|
|
6568
|
+
} else {
|
|
6569
|
+
blocker.reset();
|
|
6570
|
+
}
|
|
6571
|
+
};
|
|
6572
|
+
React.useEffect(() => {
|
|
6573
|
+
if (blocker.state === "blocked") {
|
|
6574
|
+
handleNavigate();
|
|
6575
|
+
}
|
|
6576
|
+
}, [isDirty, open, blocker]);
|
|
6577
|
+
const handleSubmit = form.handleSubmit((data) => {
|
|
6578
|
+
createComplaint(data, {
|
|
6579
|
+
onSuccess: (result) => {
|
|
6580
|
+
ui.toast.success("Complaint created successfully");
|
|
6581
|
+
setSuccess(true);
|
|
6582
|
+
form.reset();
|
|
6583
|
+
navigate(`/complaints/${result.complaint.id}`);
|
|
6584
|
+
},
|
|
6585
|
+
onError: () => ui.toast.error("Failed to create complaint")
|
|
6586
|
+
});
|
|
6587
|
+
});
|
|
6588
|
+
if (!customerId) {
|
|
6589
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal, { open, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.FocusModal.Content, { children: [
|
|
6590
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Error" }) }),
|
|
6591
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Customer ID is required to create a complaint." }) })
|
|
6592
|
+
] }) });
|
|
6593
|
+
}
|
|
6594
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(FormProvider, { ...form, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "flex h-full flex-col overflow-hidden", children: [
|
|
6595
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
6596
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
|
|
6597
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "submit", size: "small", isLoading: isPending, children: "Save" })
|
|
6598
|
+
] }) }),
|
|
6599
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Body, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16", children: [
|
|
6600
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { className: "capitalize", children: "Create Complaint" }) }),
|
|
6601
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4", children: [
|
|
6602
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6603
|
+
Controller,
|
|
6604
|
+
{
|
|
6605
|
+
control: form.control,
|
|
6606
|
+
name: "customer_id",
|
|
6607
|
+
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [
|
|
6608
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Customer ID" }),
|
|
6609
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field, disabled: true })
|
|
6610
|
+
] })
|
|
6611
|
+
}
|
|
6612
|
+
),
|
|
6613
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6614
|
+
Controller,
|
|
6615
|
+
{
|
|
6616
|
+
control: form.control,
|
|
6617
|
+
name: "order_id",
|
|
6618
|
+
rules: { required: "Order is required" },
|
|
6619
|
+
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [
|
|
6620
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", weight: "plus", children: [
|
|
6621
|
+
"Order ",
|
|
6622
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
|
|
6623
|
+
] }),
|
|
6624
|
+
customerLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Loading orders..." }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6625
|
+
ui.Select,
|
|
6626
|
+
{
|
|
6627
|
+
value: field.value,
|
|
6628
|
+
onValueChange: (value) => {
|
|
6629
|
+
field.onChange(value);
|
|
6630
|
+
form.setValue("product_id", "");
|
|
6631
|
+
},
|
|
6632
|
+
children: [
|
|
6633
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Select an order from this customer" }) }),
|
|
6634
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: customerOrders.map((order) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Item, { value: order.id, children: [
|
|
6635
|
+
new Date(order.created_at).toLocaleString(
|
|
6636
|
+
"en-US",
|
|
6637
|
+
{
|
|
6638
|
+
year: "numeric",
|
|
6639
|
+
month: "short",
|
|
6640
|
+
day: "numeric"
|
|
6641
|
+
}
|
|
6642
|
+
),
|
|
6643
|
+
" ",
|
|
6644
|
+
"- #",
|
|
6645
|
+
order.display_id
|
|
6646
|
+
] }, order.id)) })
|
|
6647
|
+
]
|
|
6648
|
+
}
|
|
6649
|
+
)
|
|
6650
|
+
] })
|
|
6651
|
+
}
|
|
6652
|
+
),
|
|
6653
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6654
|
+
Controller,
|
|
6655
|
+
{
|
|
6656
|
+
control: form.control,
|
|
6657
|
+
name: "product_id",
|
|
6658
|
+
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [
|
|
6659
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Product" }),
|
|
6660
|
+
orderLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Loading..." }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6661
|
+
ui.Select,
|
|
6662
|
+
{
|
|
6663
|
+
value: field.value,
|
|
6664
|
+
onValueChange: field.onChange,
|
|
6665
|
+
children: [
|
|
6666
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Select a product" }) }),
|
|
6667
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: orderProducts == null ? void 0 : orderProducts.map((product) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: product.id, children: product.title }, product.id)) })
|
|
6668
|
+
]
|
|
6669
|
+
}
|
|
6670
|
+
)
|
|
6671
|
+
] })
|
|
6672
|
+
}
|
|
6673
|
+
),
|
|
6674
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [
|
|
6675
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Tags" }),
|
|
6676
|
+
selectedTagIds.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2 mb-2", children: selectedTagIds.map((tagId) => {
|
|
6677
|
+
var _a3;
|
|
6678
|
+
const tag = (_a3 = tagsData == null ? void 0 : tagsData.complaint_tags) == null ? void 0 : _a3.find(
|
|
6679
|
+
(t2) => t2.id === tagId
|
|
6680
|
+
);
|
|
6681
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
6682
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "xsmall", color: "blue", children: (tag == null ? void 0 : tag.value) ?? tagId }),
|
|
6683
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6684
|
+
"button",
|
|
6685
|
+
{
|
|
6686
|
+
type: "button",
|
|
6687
|
+
onClick: () => setSelectedTagIds(
|
|
6688
|
+
(prev) => prev.filter((id) => id !== tagId)
|
|
6689
|
+
),
|
|
6690
|
+
className: "text-ui-fg-subtle hover:text-ui-fg-base text-xs",
|
|
6691
|
+
"aria-label": `Remove tag ${tag == null ? void 0 : tag.value}`,
|
|
6692
|
+
children: "✕"
|
|
6693
|
+
}
|
|
6694
|
+
)
|
|
6695
|
+
] }, tagId);
|
|
6696
|
+
}) }),
|
|
6697
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6698
|
+
ui.Select,
|
|
6699
|
+
{
|
|
6700
|
+
value: tagSelectValue,
|
|
6701
|
+
onValueChange: (value) => {
|
|
6702
|
+
if (value && !selectedTagIds.includes(value)) {
|
|
6703
|
+
setSelectedTagIds((prev) => [...prev, value]);
|
|
6704
|
+
}
|
|
6705
|
+
form.setValue("tag_ids", [...selectedTagIds, value], {
|
|
6706
|
+
shouldDirty: true
|
|
6707
|
+
});
|
|
6708
|
+
setTagSelectValue("");
|
|
6709
|
+
},
|
|
6710
|
+
children: [
|
|
6711
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Add a tag..." }) }),
|
|
6712
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: (_b = tagsData == null ? void 0 : tagsData.complaint_tags) == null ? void 0 : _b.filter((tag) => !selectedTagIds.includes(tag.id)).map((tag) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: tag.id, children: tag.value }, tag.id)) })
|
|
6713
|
+
]
|
|
6714
|
+
}
|
|
6715
|
+
)
|
|
6716
|
+
] }),
|
|
6717
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6718
|
+
Controller,
|
|
6719
|
+
{
|
|
6720
|
+
control: form.control,
|
|
6721
|
+
name: "description",
|
|
6722
|
+
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [
|
|
6723
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Description" }),
|
|
6724
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Textarea, { ...field })
|
|
6725
|
+
] })
|
|
6726
|
+
}
|
|
6727
|
+
)
|
|
6728
|
+
] })
|
|
6729
|
+
] }) }) })
|
|
6730
|
+
] }) }) }) });
|
|
6731
|
+
};
|
|
6732
|
+
const CreateComplaintPage = () => {
|
|
6733
|
+
const [searchParams] = reactRouterDom.useSearchParams();
|
|
6734
|
+
const navigate = reactRouterDom.useNavigate();
|
|
6735
|
+
const customerId = searchParams.get("customer_id") ?? "";
|
|
6736
|
+
const orderId = searchParams.get("order_id") ?? "";
|
|
6737
|
+
const [createOpen, setCreateOpen] = React.useState(true);
|
|
6738
|
+
const handleOpenChange = (open) => {
|
|
6739
|
+
setCreateOpen(open);
|
|
6740
|
+
if (!open) {
|
|
6741
|
+
navigate("/complaints", { replace: true });
|
|
6742
|
+
}
|
|
6743
|
+
};
|
|
6744
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6745
|
+
CreateComplaintModal,
|
|
6746
|
+
{
|
|
6747
|
+
customerId,
|
|
6748
|
+
orderId,
|
|
6749
|
+
open: createOpen,
|
|
6750
|
+
setOpen: handleOpenChange
|
|
6751
|
+
}
|
|
6752
|
+
);
|
|
6753
|
+
};
|
|
6502
6754
|
const ActionMenu = ({ groups }) => {
|
|
6503
6755
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.DropdownMenu, { children: [
|
|
6504
6756
|
/* @__PURE__ */ jsxRuntime.jsx(ui.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { size: "small", variant: "transparent", children: /* @__PURE__ */ jsxRuntime.jsx(icons.EllipsisHorizontal, {}) }) }),
|
|
@@ -8211,7 +8463,7 @@ const useDate = () => {
|
|
|
8211
8463
|
getRelativeDate
|
|
8212
8464
|
};
|
|
8213
8465
|
};
|
|
8214
|
-
const schema$
|
|
8466
|
+
const schema$2 = object({
|
|
8215
8467
|
note: string().min(1, "Required")
|
|
8216
8468
|
});
|
|
8217
8469
|
const ComplaintNoteModal = ({
|
|
@@ -8224,7 +8476,7 @@ const ComplaintNoteModal = ({
|
|
|
8224
8476
|
const { mutate: updateNote } = useUpdateNote(complaintId, note == null ? void 0 : note.id);
|
|
8225
8477
|
const prompt = ui.usePrompt();
|
|
8226
8478
|
const form = useForm({
|
|
8227
|
-
resolver: t(schema$
|
|
8479
|
+
resolver: t(schema$2),
|
|
8228
8480
|
defaultValues: {
|
|
8229
8481
|
note: (note == null ? void 0 : note.note) || ""
|
|
8230
8482
|
}
|
|
@@ -8416,7 +8668,7 @@ const ComplaintActivity = ({ complaint }) => {
|
|
|
8416
8668
|
)
|
|
8417
8669
|
] });
|
|
8418
8670
|
};
|
|
8419
|
-
const schema$
|
|
8671
|
+
const schema$1 = object({
|
|
8420
8672
|
order_id: string().min(1, "Required"),
|
|
8421
8673
|
product_id: string().min(1, "Required"),
|
|
8422
8674
|
number: number(),
|
|
@@ -8430,7 +8682,7 @@ const EditComplaintDrawer = ({ complaint, open, setOpen }) => {
|
|
|
8430
8682
|
const updateMutation = useUpdateComplaint(complaint.id);
|
|
8431
8683
|
const prompt = ui.usePrompt();
|
|
8432
8684
|
const form = useForm({
|
|
8433
|
-
resolver: t(schema$
|
|
8685
|
+
resolver: t(schema$1),
|
|
8434
8686
|
defaultValues: {
|
|
8435
8687
|
number: 0,
|
|
8436
8688
|
status: "open",
|
|
@@ -8728,258 +8980,6 @@ const ComplaintDetailPage = () => {
|
|
|
8728
8980
|
/* @__PURE__ */ jsxRuntime.jsx(EditComplaintDrawer, { complaint, open: editOpen, setOpen: setEditOpen })
|
|
8729
8981
|
] });
|
|
8730
8982
|
};
|
|
8731
|
-
const schema$1 = object({
|
|
8732
|
-
description: string().min(1, "Required"),
|
|
8733
|
-
customer_id: string().min(1, "Required"),
|
|
8734
|
-
order_id: string().min(1, "Required"),
|
|
8735
|
-
product_id: string().min(1, "Required"),
|
|
8736
|
-
tag_ids: array(string()).optional()
|
|
8737
|
-
});
|
|
8738
|
-
const CreateComplaintModal = ({
|
|
8739
|
-
open,
|
|
8740
|
-
setOpen,
|
|
8741
|
-
customerId,
|
|
8742
|
-
orderId
|
|
8743
|
-
}) => {
|
|
8744
|
-
var _a2, _b;
|
|
8745
|
-
const navigate = reactRouterDom.useNavigate();
|
|
8746
|
-
const { mutate: createComplaint, isPending } = useCreateComplaint();
|
|
8747
|
-
const prompt = ui.usePrompt();
|
|
8748
|
-
const form = useForm({
|
|
8749
|
-
resolver: t(schema$1),
|
|
8750
|
-
defaultValues: {
|
|
8751
|
-
description: "",
|
|
8752
|
-
customer_id: customerId,
|
|
8753
|
-
order_id: orderId ?? "",
|
|
8754
|
-
product_id: "",
|
|
8755
|
-
tag_ids: []
|
|
8756
|
-
}
|
|
8757
|
-
});
|
|
8758
|
-
const { formState } = form;
|
|
8759
|
-
const { isDirty } = formState;
|
|
8760
|
-
const selectedOrderId = useWatch({ control: form.control, name: "order_id" });
|
|
8761
|
-
const { data: customerData, isLoading: customerLoading } = useCustomerWithOrders(customerId);
|
|
8762
|
-
const customerOrders = (customerData == null ? void 0 : customerData.customer.orders) ?? [];
|
|
8763
|
-
const { data: orderData, isLoading: orderLoading } = useOrder(selectedOrderId);
|
|
8764
|
-
const orderProducts = Object.values(
|
|
8765
|
-
(((_a2 = orderData == null ? void 0 : orderData.order) == null ? void 0 : _a2.items) ?? []).reduce(
|
|
8766
|
-
(acc, item) => {
|
|
8767
|
-
if (item.product_id && !acc[item.product_id]) {
|
|
8768
|
-
acc[item.product_id] = { id: item.product_id, title: item.product_title ?? "" };
|
|
8769
|
-
}
|
|
8770
|
-
return acc;
|
|
8771
|
-
},
|
|
8772
|
-
{}
|
|
8773
|
-
)
|
|
8774
|
-
);
|
|
8775
|
-
const { data: tagsData } = useComplaintTags();
|
|
8776
|
-
const [selectedTagIds, setSelectedTagIds] = React.useState([]);
|
|
8777
|
-
const [tagSelectValue, setTagSelectValue] = React.useState("");
|
|
8778
|
-
const [success, setSuccess] = React.useState(false);
|
|
8779
|
-
let blocker = reactRouterDom.useBlocker(
|
|
8780
|
-
({ currentLocation, nextLocation }) => isDirty && formState.dirtyFields.description === true && currentLocation.pathname !== nextLocation.pathname
|
|
8781
|
-
);
|
|
8782
|
-
const handleNavigate = async () => {
|
|
8783
|
-
if (blocker.state !== "blocked") return;
|
|
8784
|
-
if (success) {
|
|
8785
|
-
blocker.proceed();
|
|
8786
|
-
return;
|
|
8787
|
-
}
|
|
8788
|
-
const confirmed = await prompt({
|
|
8789
|
-
title: "Are you sure you want to leave this form?",
|
|
8790
|
-
description: "You have unsaved changes that will be lost if you exit this form.",
|
|
8791
|
-
confirmText: "Continue",
|
|
8792
|
-
cancelText: "Cancel",
|
|
8793
|
-
variant: "confirmation"
|
|
8794
|
-
});
|
|
8795
|
-
if (confirmed) {
|
|
8796
|
-
blocker.proceed();
|
|
8797
|
-
} else {
|
|
8798
|
-
blocker.reset();
|
|
8799
|
-
}
|
|
8800
|
-
};
|
|
8801
|
-
React.useEffect(() => {
|
|
8802
|
-
if (blocker.state === "blocked") {
|
|
8803
|
-
handleNavigate();
|
|
8804
|
-
}
|
|
8805
|
-
}, [isDirty, open, blocker]);
|
|
8806
|
-
const handleSubmit = form.handleSubmit((data) => {
|
|
8807
|
-
createComplaint(data, {
|
|
8808
|
-
onSuccess: (result) => {
|
|
8809
|
-
ui.toast.success("Complaint created successfully");
|
|
8810
|
-
setSuccess(true);
|
|
8811
|
-
form.reset();
|
|
8812
|
-
navigate(`/complaints/${result.complaint.id}`);
|
|
8813
|
-
},
|
|
8814
|
-
onError: () => ui.toast.error("Failed to create complaint")
|
|
8815
|
-
});
|
|
8816
|
-
});
|
|
8817
|
-
if (!customerId) {
|
|
8818
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal, { open, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.FocusModal.Content, { children: [
|
|
8819
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Error" }) }),
|
|
8820
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "Customer ID is required to create a complaint." }) })
|
|
8821
|
-
] }) });
|
|
8822
|
-
}
|
|
8823
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(FormProvider, { ...form, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "flex h-full flex-col overflow-hidden", children: [
|
|
8824
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
8825
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", children: "Cancel" }) }),
|
|
8826
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "submit", size: "small", isLoading: isPending, children: "Save" })
|
|
8827
|
-
] }) }),
|
|
8828
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.FocusModal.Body, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 flex-col items-center overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[720px] flex-col gap-y-8 px-2 py-16", children: [
|
|
8829
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { className: "capitalize", children: "Create Complaint" }) }),
|
|
8830
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4", children: [
|
|
8831
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8832
|
-
Controller,
|
|
8833
|
-
{
|
|
8834
|
-
control: form.control,
|
|
8835
|
-
name: "customer_id",
|
|
8836
|
-
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [
|
|
8837
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Customer ID" }),
|
|
8838
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Input, { ...field, disabled: true })
|
|
8839
|
-
] })
|
|
8840
|
-
}
|
|
8841
|
-
),
|
|
8842
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8843
|
-
Controller,
|
|
8844
|
-
{
|
|
8845
|
-
control: form.control,
|
|
8846
|
-
name: "order_id",
|
|
8847
|
-
rules: { required: "Order is required" },
|
|
8848
|
-
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [
|
|
8849
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", weight: "plus", children: [
|
|
8850
|
-
"Order ",
|
|
8851
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
|
|
8852
|
-
] }),
|
|
8853
|
-
customerLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Loading orders..." }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8854
|
-
ui.Select,
|
|
8855
|
-
{
|
|
8856
|
-
value: field.value,
|
|
8857
|
-
onValueChange: (value) => {
|
|
8858
|
-
field.onChange(value);
|
|
8859
|
-
form.setValue("product_id", "");
|
|
8860
|
-
},
|
|
8861
|
-
children: [
|
|
8862
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Select an order from this customer" }) }),
|
|
8863
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: customerOrders.map((order) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Item, { value: order.id, children: [
|
|
8864
|
-
new Date(order.created_at).toLocaleString(
|
|
8865
|
-
"en-US",
|
|
8866
|
-
{
|
|
8867
|
-
year: "numeric",
|
|
8868
|
-
month: "short",
|
|
8869
|
-
day: "numeric"
|
|
8870
|
-
}
|
|
8871
|
-
),
|
|
8872
|
-
" ",
|
|
8873
|
-
"- #",
|
|
8874
|
-
order.display_id
|
|
8875
|
-
] }, order.id)) })
|
|
8876
|
-
]
|
|
8877
|
-
}
|
|
8878
|
-
)
|
|
8879
|
-
] })
|
|
8880
|
-
}
|
|
8881
|
-
),
|
|
8882
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8883
|
-
Controller,
|
|
8884
|
-
{
|
|
8885
|
-
control: form.control,
|
|
8886
|
-
name: "product_id",
|
|
8887
|
-
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [
|
|
8888
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Product" }),
|
|
8889
|
-
orderLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Loading..." }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8890
|
-
ui.Select,
|
|
8891
|
-
{
|
|
8892
|
-
value: field.value,
|
|
8893
|
-
onValueChange: field.onChange,
|
|
8894
|
-
children: [
|
|
8895
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Select a product" }) }),
|
|
8896
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: orderProducts == null ? void 0 : orderProducts.map((product) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: product.id, children: product.title }, product.id)) })
|
|
8897
|
-
]
|
|
8898
|
-
}
|
|
8899
|
-
)
|
|
8900
|
-
] })
|
|
8901
|
-
}
|
|
8902
|
-
),
|
|
8903
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [
|
|
8904
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Tags" }),
|
|
8905
|
-
selectedTagIds.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2 mb-2", children: selectedTagIds.map((tagId) => {
|
|
8906
|
-
var _a3;
|
|
8907
|
-
const tag = (_a3 = tagsData == null ? void 0 : tagsData.complaint_tags) == null ? void 0 : _a3.find(
|
|
8908
|
-
(t2) => t2.id === tagId
|
|
8909
|
-
);
|
|
8910
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8911
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "xsmall", color: "blue", children: (tag == null ? void 0 : tag.value) ?? tagId }),
|
|
8912
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8913
|
-
"button",
|
|
8914
|
-
{
|
|
8915
|
-
type: "button",
|
|
8916
|
-
onClick: () => setSelectedTagIds(
|
|
8917
|
-
(prev) => prev.filter((id) => id !== tagId)
|
|
8918
|
-
),
|
|
8919
|
-
className: "text-ui-fg-subtle hover:text-ui-fg-base text-xs",
|
|
8920
|
-
"aria-label": `Remove tag ${tag == null ? void 0 : tag.value}`,
|
|
8921
|
-
children: "✕"
|
|
8922
|
-
}
|
|
8923
|
-
)
|
|
8924
|
-
] }, tagId);
|
|
8925
|
-
}) }),
|
|
8926
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8927
|
-
ui.Select,
|
|
8928
|
-
{
|
|
8929
|
-
value: tagSelectValue,
|
|
8930
|
-
onValueChange: (value) => {
|
|
8931
|
-
if (value && !selectedTagIds.includes(value)) {
|
|
8932
|
-
setSelectedTagIds((prev) => [...prev, value]);
|
|
8933
|
-
}
|
|
8934
|
-
form.setValue("tag_ids", [...selectedTagIds, value], {
|
|
8935
|
-
shouldDirty: true
|
|
8936
|
-
});
|
|
8937
|
-
setTagSelectValue("");
|
|
8938
|
-
},
|
|
8939
|
-
children: [
|
|
8940
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "Add a tag..." }) }),
|
|
8941
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: (_b = tagsData == null ? void 0 : tagsData.complaint_tags) == null ? void 0 : _b.filter((tag) => !selectedTagIds.includes(tag.id)).map((tag) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: tag.id, children: tag.value }, tag.id)) })
|
|
8942
|
-
]
|
|
8943
|
-
}
|
|
8944
|
-
)
|
|
8945
|
-
] }),
|
|
8946
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8947
|
-
Controller,
|
|
8948
|
-
{
|
|
8949
|
-
control: form.control,
|
|
8950
|
-
name: "description",
|
|
8951
|
-
render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-2", children: [
|
|
8952
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", weight: "plus", children: "Description" }),
|
|
8953
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Textarea, { ...field })
|
|
8954
|
-
] })
|
|
8955
|
-
}
|
|
8956
|
-
)
|
|
8957
|
-
] })
|
|
8958
|
-
] }) }) })
|
|
8959
|
-
] }) }) }) });
|
|
8960
|
-
};
|
|
8961
|
-
const CreateComplaintPage = () => {
|
|
8962
|
-
const [searchParams] = reactRouterDom.useSearchParams();
|
|
8963
|
-
const navigate = reactRouterDom.useNavigate();
|
|
8964
|
-
const customerId = searchParams.get("customer_id") ?? "";
|
|
8965
|
-
const orderId = searchParams.get("order_id") ?? "";
|
|
8966
|
-
const [createOpen, setCreateOpen] = React.useState(true);
|
|
8967
|
-
const handleOpenChange = (open) => {
|
|
8968
|
-
setCreateOpen(open);
|
|
8969
|
-
if (!open) {
|
|
8970
|
-
navigate("/complaints", { replace: true });
|
|
8971
|
-
}
|
|
8972
|
-
};
|
|
8973
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8974
|
-
CreateComplaintModal,
|
|
8975
|
-
{
|
|
8976
|
-
customerId,
|
|
8977
|
-
orderId,
|
|
8978
|
-
open: createOpen,
|
|
8979
|
-
setOpen: handleOpenChange
|
|
8980
|
-
}
|
|
8981
|
-
);
|
|
8982
|
-
};
|
|
8983
8983
|
const schema = object({
|
|
8984
8984
|
value: string().min(1, "Required")
|
|
8985
8985
|
});
|
|
@@ -9142,16 +9142,16 @@ const routeModule = {
|
|
|
9142
9142
|
path: "/settings/complaint-stats",
|
|
9143
9143
|
handle: handle$2
|
|
9144
9144
|
},
|
|
9145
|
+
{
|
|
9146
|
+
Component: CreateComplaintPage,
|
|
9147
|
+
path: "/complaints/create"
|
|
9148
|
+
},
|
|
9145
9149
|
{
|
|
9146
9150
|
Component: ComplaintDetailPage,
|
|
9147
9151
|
path: "/complaints/:id",
|
|
9148
9152
|
handle: handle$1,
|
|
9149
9153
|
loader: loader$1
|
|
9150
9154
|
},
|
|
9151
|
-
{
|
|
9152
|
-
Component: CreateComplaintPage,
|
|
9153
|
-
path: "/complaints/create"
|
|
9154
|
-
},
|
|
9155
9155
|
{
|
|
9156
9156
|
Component: ComplaintTagDetailPage,
|
|
9157
9157
|
path: "/settings/complaint-tags/:id",
|