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.
@@ -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 || 'supersecret',
14
- cookieSecret: process.env.COOKIE_SECRET || 'supersecret'
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVkdXNhLWNvbmZpZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL21lZHVzYS1jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFBaUU7QUFFakUsSUFBQSxlQUFPLEVBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLElBQUksYUFBYSxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFBO0FBRTdELE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBQSxvQkFBWSxFQUFDO0lBQzdCLGFBQWEsRUFBRTtRQUNkLFFBQVEsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVM7UUFDL0IsV0FBVyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWTtRQUNyQyxJQUFJLEVBQUU7WUFDTCxTQUFTLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksdUJBQXVCO1lBQzVELFNBQVMsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSw2Q0FBNkM7WUFDbEYsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxJQUFJLDZDQUE2QztZQUNoRixTQUFTLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksYUFBYTtZQUNsRCxZQUFZLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLElBQUksYUFBYTtTQUN4RDtLQUNEO0lBQ0QsT0FBTyxFQUFFO1FBQ1I7WUFDQyxPQUFPLEVBQUUseUJBQXlCO1NBQ2xDO0tBQ0Q7Q0FDRCxDQUFDLENBQUEifQ==
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$3 = object({
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$3),
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$2 = object({
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$2),
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",