@medusajs/dashboard 2.10.4-preview-20250924060154 → 2.10.4-preview-20250924090158

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.
Files changed (54) hide show
  1. package/dist/{add-campaign-promotions-BWIP24MA.mjs → add-campaign-promotions-62IIOR5K.mjs} +3 -3
  2. package/dist/{api-key-management-detail-WGWZQCFC.mjs → api-key-management-detail-TEW653QF.mjs} +1 -1
  3. package/dist/{api-key-management-sales-channels-H5TVIHTV.mjs → api-key-management-sales-channels-ESGRJKDT.mjs} +1 -1
  4. package/dist/app.css +0 -3
  5. package/dist/app.js +3490 -3464
  6. package/dist/app.mjs +2 -2
  7. package/dist/{campaign-detail-EJD7LQCW.mjs → campaign-detail-XYLU3HF4.mjs} +3 -3
  8. package/dist/{chunk-2252SSK6.mjs → chunk-6W7OL4TX.mjs} +1 -1
  9. package/dist/{chunk-OQPVQGSH.mjs → chunk-7GBCLBMX.mjs} +24 -11
  10. package/dist/{chunk-YPSSUJUZ.mjs → chunk-HEBATBOH.mjs} +6 -2
  11. package/dist/{chunk-U2FXUMKA.mjs → chunk-NDNUJ2UK.mjs} +1 -1
  12. package/dist/{chunk-CAZKNJTG.mjs → chunk-NKM6CHK6.mjs} +30 -30
  13. package/dist/{chunk-WP5CXGGO.mjs → chunk-TWP4GTKM.mjs} +1 -1
  14. package/dist/{chunk-V53HAFWH.mjs → chunk-UOEALCPZ.mjs} +1 -1
  15. package/dist/{chunk-6RWF7BPW.mjs → chunk-V6JXTITD.mjs} +1 -1
  16. package/dist/{customer-group-list-UTC5ZCJZ.mjs → customer-group-list-6XY7YF5E.mjs} +1 -1
  17. package/dist/{inventory-detail-BO5E7KXO.mjs → inventory-detail-WI5T47QL.mjs} +1 -1
  18. package/dist/{location-edit-RNGPJ26L.mjs → location-edit-X6JBEWIF.mjs} +1 -1
  19. package/dist/location-list-VNEYHAKV.mjs +323 -0
  20. package/dist/{location-sales-channels-NSXV65ZM.mjs → location-sales-channels-HVZHZMBY.mjs} +1 -1
  21. package/dist/{order-detail-6XQLJ5TU.mjs → order-detail-CNQ7HP32.mjs} +30 -22
  22. package/dist/{order-list-OTPVQKU6.mjs → order-list-YWPAJ7FR.mjs} +2 -2
  23. package/dist/{product-attributes-5PLACMXK.mjs → product-attributes-6ELSX5OH.mjs} +3 -3
  24. package/dist/{product-create-6FMLIS5X.mjs → product-create-6NWXJ7AY.mjs} +4 -4
  25. package/dist/{product-detail-2BJJMCCO.mjs → product-detail-G53SUBEP.mjs} +4 -4
  26. package/dist/{product-edit-N5P7RVNS.mjs → product-edit-ZYUXMIZP.mjs} +3 -3
  27. package/dist/{product-list-EUQX3NBE.mjs → product-list-R6IDCNRV.mjs} +2 -2
  28. package/dist/{product-media-XJGAON6B.mjs → product-media-AKHSFDJQ.mjs} +2 -2
  29. package/dist/{product-organization-FB6BVKKL.mjs → product-organization-J2UYHJ6I.mjs} +3 -3
  30. package/dist/{product-sales-channels-QBQDLU7Z.mjs → product-sales-channels-UX7AOJIF.mjs} +1 -1
  31. package/dist/{product-shipping-profile-UZQSV54B.mjs → product-shipping-profile-FN7L2V4X.mjs} +3 -3
  32. package/dist/{promotion-detail-VB5GZDCC.mjs → promotion-detail-RISSMGU5.mjs} +112 -63
  33. package/dist/{promotion-list-NAUTWXNU.mjs → promotion-list-UPVSOD6R.mjs} +3 -3
  34. package/dist/{refund-reason-list-VBHGRLJJ.mjs → refund-reason-list-RGRFZ5DU.mjs} +9 -4
  35. package/dist/{reset-password-ZCKXQZNQ.mjs → reset-password-AYCPBCKE.mjs} +1 -1
  36. package/dist/{sales-channel-list-R4HT6A7P.mjs → sales-channel-list-KNLMJ67Q.mjs} +1 -1
  37. package/dist/{tax-region-create-2GDG36NQ.mjs → tax-region-create-SP46RW2E.mjs} +1 -1
  38. package/dist/{user-list-TPBPZ7KJ.mjs → user-list-G4H2RSDX.mjs} +1 -1
  39. package/package.json +9 -9
  40. package/src/components/data-table/data-table.tsx +64 -46
  41. package/src/i18n/translations/$schema.json +19 -2
  42. package/src/i18n/translations/en.json +6 -2
  43. package/src/routes/locations/location-edit/components/edit-location-form/edit-location-form.tsx +1 -1
  44. package/src/routes/locations/location-list/index.ts +0 -1
  45. package/src/routes/locations/location-list/location-list.tsx +52 -14
  46. package/src/routes/locations/location-list/use-location-list-table-columns.tsx +185 -0
  47. package/src/routes/locations/location-list/use-location-list-table-query.tsx +22 -0
  48. package/src/routes/orders/order-detail/components/order-activity-section/order-timeline.tsx +13 -5
  49. package/src/routes/refund-reasons/refund-reason-list/components/refund-reason-list-table/refund-reason-list-table.tsx +12 -4
  50. package/dist/chunk-BKJC5BGQ.mjs +0 -53
  51. package/dist/location-list-NKIOBHG4.mjs +0 -298
  52. package/src/routes/locations/location-list/components/location-list-header/index.ts +0 -1
  53. package/src/routes/locations/location-list/components/location-list-header/location-list-header.tsx +0 -21
  54. package/src/routes/locations/location-list/loader.ts +0 -36
@@ -31,26 +31,26 @@ type DataTableActionProps = {
31
31
  label: string
32
32
  disabled?: boolean
33
33
  } & (
34
- | {
34
+ | {
35
35
  to: string
36
36
  }
37
- | {
37
+ | {
38
38
  onClick: () => void
39
39
  }
40
- )
40
+ )
41
41
 
42
42
  type DataTableActionMenuActionProps = {
43
43
  label: string
44
44
  icon: ReactNode
45
45
  disabled?: boolean
46
46
  } & (
47
- | {
47
+ | {
48
48
  to: string
49
49
  }
50
- | {
50
+ | {
51
51
  onClick: () => void
52
52
  }
53
- )
53
+ )
54
54
 
55
55
  type DataTableActionMenuGroupProps = {
56
56
  actions: DataTableActionMenuActionProps[]
@@ -138,15 +138,18 @@ export const DataTable = <TData,>({
138
138
  const isViewConfigEnabled = useFeatureFlag("view_configurations")
139
139
 
140
140
  // If view config is disabled, don't use column visibility features
141
- const effectiveEnableColumnVisibility = isViewConfigEnabled && enableColumnVisibility
141
+ const effectiveEnableColumnVisibility =
142
+ isViewConfigEnabled && enableColumnVisibility
142
143
  const effectiveEnableViewSelector = isViewConfigEnabled && enableViewSelector
143
144
 
144
145
  const enableFiltering = filters && filters.length > 0
145
- const showFilterMenu = enableFilterMenu !== undefined ? enableFilterMenu : enableFiltering
146
+ const showFilterMenu =
147
+ enableFilterMenu !== undefined ? enableFilterMenu : enableFiltering
146
148
  const enableCommands = commands && commands.length > 0
147
149
  const enableSorting = columns.some((column) => column.enableSorting)
148
150
 
149
- const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>(initialColumnVisibility)
151
+ const [columnVisibility, setColumnVisibility] =
152
+ React.useState<VisibilityState>(initialColumnVisibility)
150
153
 
151
154
  // Update column visibility when initial visibility changes
152
155
  React.useEffect(() => {
@@ -154,9 +157,12 @@ export const DataTable = <TData,>({
154
157
  const currentKeys = Object.keys(columnVisibility).sort()
155
158
  const newKeys = Object.keys(initialColumnVisibility).sort()
156
159
 
157
- const hasChanged = currentKeys.length !== newKeys.length ||
160
+ const hasChanged =
161
+ currentKeys.length !== newKeys.length ||
158
162
  currentKeys.some((key, index) => key !== newKeys[index]) ||
159
- Object.entries(initialColumnVisibility).some(([key, value]) => columnVisibility[key] !== value)
163
+ Object.entries(initialColumnVisibility).some(
164
+ ([key, value]) => columnVisibility[key] !== value
165
+ )
160
166
 
161
167
  if (hasChanged) {
162
168
  setColumnVisibility(initialColumnVisibility)
@@ -164,10 +170,13 @@ export const DataTable = <TData,>({
164
170
  }, [initialColumnVisibility])
165
171
 
166
172
  // Wrapper function to handle column visibility changes
167
- const handleColumnVisibilityChange = React.useCallback((visibility: VisibilityState) => {
168
- setColumnVisibility(visibility)
169
- onColumnVisibilityChange?.(visibility)
170
- }, [onColumnVisibilityChange])
173
+ const handleColumnVisibilityChange = React.useCallback(
174
+ (visibility: VisibilityState) => {
175
+ setColumnVisibility(visibility)
176
+ onColumnVisibilityChange?.(visibility)
177
+ },
178
+ [onColumnVisibilityChange]
179
+ )
171
180
 
172
181
  // Extract filter IDs for query param management
173
182
  const filterIds = useMemo(() => filters?.map((f) => f.id) ?? [], [filters])
@@ -231,7 +240,7 @@ export const DataTable = <TData,>({
231
240
  Array.from(prev.keys()).forEach((key) => {
232
241
  if (prefixedFilterIds.includes(key)) {
233
242
  // Extract the unprefixed key
234
- const unprefixedKey = prefix ? key.replace(`${prefix}_`, '') : key
243
+ const unprefixedKey = prefix ? key.replace(`${prefix}_`, "") : key
235
244
  if (!(unprefixedKey in value)) {
236
245
  prev.delete(key)
237
246
  }
@@ -257,11 +266,14 @@ export const DataTable = <TData,>({
257
266
  }, [order])
258
267
 
259
268
  // Memoize current configuration to prevent infinite loops
260
- const currentConfiguration = useMemo(() => ({
261
- filters: filtering,
262
- sorting: sorting,
263
- search: search,
264
- }), [filtering, sorting, search])
269
+ const currentConfiguration = useMemo(
270
+ () => ({
271
+ filters: filtering,
272
+ sorting: sorting,
273
+ search: search,
274
+ }),
275
+ [filtering, sorting, search]
276
+ )
265
277
 
266
278
  const handleSortingChange = (value: DataTableSortingState) => {
267
279
  setSearchParams((prev) => {
@@ -315,42 +327,43 @@ export const DataTable = <TData,>({
315
327
  onRowClick: rowHref ? onRowClick : undefined,
316
328
  pagination: enablePagination
317
329
  ? {
318
- state: pagination,
319
- onPaginationChange: handlePaginationChange,
320
- }
330
+ state: pagination,
331
+ onPaginationChange: handlePaginationChange,
332
+ }
321
333
  : undefined,
322
334
  filtering: enableFiltering
323
335
  ? {
324
- state: filtering,
325
- onFilteringChange: handleFilteringChange,
326
- }
336
+ state: filtering,
337
+ onFilteringChange: handleFilteringChange,
338
+ }
327
339
  : undefined,
328
340
  sorting: enableSorting
329
341
  ? {
330
- state: sorting,
331
- onSortingChange: handleSortingChange,
332
- }
342
+ state: sorting,
343
+ onSortingChange: handleSortingChange,
344
+ }
333
345
  : undefined,
334
346
  search: enableSearch
335
347
  ? {
336
- state: search,
337
- onSearchChange: handleSearchChange,
338
- }
348
+ state: search,
349
+ onSearchChange: handleSearchChange,
350
+ }
339
351
  : undefined,
340
352
  rowSelection,
341
353
  isLoading,
342
354
  columnVisibility: effectiveEnableColumnVisibility
343
355
  ? {
344
- state: columnVisibility,
345
- onColumnVisibilityChange: handleColumnVisibilityChange,
346
- }
347
- : undefined,
348
- columnOrder: effectiveEnableColumnVisibility && columnOrder && onColumnOrderChange
349
- ? {
350
- state: columnOrder,
351
- onColumnOrderChange: onColumnOrderChange,
352
- }
356
+ state: columnVisibility,
357
+ onColumnVisibilityChange: handleColumnVisibilityChange,
358
+ }
353
359
  : undefined,
360
+ columnOrder:
361
+ effectiveEnableColumnVisibility && columnOrder && onColumnOrderChange
362
+ ? {
363
+ state: columnOrder,
364
+ onColumnOrderChange: onColumnOrderChange,
365
+ }
366
+ : undefined,
354
367
  })
355
368
 
356
369
  const shouldRenderHeading = heading || subHeading
@@ -358,7 +371,9 @@ export const DataTable = <TData,>({
358
371
  return (
359
372
  <UiDataTable
360
373
  instance={instance}
361
- className={layout === "fill" ? "h-full [&_tr]:last-of-type:!border-b" : undefined}
374
+ className={
375
+ layout === "fill" ? "h-full [&_tr]:last-of-type:!border-b" : undefined
376
+ }
362
377
  >
363
378
  <UiDataTable.Toolbar
364
379
  className="flex flex-col items-start justify-between gap-2 md:flex-row md:items-center"
@@ -397,7 +412,9 @@ export const DataTable = <TData,>({
397
412
  </div>
398
413
  )}
399
414
  {actionMenu && <ActionMenu variant="primary" {...actionMenu} />}
400
- {actions && actions.length > 0 && <DataTableActions actions={actions} />}
415
+ {actions && actions.length > 0 && (
416
+ <DataTableActions actions={actions} />
417
+ )}
401
418
  {!actions && action && <DataTableAction {...action} />}
402
419
  </div>
403
420
  </div>
@@ -407,7 +424,9 @@ export const DataTable = <TData,>({
407
424
  <UiDataTable.Pagination translations={paginationTranslations} />
408
425
  )}
409
426
  {enableCommands && (
410
- <UiDataTable.CommandBar selectedLabel={(count) => `${count} selected`} />
427
+ <UiDataTable.CommandBar
428
+ selectedLabel={(count) => `${count} selected`}
429
+ />
411
430
  )}
412
431
  </UiDataTable>
413
432
  )
@@ -520,4 +539,3 @@ const DataTableActions = ({ actions }: { actions: DataTableActionProps[] }) => {
520
539
  </div>
521
540
  )
522
541
  }
523
-
@@ -5834,9 +5834,23 @@
5834
5834
  "properties": {
5835
5835
  "description": {
5836
5836
  "type": "string"
5837
+ },
5838
+ "noRecordsMessage": {
5839
+ "type": "string"
5840
+ },
5841
+ "noRecordsMessageEmpty": {
5842
+ "type": "string"
5843
+ },
5844
+ "noRecordsMessageFiltered": {
5845
+ "type": "string"
5837
5846
  }
5838
5847
  },
5839
- "required": ["description"],
5848
+ "required": [
5849
+ "description",
5850
+ "noRecordsMessage",
5851
+ "noRecordsMessageEmpty",
5852
+ "noRecordsMessageFiltered"
5853
+ ],
5840
5854
  "additionalProperties": false
5841
5855
  },
5842
5856
  "create": {
@@ -5876,9 +5890,12 @@
5876
5890
  "properties": {
5877
5891
  "confirmation": {
5878
5892
  "type": "string"
5893
+ },
5894
+ "successToast": {
5895
+ "type": "string"
5879
5896
  }
5880
5897
  },
5881
- "required": ["confirmation"],
5898
+ "required": ["confirmation", "successToast"],
5882
5899
  "additionalProperties": false
5883
5900
  },
5884
5901
  "fulfillmentProviders": {
@@ -1535,7 +1535,10 @@
1535
1535
  "stockLocations": {
1536
1536
  "domain": "Locations & Shipping",
1537
1537
  "list": {
1538
- "description": "Manage your store's stock locations and shipping options."
1538
+ "description": "Manage your store's stock locations and shipping options.",
1539
+ "noRecordsMessage": "No records",
1540
+ "noRecordsMessageEmpty": "No locations found",
1541
+ "noRecordsMessageFiltered": "No locations found matching the filters"
1539
1542
  },
1540
1543
  "create": {
1541
1544
  "header": "Create Stock Location",
@@ -1548,7 +1551,8 @@
1548
1551
  "successToast": "Location {{name}} was successfully updated."
1549
1552
  },
1550
1553
  "delete": {
1551
- "confirmation": "You are about to delete the stock location \"{{name}}\". This action cannot be undone."
1554
+ "confirmation": "You are about to delete the stock location \"{{name}}\". This action cannot be undone.",
1555
+ "successToast": "Location \"{{name}}\" was successfully deleted."
1552
1556
  },
1553
1557
  "fulfillmentProviders": {
1554
1558
  "header": "Fulfillment Providers",
@@ -62,7 +62,7 @@ export const EditLocationForm = ({ location }: EditLocationFormProps) => {
62
62
  },
63
63
  {
64
64
  onSuccess: () => {
65
- toast.success(t("stockLocations.edit.successToast"))
65
+ toast.success(t("stockLocations.edit.successToast", { name: name }))
66
66
  handleSuccess()
67
67
  },
68
68
  onError: (e) => {
@@ -1,2 +1 @@
1
- export { shippingListLoader as loader } from "./loader"
2
1
  export { LocationList as Component } from "./location-list"
@@ -1,34 +1,46 @@
1
1
  import { ShoppingBag, TruckFast } from "@medusajs/icons"
2
2
  import { Container, Heading } from "@medusajs/ui"
3
3
  import { useTranslation } from "react-i18next"
4
- import { useLoaderData } from "react-router-dom"
5
4
 
6
5
  import { useStockLocations } from "../../../hooks/api/stock-locations"
7
- import LocationListItem from "./components/location-list-item/location-list-item"
8
6
  import { LOCATION_LIST_FIELDS } from "./constants"
9
- import { shippingListLoader } from "./loader"
7
+ import { useLocationListTableColumns } from "./use-location-list-table-columns"
8
+ import { useLocationListTableQuery } from "./use-location-list-table-query"
10
9
 
10
+ import { DataTable } from "../../../components/data-table"
11
11
  import { SidebarLink } from "../../../components/common/sidebar-link/sidebar-link"
12
12
  import { TwoColumnPage } from "../../../components/layout/pages"
13
13
  import { useExtension } from "../../../providers/extension-provider"
14
- import { LocationListHeader } from "./components/location-list-header"
14
+ import { keepPreviousData } from "@tanstack/react-query"
15
+
16
+ const PAGE_SIZE = 20
17
+ const PREFIX = "loc"
15
18
 
16
19
  export function LocationList() {
17
- const initialData = useLoaderData() as Awaited<
18
- ReturnType<typeof shippingListLoader>
19
- >
20
+ const { t } = useTranslation()
21
+
22
+ const searchParams = useLocationListTableQuery({
23
+ pageSize: PAGE_SIZE,
24
+ prefix: PREFIX,
25
+ })
20
26
 
21
27
  const {
22
28
  stock_locations: stockLocations = [],
29
+ count,
23
30
  isError,
24
31
  error,
32
+ isLoading,
25
33
  } = useStockLocations(
26
34
  {
27
35
  fields: LOCATION_LIST_FIELDS,
36
+ ...searchParams,
28
37
  },
29
- { initialData }
38
+ {
39
+ placeholderData: keepPreviousData,
40
+ }
30
41
  )
31
42
 
43
+ const columns = useLocationListTableColumns()
32
44
  const { getWidgets } = useExtension()
33
45
 
34
46
  if (isError) {
@@ -46,12 +58,38 @@ export function LocationList() {
46
58
  showJSON
47
59
  >
48
60
  <TwoColumnPage.Main>
49
- <LocationListHeader />
50
- <div className="flex flex-col gap-3 lg:col-span-2">
51
- {stockLocations.map((location) => (
52
- <LocationListItem key={location.id} location={location} />
53
- ))}
54
- </div>
61
+ <Container className="flex flex-col divide-y p-0">
62
+ <DataTable
63
+ data={stockLocations}
64
+ columns={columns}
65
+ rowCount={count}
66
+ pageSize={PAGE_SIZE}
67
+ getRowId={(row) => row.id}
68
+ heading={t("stockLocations.domain")}
69
+ subHeading={t("stockLocations.list.description")}
70
+ emptyState={{
71
+ empty: {
72
+ heading: t("stockLocations.list.noRecordsMessage"),
73
+ description: t("stockLocations.list.noRecordsMessageEmpty"),
74
+ },
75
+ filtered: {
76
+ heading: t("stockLocations.list.noRecordsMessage"),
77
+ description: t("stockLocations.list.noRecordsMessageFiltered"),
78
+ },
79
+ }}
80
+ actions={[
81
+ {
82
+ label: t("actions.create"),
83
+ to: "create",
84
+ },
85
+ ]}
86
+ isLoading={isLoading}
87
+ rowHref={(row) => `/settings/locations/${row.id}`}
88
+ enableSearch={true}
89
+ prefix={PREFIX}
90
+ layout="fill"
91
+ />
92
+ </Container>
55
93
  </TwoColumnPage.Main>
56
94
  <TwoColumnPage.Sidebar>
57
95
  <LinksSection />
@@ -0,0 +1,185 @@
1
+ import { HttpTypes } from "@medusajs/types"
2
+ import { PencilSquare, Trash } from "@medusajs/icons"
3
+ import {
4
+ createDataTableColumnHelper,
5
+ StatusBadge,
6
+ toast,
7
+ usePrompt,
8
+ } from "@medusajs/ui"
9
+ import { useTranslation } from "react-i18next"
10
+ import { useMemo } from "react"
11
+ import { useNavigate } from "react-router-dom"
12
+ import { FetchError } from "@medusajs/js-sdk"
13
+
14
+ import { PlaceholderCell } from "../../../components/table/table-cells/common/placeholder-cell"
15
+ import { getFormattedAddress } from "../../../lib/addresses"
16
+ import { FulfillmentSetType } from "../common/constants"
17
+ import { queryClient } from "../../../lib/query-client"
18
+ import { stockLocationsQueryKeys } from "../../../hooks/api/stock-locations"
19
+ import { ListSummary } from "../../../components/common/list-summary"
20
+ import { sdk } from "../../../lib/client"
21
+
22
+ const columnHelper = createDataTableColumnHelper<HttpTypes.AdminStockLocation>()
23
+
24
+ export const useLocationListTableColumns = () => {
25
+ const { t } = useTranslation()
26
+ const navigate = useNavigate()
27
+ const prompt = usePrompt()
28
+
29
+ const handleDelete = async (location: HttpTypes.AdminStockLocation) => {
30
+ const result = await prompt({
31
+ title: t("general.areYouSure"),
32
+ description: t("stockLocations.delete.confirmation", {
33
+ name: location.name,
34
+ }),
35
+ confirmText: t("actions.remove"),
36
+ cancelText: t("actions.cancel"),
37
+ })
38
+
39
+ if (!result) {
40
+ return
41
+ }
42
+
43
+ try {
44
+ await sdk.admin.stockLocation.delete(location.id)
45
+ queryClient.invalidateQueries({
46
+ queryKey: stockLocationsQueryKeys.lists(),
47
+ })
48
+
49
+ queryClient.invalidateQueries({
50
+ queryKey: stockLocationsQueryKeys.detail(location.id),
51
+ })
52
+
53
+ toast.success(
54
+ t("stockLocations.delete.successToast", {
55
+ name: location.name,
56
+ })
57
+ )
58
+ } catch (e) {
59
+ toast.error((e as FetchError).message)
60
+ }
61
+ }
62
+
63
+ return useMemo(
64
+ () => [
65
+ columnHelper.accessor("name", {
66
+ header: t("fields.name"),
67
+ cell: ({ getValue }) => {
68
+ const name = getValue()
69
+ if (!name) {
70
+ return <PlaceholderCell />
71
+ }
72
+
73
+ return (
74
+ <span className="text-ui-fg-subtle text-small truncate">
75
+ {name}
76
+ </span>
77
+ )
78
+ },
79
+ }),
80
+ columnHelper.accessor("address", {
81
+ header: t("fields.address"),
82
+ cell: ({ getValue, row }) => {
83
+ const address = getValue()
84
+ const location = row.original
85
+
86
+ if (!address) {
87
+ return <PlaceholderCell />
88
+ }
89
+
90
+ return (
91
+ <div className="flex flex-col">
92
+ <span className="text-ui-fg-subtle text-small truncate">
93
+ {getFormattedAddress({
94
+ address: location.address as HttpTypes.AdminOrderAddress,
95
+ }).join(", ")}
96
+ </span>
97
+ </div>
98
+ )
99
+ },
100
+ }),
101
+ columnHelper.accessor("fulfillment_sets", {
102
+ id: "shipping_fulfillment",
103
+ header: t("stockLocations.fulfillmentSets.shipping.header"),
104
+ cell: ({ getValue }) => {
105
+ const fulfillmentSets = getValue()
106
+ const shippingSet = fulfillmentSets?.find(
107
+ (f) => f.type === FulfillmentSetType.Shipping
108
+ )
109
+ const fulfillmentSetExists = !!shippingSet
110
+
111
+ return (
112
+ <StatusBadge color={fulfillmentSetExists ? "green" : "grey"}>
113
+ {t(
114
+ fulfillmentSetExists ? "statuses.enabled" : "statuses.disabled"
115
+ )}
116
+ </StatusBadge>
117
+ )
118
+ },
119
+ }),
120
+ columnHelper.accessor("fulfillment_sets", {
121
+ id: "pickup_fulfillment",
122
+ header: t("stockLocations.fulfillmentSets.pickup.header"),
123
+ cell: ({ getValue }) => {
124
+ const fulfillmentSets = getValue()
125
+ const pickupSet = fulfillmentSets?.find(
126
+ (f) => f.type === FulfillmentSetType.Pickup
127
+ )
128
+ const fulfillmentSetExists = !!pickupSet
129
+
130
+ return (
131
+ <StatusBadge color={fulfillmentSetExists ? "green" : "grey"}>
132
+ {t(
133
+ fulfillmentSetExists ? "statuses.enabled" : "statuses.disabled"
134
+ )}
135
+ </StatusBadge>
136
+ )
137
+ },
138
+ }),
139
+ columnHelper.accessor("sales_channels", {
140
+ header: t("stockLocations.salesChannels.label"),
141
+ cell: ({ getValue }) => {
142
+ const salesChannels = getValue()
143
+
144
+ if (!salesChannels?.length) {
145
+ return <PlaceholderCell />
146
+ }
147
+
148
+ return (
149
+ <div className="flex items-center">
150
+ <ListSummary
151
+ inline
152
+ n={1}
153
+ list={salesChannels.map((s) => s.name)}
154
+ />
155
+ </div>
156
+ )
157
+ },
158
+ }),
159
+ columnHelper.action({
160
+ actions: (ctx) => {
161
+ const location = ctx.row.original
162
+ return [
163
+ [
164
+ {
165
+ icon: <PencilSquare />,
166
+ label: t("actions.edit"),
167
+ onClick: () => {
168
+ navigate(`/settings/locations/${location.id}/edit`)
169
+ },
170
+ },
171
+ ],
172
+ [
173
+ {
174
+ icon: <Trash />,
175
+ label: t("actions.delete"),
176
+ onClick: () => handleDelete(location),
177
+ },
178
+ ],
179
+ ]
180
+ },
181
+ }),
182
+ ],
183
+ []
184
+ )
185
+ }
@@ -0,0 +1,22 @@
1
+ import { HttpTypes } from "@medusajs/types"
2
+ import { useQueryParams } from "../../../hooks/use-query-params"
3
+
4
+ export const useLocationListTableQuery = ({
5
+ pageSize = 20,
6
+ prefix,
7
+ }: {
8
+ pageSize?: number
9
+ prefix?: string
10
+ }) => {
11
+ const queryObject = useQueryParams(["order", "offset", "q"], prefix)
12
+
13
+ const { offset, ...rest } = queryObject
14
+
15
+ const searchParams: HttpTypes.AdminStockLocationListParams = {
16
+ limit: pageSize,
17
+ offset: offset ? Number(offset) : 0,
18
+ ...rest,
19
+ }
20
+
21
+ return searchParams
22
+ }
@@ -1,4 +1,4 @@
1
- import { Button, Text, Tooltip, clx, usePrompt } from "@medusajs/ui"
1
+ import { Button, Text, Tooltip, clx, toast, usePrompt } from "@medusajs/ui"
2
2
  import { Collapsible as RadixCollapsible } from "radix-ui"
3
3
 
4
4
  import { PropsWithChildren, ReactNode, useMemo, useState } from "react"
@@ -785,7 +785,9 @@ const ReturnBody = ({
785
785
  return
786
786
  }
787
787
 
788
- await cancelReturnRequest()
788
+ await cancelReturnRequest().catch((error) => {
789
+ toast.error(error.message)
790
+ })
789
791
  }
790
792
 
791
793
  const numberOfItems = orderReturn.items.reduce((acc, item) => {
@@ -842,7 +844,9 @@ const ClaimBody = ({
842
844
  return
843
845
  }
844
846
 
845
- await cancelClaim()
847
+ await cancelClaim().catch((error) => {
848
+ toast.error(error.message)
849
+ })
846
850
  }
847
851
 
848
852
  const outboundItems = (claim.additional_items || []).reduce(
@@ -916,7 +920,9 @@ const ExchangeBody = ({
916
920
  return
917
921
  }
918
922
 
919
- await cancelExchange()
923
+ await cancelExchange().catch((error) => {
924
+ toast.error(error.message)
925
+ })
920
926
  }
921
927
 
922
928
  const outboundItems = (exchange.additional_items || []).reduce(
@@ -1015,7 +1021,9 @@ const TransferOrderRequestBody = ({
1015
1021
  return
1016
1022
  }
1017
1023
 
1018
- await cancelTransfer()
1024
+ await cancelTransfer().catch((error) => {
1025
+ toast.error(error.message)
1026
+ })
1019
1027
  }
1020
1028
 
1021
1029
  /**