@lodashventure/medusa-quotation 1.4.20 → 1.4.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ import { DocumentText, CheckCircleSolid, Plus, Trash } from "@medusajs/icons";
4
4
  import { clx, FocusModal, Heading, Text, Button, Table, Badge, Label, DatePicker, Input, toast, Container, Select, Textarea, createDataTableColumnHelper, useDataTable, DataTable, Toaster, usePrompt, IconButton, Hint, CurrencyInput } from "@medusajs/ui";
5
5
  import { useState, useCallback, useEffect, useMemo } from "react";
6
6
  import { useNavigate, useParams, Link } from "react-router-dom";
7
- import { XCircle, Clock, CheckCircle } from "lucide-react";
7
+ import { XCircle, CheckCircle, Clock } from "lucide-react";
8
8
  import Medusa from "@medusajs/js-sdk";
9
9
  import { zodResolver } from "@hookform/resolvers/zod";
10
10
  import { useForm, Controller } from "react-hook-form";
@@ -13,20 +13,26 @@ import pdfMake from "pdfmake/build/pdfmake";
13
13
  import { debounce } from "lodash";
14
14
  import "@medusajs/admin-shared";
15
15
  const StatusTitles = {
16
+ approved: "Approved",
16
17
  accepted: "Accepted",
17
18
  customer_rejected: "Customer Rejected",
18
19
  merchant_rejected: "Merchant Rejected",
19
20
  pending_merchant: "Pending Merchant",
20
- pending_customer: "Pending Customer"
21
+ pending_customer: "Pending Customer",
22
+ voided: "Voided"
21
23
  };
22
24
  const getStatusColor = (statusKey) => {
23
25
  switch (statusKey) {
24
26
  case "accepted":
25
27
  return "bg-green-100 text-green-800";
28
+ case "approved":
29
+ return "bg-emerald-100 text-emerald-800";
26
30
  case "pending_merchant":
27
31
  return "bg-blue-100 text-blue-800";
28
32
  case "customer_rejected":
29
33
  return "bg-red-100 text-red-800";
34
+ case "voided":
35
+ return "bg-gray-100 text-gray-800";
30
36
  default:
31
37
  return "bg-gray-100 text-gray-800";
32
38
  }
@@ -43,6 +49,10 @@ const getStatusIcon = (statusKey) => {
43
49
  return /* @__PURE__ */ jsx(XCircle, { className: "h-4 w-4 text-red-600" });
44
50
  case "customer_rejected":
45
51
  return /* @__PURE__ */ jsx(XCircle, { className: "h-4 w-4 text-red-600" });
52
+ case "approved":
53
+ return /* @__PURE__ */ jsx(CheckCircle, { className: "h-4 w-4 text-emerald-600" });
54
+ case "voided":
55
+ return /* @__PURE__ */ jsx(XCircle, { className: "h-4 w-4 text-gray-600" });
46
56
  default:
47
57
  return null;
48
58
  }
@@ -147,7 +157,7 @@ const useAddQuoteItem = (id, options) => {
147
157
  setIsPending(false);
148
158
  }
149
159
  };
150
- return { mutate, isPending, error };
160
+ return { mutate, mutateAsync: mutate, isPending, error };
151
161
  };
152
162
  const useUpdateQuoteItem = (id, options) => {
153
163
  const [isPending, setIsPending] = useState(false);
@@ -171,7 +181,7 @@ const useUpdateQuoteItem = (id, options) => {
171
181
  setIsPending(false);
172
182
  }
173
183
  };
174
- return { mutate, isPending, error };
184
+ return { mutate, mutateAsync: mutate, isPending, error };
175
185
  };
176
186
  const useRemoveQuoteItem = (id, options) => {
177
187
  const [isPending, setIsPending] = useState(false);
@@ -191,7 +201,7 @@ const useRemoveQuoteItem = (id, options) => {
191
201
  setIsPending(false);
192
202
  }
193
203
  };
194
- return { mutate, isPending, error };
204
+ return { mutate, mutateAsync: mutate, isPending, error };
195
205
  };
196
206
  const useConfirmQuote = (id, options) => {
197
207
  const [isPending, setIsPending] = useState(false);
@@ -211,7 +221,7 @@ const useConfirmQuote = (id, options) => {
211
221
  setIsPending(false);
212
222
  }
213
223
  };
214
- return { mutate, isPending, error };
224
+ return { mutate, mutateAsync: mutate, isPending, error };
215
225
  };
216
226
  const useSendQuote = (id, options) => {
217
227
  const [isPending, setIsPending] = useState(false);
@@ -219,22 +229,49 @@ const useSendQuote = (id, options) => {
219
229
  const sendQuote = async (id2) => sdk.client.fetch(`/admin/quotes/${id2}/send`, {
220
230
  method: "POST"
221
231
  });
222
- const mutate = async () => {
223
- var _a;
232
+ const mutate = async (_, mutateOptions) => {
233
+ var _a, _b, _c;
224
234
  try {
225
235
  setIsPending(true);
226
236
  setError(null);
227
237
  const data = await sendQuote(id);
228
238
  (_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options, data);
239
+ (_b = mutateOptions == null ? void 0 : mutateOptions.onSuccess) == null ? void 0 : _b.call(mutateOptions, data);
229
240
  return data;
230
241
  } catch (err) {
231
242
  setError(err);
243
+ (_c = mutateOptions == null ? void 0 : mutateOptions.onError) == null ? void 0 : _c.call(mutateOptions, err);
232
244
  throw err;
233
245
  } finally {
234
246
  setIsPending(false);
235
247
  }
236
248
  };
237
- return { mutate, isPending, error };
249
+ return { mutate, mutateAsync: mutate, isPending, error };
250
+ };
251
+ const useApproveQuote = (id, options) => {
252
+ const [isPending, setIsPending] = useState(false);
253
+ const [error, setError] = useState(null);
254
+ const approveQuote = async (quoteId) => sdk.client.fetch(`/admin/quotes/${quoteId}/approve`, {
255
+ method: "POST"
256
+ });
257
+ const mutate = async (_, mutateOptions) => {
258
+ var _a, _b, _c;
259
+ try {
260
+ setIsPending(true);
261
+ setError(null);
262
+ const data = await approveQuote(id);
263
+ (_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options, data);
264
+ (_b = mutateOptions == null ? void 0 : mutateOptions.onSuccess) == null ? void 0 : _b.call(mutateOptions, data);
265
+ return data;
266
+ } catch (err) {
267
+ setError(err);
268
+ (_c = mutateOptions == null ? void 0 : mutateOptions.onError) == null ? void 0 : _c.call(mutateOptions, err);
269
+ throw err;
270
+ } finally {
271
+ setIsPending(false);
272
+ }
273
+ };
274
+ return { mutate, mutateAsync: mutate, isPending, error };
238
275
  };
239
276
  const useRejectQuote = (id, options) => {
240
277
  const [isPending, setIsPending] = useState(false);
@@ -242,22 +279,96 @@ const useRejectQuote = (id, options) => {
242
279
  const rejectQuote = async (id2) => sdk.client.fetch(`/admin/quotes/${id2}/reject`, {
243
280
  method: "POST"
244
281
  });
245
- const mutate = async () => {
246
- var _a;
282
+ const mutate = async (_, mutateOptions) => {
283
+ var _a, _b, _c;
247
284
  try {
248
285
  setIsPending(true);
249
286
  setError(null);
250
287
  const data = await rejectQuote(id);
251
288
  (_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options, data);
289
+ (_b = mutateOptions == null ? void 0 : mutateOptions.onSuccess) == null ? void 0 : _b.call(mutateOptions, data);
252
290
  return data;
253
291
  } catch (err) {
254
292
  setError(err);
293
+ (_c = mutateOptions == null ? void 0 : mutateOptions.onError) == null ? void 0 : _c.call(mutateOptions, err);
255
294
  throw err;
256
295
  } finally {
257
296
  setIsPending(false);
258
297
  }
259
298
  };
260
- return { mutate, isPending, error };
299
+ return { mutate, mutateAsync: mutate, isPending, error };
300
+ };
301
+ const useVoidQuote = (id, options) => {
302
+ const [isPending, setIsPending] = useState(false);
303
+ const [error, setError] = useState(null);
304
+ const voidQuote = async (quoteId) => sdk.client.fetch(`/admin/quotes/${quoteId}/void`, {
305
+ method: "POST"
306
+ });
307
+ const mutate = async (_, mutateOptions) => {
308
+ var _a, _b, _c;
309
+ try {
310
+ setIsPending(true);
311
+ setError(null);
312
+ const data = await voidQuote(id);
313
+ (_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options, data);
314
+ (_b = mutateOptions == null ? void 0 : mutateOptions.onSuccess) == null ? void 0 : _b.call(mutateOptions, data);
315
+ return data;
316
+ } catch (err) {
317
+ setError(err);
318
+ (_c = mutateOptions == null ? void 0 : mutateOptions.onError) == null ? void 0 : _c.call(mutateOptions, err);
319
+ throw err;
320
+ } finally {
321
+ setIsPending(false);
322
+ }
323
+ };
324
+ return { mutate, mutateAsync: mutate, isPending, error };
325
+ };
326
+ const useDeleteQuote = (id, options) => {
327
+ const [isPending, setIsPending] = useState(false);
328
+ const [error, setError] = useState(null);
329
+ const deleteQuote = async () => {
330
+ const response = await fetch(`/admin/quotes/${id}`, {
331
+ method: "DELETE",
332
+ headers: {
333
+ "Content-Type": "application/json"
334
+ },
335
+ credentials: "include"
336
+ });
337
+ if (!response.ok) {
338
+ const errorText = await response.text();
339
+ let errorMessage = errorText;
340
+ try {
341
+ const errorJson = JSON.parse(errorText);
342
+ errorMessage = errorJson.message || errorText;
343
+ } catch {
344
+ }
345
+ throw new Error(errorMessage || `HTTP ${response.status}`);
346
+ }
347
+ if (response.status === 204) {
348
+ return;
349
+ }
350
+ const contentType = response.headers.get("content-type");
351
+ if (contentType && contentType.includes("application/json")) {
352
+ return response.json();
353
+ }
354
+ };
355
+ const mutate = async (_, mutateOptions) => {
356
+ var _a, _b, _c;
357
+ try {
358
+ setIsPending(true);
359
+ setError(null);
360
+ await deleteQuote();
361
+ (_a = options == null ? void 0 : options.onSuccess) == null ? void 0 : _a.call(options);
362
+ (_b = mutateOptions == null ? void 0 : mutateOptions.onSuccess) == null ? void 0 : _b.call(mutateOptions);
363
+ } catch (err) {
364
+ setError(err);
365
+ (_c = mutateOptions == null ? void 0 : mutateOptions.onError) == null ? void 0 : _c.call(mutateOptions, err);
366
+ throw err;
367
+ } finally {
368
+ setIsPending(false);
369
+ }
370
+ };
371
+ return { mutate, mutateAsync: mutate, isPending, error };
261
372
  };
262
373
  const useQuoteStore = () => {
263
374
  const [data, setData] = useState(void 0);
@@ -1674,11 +1785,15 @@ const TotalsBreakdown = ({ order }) => {
1674
1785
  })
1675
1786
  ] });
1676
1787
  };
1677
- const useOrderPreview = (id, query) => {
1788
+ const useOrderPreview = (id, query, options) => {
1678
1789
  const [data, setData] = useState(void 0);
1679
1790
  const [isLoading, setIsLoading] = useState(true);
1680
1791
  const [error, setError] = useState(null);
1792
+ const enabled = (options == null ? void 0 : options.enabled) ?? true;
1681
1793
  const fetchOrderPreview = useCallback(async () => {
1794
+ if (!id || !enabled) {
1795
+ return;
1796
+ }
1682
1797
  try {
1683
1798
  setIsLoading(true);
1684
1799
  setError(null);
@@ -1689,10 +1804,14 @@ const useOrderPreview = (id, query) => {
1689
1804
  } finally {
1690
1805
  setIsLoading(false);
1691
1806
  }
1692
- }, [id, JSON.stringify(query)]);
1807
+ }, [id, enabled, JSON.stringify(query)]);
1693
1808
  useEffect(() => {
1809
+ if (!id || !enabled) {
1810
+ setIsLoading(false);
1811
+ return;
1812
+ }
1694
1813
  fetchOrderPreview();
1695
- }, [fetchOrderPreview]);
1814
+ }, [fetchOrderPreview, id, enabled]);
1696
1815
  return {
1697
1816
  ...data,
1698
1817
  isLoading,
@@ -1752,13 +1871,17 @@ const DEFAULT_RELATIONS = [
1752
1871
  const DEFAULT_ORDER_FIELDS = `${DEFAULT_PROPERTIES.join(
1753
1872
  ","
1754
1873
  )},${DEFAULT_RELATIONS.join(",")}`;
1755
- const useOrder = (id, query) => {
1874
+ const useOrder = (id, query, options) => {
1756
1875
  const [data, setData] = useState(
1757
1876
  void 0
1758
1877
  );
1759
1878
  const [isLoading, setIsLoading] = useState(true);
1760
1879
  const [error, setError] = useState(null);
1880
+ const enabled = (options == null ? void 0 : options.enabled) ?? true;
1761
1881
  const fetchOrder = useCallback(async () => {
1882
+ if (!id || !enabled) {
1883
+ return;
1884
+ }
1762
1885
  try {
1763
1886
  setIsLoading(true);
1764
1887
  setError(null);
@@ -1769,10 +1892,14 @@ const useOrder = (id, query) => {
1769
1892
  } finally {
1770
1893
  setIsLoading(false);
1771
1894
  }
1772
- }, [id, JSON.stringify(query)]);
1895
+ }, [id, enabled, JSON.stringify(query)]);
1773
1896
  useEffect(() => {
1897
+ if (!id || !enabled) {
1898
+ setIsLoading(false);
1899
+ return;
1900
+ }
1774
1901
  fetchOrder();
1775
- }, [fetchOrder]);
1902
+ }, [fetchOrder, id, enabled]);
1776
1903
  return {
1777
1904
  ...data,
1778
1905
  isLoading,
@@ -2144,77 +2271,150 @@ const QuoteDetails = () => {
2144
2271
  var _a, _b, _c, _d, _e, _f, _g, _h;
2145
2272
  const { id } = useParams();
2146
2273
  const navigate = useNavigate();
2147
- const { quote, isLoading } = useQuote(id, {
2274
+ const { quote, isLoading, refetch: refetchQuote } = useQuote(id, {
2148
2275
  fields: "*draft_order,*draft_order.customer,*draft_order.shipping_address,*draft_order.billing_address"
2149
2276
  });
2150
2277
  const { generatePdf, downloadPdf, pdfUrl } = useQuotePdf();
2151
2278
  const { store } = useQuoteStore();
2279
+ const draftOrderId = quote == null ? void 0 : quote.draft_order_id;
2152
2280
  const { order: preview, isLoading: isPreviewLoading } = useOrderPreview(
2153
- quote == null ? void 0 : quote.draft_order_id,
2281
+ draftOrderId,
2154
2282
  {
2155
2283
  fields: DEFAULT_ORDER_FIELDS
2156
2284
  },
2157
- { enabled: !!(quote == null ? void 0 : quote.draft_order_id) }
2285
+ { enabled: !!draftOrderId }
2286
+ );
2287
+ useOrder(
2288
+ draftOrderId,
2289
+ {
2290
+ fields: DEFAULT_ORDER_FIELDS
2291
+ },
2292
+ { enabled: !!draftOrderId }
2158
2293
  );
2159
- const { order } = useOrder(quote == null ? void 0 : quote.draft_order_id, {
2160
- fields: DEFAULT_ORDER_FIELDS
2161
- });
2162
- console.log(order);
2163
2294
  const prompt = usePrompt();
2164
2295
  const { mutateAsync: rejectQuote, isPending: isRejectingQuote } = useRejectQuote(id);
2165
- const [showRejectQuote, setShowRejectQuote] = useState(false);
2166
2296
  const { mutateAsync: sendQuote, isPending: isSendingQuote } = useSendQuote(
2167
2297
  id
2168
2298
  );
2169
- const [showSendQuote, setShowSendQuote] = useState(false);
2170
- const [showManageQuote, setShowManageQuote] = useState(false);
2171
- useEffect(() => {
2172
- if (["pending_merchant", "customer_rejected"].includes(quote == null ? void 0 : quote.status)) {
2173
- setShowSendQuote(true);
2174
- } else {
2175
- setShowSendQuote(false);
2176
- }
2177
- if (["customer_rejected", "merchant_rejected", "accepted"].includes(
2178
- (quote == null ? void 0 : quote.status) ?? ""
2179
- )) {
2180
- setShowRejectQuote(false);
2181
- } else {
2182
- setShowRejectQuote(true);
2183
- }
2184
- if (!["pending_merchant", "customer_rejected"].includes((quote == null ? void 0 : quote.status) ?? "")) {
2185
- setShowManageQuote(false);
2186
- } else {
2187
- setShowManageQuote(true);
2188
- }
2189
- }, [quote]);
2299
+ const { mutateAsync: approveQuote, isPending: isApprovingQuote } = useApproveQuote(id);
2300
+ const { mutateAsync: voidQuote, isPending: isVoidingQuote } = useVoidQuote(
2301
+ id
2302
+ );
2303
+ const { mutateAsync: deleteQuote, isPending: isDeletingQuote } = useDeleteQuote(id);
2304
+ const quoteStatus = (quote == null ? void 0 : quote.status) ?? "";
2305
+ const canApproveQuote = [
2306
+ "pending_merchant",
2307
+ "pending_customer",
2308
+ "customer_rejected"
2309
+ ].includes(quoteStatus);
2310
+ const canRejectQuote = ["pending_merchant", "pending_customer"].includes(
2311
+ quoteStatus
2312
+ );
2313
+ const canSendQuote = ["pending_merchant", "customer_rejected"].includes(
2314
+ quoteStatus
2315
+ );
2316
+ const canManageQuote = ["pending_merchant", "customer_rejected"].includes(
2317
+ quoteStatus
2318
+ );
2319
+ const canDeleteQuote = !["accepted", "approved", "converted"].includes(
2320
+ quoteStatus
2321
+ );
2322
+ const canVoidQuote = quoteStatus === "approved";
2323
+ const isMutatingQuote = isRejectingQuote || isSendingQuote || isApprovingQuote || isVoidingQuote || isDeletingQuote;
2324
+ const getErrorMessage = (error) => error instanceof Error ? error.message : "Something went wrong";
2190
2325
  const handleRejectQuote = async () => {
2191
- const res = await prompt({
2326
+ const confirmed = await prompt({
2192
2327
  title: "Reject quote?",
2193
2328
  description: "You are about to reject this customer's quote. Do you want to continue?",
2194
- confirmText: "Continue",
2329
+ confirmText: "Reject",
2195
2330
  cancelText: "Cancel",
2196
2331
  variant: "confirmation"
2197
2332
  });
2198
- if (res) {
2199
- await rejectQuote(void 0, {
2200
- onSuccess: () => toast.success("Successfully rejected customer's quote"),
2201
- onError: (e) => toast.error(e.message)
2202
- });
2333
+ if (!confirmed) {
2334
+ return;
2335
+ }
2336
+ try {
2337
+ await rejectQuote();
2338
+ await refetchQuote();
2339
+ toast.success("Successfully rejected customer's quote");
2340
+ } catch (error) {
2341
+ toast.error(getErrorMessage(error));
2203
2342
  }
2204
2343
  };
2205
2344
  const handleSendQuote = async () => {
2206
- const res = await prompt({
2345
+ const confirmed = await prompt({
2207
2346
  title: "Send quote?",
2208
2347
  description: "You are about to send this quote to the customer. Do you want to continue?",
2209
- confirmText: "Continue",
2348
+ confirmText: "Send",
2210
2349
  cancelText: "Cancel",
2211
2350
  variant: "confirmation"
2212
2351
  });
2213
- if (res) {
2214
- await sendQuote(void 0, {
2215
- onSuccess: () => toast.success("Successfully sent quote to customer"),
2216
- onError: (e) => toast.error(e.message)
2217
- });
2352
+ if (!confirmed) {
2353
+ return;
2354
+ }
2355
+ try {
2356
+ await sendQuote();
2357
+ await refetchQuote();
2358
+ toast.success("Successfully sent quote to customer");
2359
+ } catch (error) {
2360
+ toast.error(getErrorMessage(error));
2361
+ }
2362
+ };
2363
+ const handleApproveQuote = async () => {
2364
+ const confirmed = await prompt({
2365
+ title: "Approve quote?",
2366
+ description: "Approving the quote makes it ready for processing. Continue?",
2367
+ confirmText: "Approve",
2368
+ cancelText: "Cancel",
2369
+ variant: "confirmation"
2370
+ });
2371
+ if (!confirmed) {
2372
+ return;
2373
+ }
2374
+ try {
2375
+ await approveQuote();
2376
+ await refetchQuote();
2377
+ toast.success("Quote approved");
2378
+ } catch (error) {
2379
+ toast.error(getErrorMessage(error));
2380
+ }
2381
+ };
2382
+ const handleVoidQuote = async () => {
2383
+ const confirmed = await prompt({
2384
+ title: "Void approved quote?",
2385
+ description: "Voiding will move the quote out of the approved state. Continue?",
2386
+ confirmText: "Void",
2387
+ cancelText: "Cancel",
2388
+ variant: "confirmation"
2389
+ });
2390
+ if (!confirmed) {
2391
+ return;
2392
+ }
2393
+ try {
2394
+ await voidQuote();
2395
+ await refetchQuote();
2396
+ toast.success("Quote voided");
2397
+ } catch (error) {
2398
+ toast.error(getErrorMessage(error));
2399
+ }
2400
+ };
2401
+ const handleDeleteQuote = async () => {
2402
+ const confirmed = await prompt({
2403
+ title: "Delete quote?",
2404
+ description: "This will remove the quote permanently. This action cannot be undone.",
2405
+ confirmText: "Delete",
2406
+ cancelText: "Cancel",
2407
+ variant: "danger"
2408
+ });
2409
+ if (!confirmed) {
2410
+ return;
2411
+ }
2412
+ try {
2413
+ await deleteQuote();
2414
+ toast.success("Quote deleted");
2415
+ navigate("/quotes");
2416
+ } catch (error) {
2417
+ toast.error(getErrorMessage(error));
2218
2418
  }
2219
2419
  };
2220
2420
  const parseToPdfData = () => {
@@ -2353,33 +2553,64 @@ const QuoteDetails = () => {
2353
2553
  )
2354
2554
  ] })
2355
2555
  ] }),
2356
- /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle flex items-center justify-end gap-x-2 rounded-b-xl px-4 py-4", children: [
2357
- showRejectQuote && /* @__PURE__ */ jsx(
2556
+ /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle flex flex-wrap items-center justify-end gap-2 rounded-b-xl px-4 py-4", children: [
2557
+ canDeleteQuote && /* @__PURE__ */ jsx(
2558
+ Button,
2559
+ {
2560
+ size: "small",
2561
+ variant: "danger",
2562
+ onClick: handleDeleteQuote,
2563
+ disabled: isMutatingQuote,
2564
+ children: "Delete Quote"
2565
+ }
2566
+ ),
2567
+ canVoidQuote && /* @__PURE__ */ jsx(
2568
+ Button,
2569
+ {
2570
+ size: "small",
2571
+ variant: "secondary",
2572
+ onClick: handleVoidQuote,
2573
+ disabled: isMutatingQuote,
2574
+ children: "Void Quote"
2575
+ }
2576
+ ),
2577
+ canRejectQuote && /* @__PURE__ */ jsx(
2358
2578
  Button,
2359
2579
  {
2360
2580
  size: "small",
2361
2581
  variant: "secondary",
2362
- onClick: () => handleRejectQuote(),
2363
- disabled: isRejectingQuote,
2582
+ onClick: handleRejectQuote,
2583
+ disabled: isMutatingQuote,
2364
2584
  children: "Reject Quote"
2365
2585
  }
2366
2586
  ),
2367
- showSendQuote && /* @__PURE__ */ jsx(
2587
+ canApproveQuote && /* @__PURE__ */ jsx(
2588
+ Button,
2589
+ {
2590
+ size: "small",
2591
+ variant: "primary",
2592
+ onClick: handleApproveQuote,
2593
+ disabled: isMutatingQuote,
2594
+ children: "Approve Quote"
2595
+ }
2596
+ ),
2597
+ canSendQuote && /* @__PURE__ */ jsx(
2368
2598
  Button,
2369
2599
  {
2370
2600
  size: "small",
2371
2601
  variant: "secondary",
2372
- onClick: () => handleSendQuote(),
2373
- disabled: isSendingQuote || isRejectingQuote,
2602
+ onClick: handleSendQuote,
2603
+ disabled: isMutatingQuote,
2374
2604
  children: "Send Quote"
2375
2605
  }
2376
2606
  ),
2377
- showManageQuote && /* @__PURE__ */ jsx(
2607
+ canManageQuote && /* @__PURE__ */ jsx(
2378
2608
  Button,
2379
2609
  {
2380
2610
  size: "small",
2381
2611
  variant: "secondary",
2382
2612
  onClick: () => navigate(`/quotes/${quote.id}/manage`),
2613
+ disabled: isMutatingQuote,
2383
2614
  children: "Manage Quote"
2384
2615
  }
2385
2616
  )
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const merchant_approve_quote_1 = require("../../../../../workflows/merchant-approve-quote");
6
+ const POST = async (req, res) => {
7
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
8
+ const { id } = req.params;
9
+ await (0, merchant_approve_quote_1.merchantApproveQuoteWorkflow)(req.scope).run({
10
+ input: {
11
+ quote_id: id,
12
+ },
13
+ });
14
+ const { data: [quote], } = await query.graph({
15
+ entity: "quote",
16
+ filters: { id },
17
+ fields: req.queryConfig.fields,
18
+ }, { throwIfKeyNotFound: true });
19
+ res.json({ quote });
20
+ };
21
+ exports.POST = POST;
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3F1b3Rlcy9baWRdL2FwcHJvdmUvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEscURBQXNFO0FBQ3RFLDRGQUErRjtBQUV4RixNQUFNLElBQUksR0FBRyxLQUFLLEVBQ3ZCLEdBQStCLEVBQy9CLEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqRSxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztJQUUxQixNQUFNLElBQUEscURBQTRCLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUNoRCxLQUFLLEVBQUU7WUFDTCxRQUFRLEVBQUUsRUFBRTtTQUNiO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxFQUNKLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUNkLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUNuQjtRQUNFLE1BQU0sRUFBRSxPQUFPO1FBQ2YsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQ2YsTUFBTSxFQUFFLEdBQUcsQ0FBQyxXQUFXLENBQUMsTUFBTTtLQUMvQixFQUNELEVBQUUsa0JBQWtCLEVBQUUsSUFBSSxFQUFFLENBQzdCLENBQUM7SUFFRixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztBQUN0QixDQUFDLENBQUM7QUF6QlcsUUFBQSxJQUFJLFFBeUJmIn0=
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GET = void 0;
3
+ exports.DELETE = exports.GET = void 0;
4
4
  const utils_1 = require("@medusajs/framework/utils");
5
+ const merchant_delete_quote_1 = require("../../../../workflows/merchant-delete-quote");
5
6
  const GET = async (req, res) => {
6
7
  const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
7
8
  const { id } = req.params;
@@ -13,4 +14,14 @@ const GET = async (req, res) => {
13
14
  res.json({ quote });
14
15
  };
15
16
  exports.GET = GET;
16
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3F1b3Rlcy9baWRdL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUlBLHFEQUFzRTtBQUUvRCxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQ3RCLEdBQStCLEVBQy9CLEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqRSxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztJQUUxQixNQUFNLEVBQ0osSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQ2QsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQ25CO1FBQ0UsTUFBTSxFQUFFLE9BQU87UUFDZixPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUU7UUFDZixNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLDhCQUE4QixDQUFDO0tBQ3BFLEVBQ0QsRUFBRSxrQkFBa0IsRUFBRSxJQUFJLEVBQUUsQ0FDN0IsQ0FBQztJQUVGLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0FBQ3RCLENBQUMsQ0FBQztBQW5CVyxRQUFBLEdBQUcsT0FtQmQifQ==
17
+ const DELETE = async (req, res) => {
18
+ const { id } = req.params;
19
+ await (0, merchant_delete_quote_1.merchantDeleteQuoteWorkflow)(req.scope).run({
20
+ input: {
21
+ quote_id: id,
22
+ },
23
+ });
24
+ res.status(204).send();
25
+ };
26
+ exports.DELETE = DELETE;
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3F1b3Rlcy9baWRdL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUlBLHFEQUFzRTtBQUN0RSx1RkFBMEY7QUFFbkYsTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUN0QixHQUErQixFQUMvQixHQUFtQixFQUNuQixFQUFFO0lBQ0YsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakUsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUM7SUFFMUIsTUFBTSxFQUNKLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUNkLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUNuQjtRQUNFLE1BQU0sRUFBRSxPQUFPO1FBQ2YsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQ2YsTUFBTSxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSw4QkFBOEIsQ0FBQztLQUNwRSxFQUNELEVBQUUsa0JBQWtCLEVBQUUsSUFBSSxFQUFFLENBQzdCLENBQUM7SUFFRixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztBQUN0QixDQUFDLENBQUM7QUFuQlcsUUFBQSxHQUFHLE9BbUJkO0FBRUssTUFBTSxNQUFNLEdBQUcsS0FBSyxFQUN6QixHQUErQixFQUMvQixHQUFtQixFQUNuQixFQUFFO0lBQ0YsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUM7SUFFMUIsTUFBTSxJQUFBLG1EQUEyQixFQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDL0MsS0FBSyxFQUFFO1lBQ0wsUUFBUSxFQUFFLEVBQUU7U0FDYjtLQUNGLENBQUMsQ0FBQztJQUVILEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDekIsQ0FBQyxDQUFDO0FBYlcsUUFBQSxNQUFNLFVBYWpCIn0=
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const merchant_void_quote_1 = require("../../../../../workflows/merchant-void-quote");
6
+ const POST = async (req, res) => {
7
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
8
+ const { id } = req.params;
9
+ await (0, merchant_void_quote_1.merchantVoidQuoteWorkflow)(req.scope).run({
10
+ input: {
11
+ quote_id: id,
12
+ },
13
+ });
14
+ const { data: [quote], } = await query.graph({
15
+ entity: "quote",
16
+ filters: { id },
17
+ fields: req.queryConfig.fields,
18
+ }, { throwIfKeyNotFound: true });
19
+ res.json({ quote });
20
+ };
21
+ exports.POST = POST;
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3F1b3Rlcy9baWRdL3ZvaWQvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEscURBQXNFO0FBQ3RFLHNGQUF5RjtBQUVsRixNQUFNLElBQUksR0FBRyxLQUFLLEVBQ3ZCLEdBQStCLEVBQy9CLEdBQW1CLEVBQ25CLEVBQUU7SUFDRixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqRSxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztJQUUxQixNQUFNLElBQUEsK0NBQXlCLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUM3QyxLQUFLLEVBQUU7WUFDTCxRQUFRLEVBQUUsRUFBRTtTQUNiO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxFQUNKLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUNkLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUNuQjtRQUNFLE1BQU0sRUFBRSxPQUFPO1FBQ2YsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQ2YsTUFBTSxFQUFFLEdBQUcsQ0FBQyxXQUFXLENBQUMsTUFBTTtLQUMvQixFQUNELEVBQUUsa0JBQWtCLEVBQUUsSUFBSSxFQUFFLENBQzdCLENBQUM7SUFFRixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztBQUN0QixDQUFDLENBQUM7QUF6QlcsUUFBQSxJQUFJLFFBeUJmIn0=
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Migration20251028120000 = void 0;
4
+ const migrations_1 = require("@medusajs/framework/mikro-orm/migrations");
5
+ const QUOTE_STATUS_CONSTRAINT = "'draft', 'pending_merchant', 'pending_customer', 'approved', 'accepted', 'customer_rejected', 'merchant_rejected', 'voided', 'expired', 'converted'";
6
+ const PREVIOUS_QUOTE_STATUS_CONSTRAINT = "'draft', 'pending_merchant', 'pending_customer', 'accepted', 'customer_rejected', 'merchant_rejected', 'expired', 'converted'";
7
+ class Migration20251028120000 extends migrations_1.Migration {
8
+ async up() {
9
+ this.addSql(`alter table if exists "quote" drop constraint if exists "quote_status_check";`);
10
+ this.addSql(`alter table if exists "quote" add constraint "quote_status_check" check("status" in (${QUOTE_STATUS_CONSTRAINT}));`);
11
+ }
12
+ async down() {
13
+ this.addSql(`alter table if exists "quote" drop constraint if exists "quote_status_check";`);
14
+ this.addSql(`alter table if exists "quote" add constraint "quote_status_check" check("status" in (${PREVIOUS_QUOTE_STATUS_CONSTRAINT}));`);
15
+ }
16
+ }
17
+ exports.Migration20251028120000 = Migration20251028120000;
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWlncmF0aW9uMjAyNTEwMjgxMjAwMDAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9xdW90ZS9taWdyYXRpb25zL01pZ3JhdGlvbjIwMjUxMDI4MTIwMDAwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlFQUFxRTtBQUVyRSxNQUFNLHVCQUF1QixHQUMzQixxSkFBcUosQ0FBQztBQUV4SixNQUFNLGdDQUFnQyxHQUNwQywrSEFBK0gsQ0FBQztBQUVsSSxNQUFhLHVCQUF3QixTQUFRLHNCQUFTO0lBQzNDLEtBQUssQ0FBQyxFQUFFO1FBQ2YsSUFBSSxDQUFDLE1BQU0sQ0FDVCwrRUFBK0UsQ0FDaEYsQ0FBQztRQUVGLElBQUksQ0FBQyxNQUFNLENBQ1Qsd0ZBQXdGLHVCQUF1QixLQUFLLENBQ3JILENBQUM7SUFDSixDQUFDO0lBRVEsS0FBSyxDQUFDLElBQUk7UUFDakIsSUFBSSxDQUFDLE1BQU0sQ0FDVCwrRUFBK0UsQ0FDaEYsQ0FBQztRQUVGLElBQUksQ0FBQyxNQUFNLENBQ1Qsd0ZBQXdGLGdDQUFnQyxLQUFLLENBQzlILENBQUM7SUFDSixDQUFDO0NBQ0Y7QUFwQkQsMERBb0JDIn0=