From 58c68f67156e993255fbc25d91db15ae23bc95c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frane=20Poli=C4=87?= <16856471+fPolic@users.noreply.github.com> Date: Sat, 6 Apr 2024 17:41:54 +0200 Subject: [PATCH] feat(dashboard): Admin UI regions v2 (#6943) --- .changeset/hip-files-film.md | 6 + .../payment/payment-providers.spec.ts | 33 + .../public/locales/en-US/translation.json | 2 +- .../dashboard/scripts/generate-countries.js | 2 +- .../region/countries-cell/countries-cell.tsx | 31 +- .../payment-providers-cell.tsx | 25 +- .../dashboard/src/hooks/api/payments.ts | 24 + .../dashboard/src/hooks/api/regions.tsx | 3 +- .../columns/use-region-table-columns.tsx | 14 +- .../dashboard/src/lib/api-v2/index.ts | 3 +- .../dashboard/src/lib/api-v2/region.ts | 23 - .../dashboard/src/lib/api-v2/store.ts | 32 - .../dashboard/src/lib/api-v2/types/store.ts | 4 +- .../dashboard/src/lib/client/client.ts | 2 + .../dashboard/src/lib/client/payments.ts | 13 + .../admin-next/dashboard/src/lib/countries.ts | 8 +- .../dashboard/src/lib/currencies.ts | 2 +- .../dashboard/src/lib/format-provider.ts | 14 +- .../src/providers/router-provider/v2.tsx | 37 ++ .../create-shipping-option-form.tsx | 563 ------------------ .../create-shipping-option-form/index.ts | 1 - .../region-create-shipping-option/index.ts | 1 - .../region-create-shipping-option.tsx | 59 -- .../regions/region-create/region-create.tsx | 27 - .../region-shipping-option-section/index.ts | 1 - .../region-shipping-option-section.tsx | 173 ------ .../edit-shipping-option-form.tsx | 428 ------------- .../edit-shipping-option-form/index.ts | 1 - .../region-edit-shipping-option/index.ts | 1 - .../region-edit-shipping-option.tsx | 49 -- .../dashboard/src/types/api-responses.ts | 7 + .../regions/common}/constants.ts | 0 .../regions/common}/hooks/use-countries.tsx | 4 +- .../hooks/use-country-table-columns.tsx | 5 +- .../common}/hooks/use-country-table-query.tsx | 0 .../add-countries-form/add-countries-form.tsx | 22 +- .../components/add-countries-form/index.ts | 0 .../regions/region-add-countries/index.ts | 0 .../region-add-countries.tsx | 6 +- .../create-region-form/create-region-form.tsx | 120 +--- .../components/create-region-form/index.ts | 0 .../regions/region-create/index.ts | 0 .../regions/region-create/region-create.tsx | 29 + .../region-country-section/index.ts | 0 .../region-country-section.tsx | 35 +- .../region-general-section/index.ts | 0 .../region-general-section.tsx | 53 +- .../regions/region-detail/index.ts | 0 .../regions/region-detail/loader.ts | 3 +- .../regions/region-detail/region-detail.tsx | 16 +- .../edit-region-form/edit-region-form.tsx | 52 +- .../components/edit-region-form/index.ts | 0 .../regions/region-edit/index.ts | 0 .../regions/region-edit/region-edit.tsx | 21 +- .../components/region-list-table/index.ts | 0 .../region-list-table/region-list-table.tsx | 15 +- .../regions/region-list/index.ts | 0 .../regions/region-list/region-list.tsx | 0 .../add-currencies-form.tsx | 4 +- .../store-add-currencies.tsx | 4 +- .../medusa-js/src/resources/admin/regions.ts | 49 +- .../src/api-v2/admin/payments/middlewares.ts | 11 + .../admin/payments/payment-providers/route.ts | 30 + .../src/api-v2/admin/payments/query-config.ts | 9 + .../src/api-v2/admin/payments/validators.ts | 23 +- .../src/api-v2/admin/regions/validators.ts | 9 + .../src/api/routes/admin/regions/index.ts | 1 + .../payment/src/services/payment-module.ts | 20 + .../payment/src/services/payment-provider.ts | 17 + packages/types/src/payment/service.ts | 6 + packages/types/src/region/common.ts | 5 + packages/types/src/region/mutations.ts | 4 + 72 files changed, 475 insertions(+), 1687 deletions(-) create mode 100644 .changeset/hip-files-film.md create mode 100644 integration-tests/modules/__tests__/payment/payment-providers.spec.ts create mode 100644 packages/admin-next/dashboard/src/hooks/api/payments.ts delete mode 100644 packages/admin-next/dashboard/src/lib/api-v2/region.ts delete mode 100644 packages/admin-next/dashboard/src/lib/api-v2/store.ts create mode 100644 packages/admin-next/dashboard/src/lib/client/payments.ts delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/components/create-shipping-option-form/create-shipping-option-form.tsx delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/components/create-shipping-option-form/index.ts delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/index.ts delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/region-create-shipping-option.tsx delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-create/region-create.tsx delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-shipping-option-section/index.ts delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-shipping-option-section/region-shipping-option-section.tsx delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/components/edit-shipping-option-form/edit-shipping-option-form.tsx delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/components/edit-shipping-option-form/index.ts delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/index.ts delete mode 100644 packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/region-edit-shipping-option.tsx rename packages/admin-next/dashboard/src/{routes/regions/shared => v2-routes/regions/common}/constants.ts (100%) rename packages/admin-next/dashboard/src/{routes/regions/shared => v2-routes/regions/common}/hooks/use-countries.tsx (94%) rename packages/admin-next/dashboard/src/{routes/regions/shared => v2-routes/regions/common}/hooks/use-country-table-columns.tsx (83%) rename packages/admin-next/dashboard/src/{routes/regions/shared => v2-routes/regions/common}/hooks/use-country-table-query.tsx (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-add-countries/components/add-countries-form/add-countries-form.tsx (89%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-add-countries/components/add-countries-form/index.ts (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-add-countries/index.ts (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-add-countries/region-add-countries.tsx (72%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-create/components/create-region-form/create-region-form.tsx (78%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-create/components/create-region-form/index.ts (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-create/index.ts (100%) create mode 100644 packages/admin-next/dashboard/src/v2-routes/regions/region-create/region-create.tsx rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-detail/components/region-country-section/index.ts (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-detail/components/region-country-section/region-country-section.tsx (88%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-detail/components/region-general-section/index.ts (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-detail/components/region-general-section/region-general-section.tsx (65%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-detail/index.ts (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-detail/loader.ts (86%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-detail/region-detail.tsx (66%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-edit/components/edit-region-form/edit-region-form.tsx (75%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-edit/components/edit-region-form/index.ts (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-edit/index.ts (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-edit/region-edit.tsx (64%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-list/components/region-list-table/index.ts (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-list/components/region-list-table/region-list-table.tsx (88%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-list/index.ts (100%) rename packages/admin-next/dashboard/src/{routes => v2-routes}/regions/region-list/region-list.tsx (100%) create mode 100644 packages/medusa/src/api-v2/admin/payments/payment-providers/route.ts diff --git a/.changeset/hip-files-film.md b/.changeset/hip-files-film.md new file mode 100644 index 0000000000..44fdbfc8f7 --- /dev/null +++ b/.changeset/hip-files-film.md @@ -0,0 +1,6 @@ +--- +"@medusajs/medusa": patch +"@medusajs/types": patch +--- + +feat(medusa, types): list payment providers endpoint diff --git a/integration-tests/modules/__tests__/payment/payment-providers.spec.ts b/integration-tests/modules/__tests__/payment/payment-providers.spec.ts new file mode 100644 index 0000000000..bb9466056c --- /dev/null +++ b/integration-tests/modules/__tests__/payment/payment-providers.spec.ts @@ -0,0 +1,33 @@ +import { medusaIntegrationTestRunner } from "medusa-test-utils/dist" + +jest.setTimeout(50000) + +const env = { MEDUSA_FF_MEDUSA_V2: true } + +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Payment Providers", () => { + let appContainer + + beforeAll(async () => { + appContainer = getContainer() + }) + + it("should list payment providers", async () => { + let response = await api.get(`/admin/payments/payment-providers`) + + expect(response.status).toEqual(200) + expect(response.data.payment_providers).toEqual([ + expect.objectContaining({ + id: "pp_system_default_2", + }), + expect.objectContaining({ + id: "pp_system_default", + }), + ]) + expect(response.data.count).toEqual(2) + }) + }) + }, +}) diff --git a/packages/admin-next/dashboard/public/locales/en-US/translation.json b/packages/admin-next/dashboard/public/locales/en-US/translation.json index a0b8c7cab4..cfc472c920 100644 --- a/packages/admin-next/dashboard/public/locales/en-US/translation.json +++ b/packages/admin-next/dashboard/public/locales/en-US/translation.json @@ -817,7 +817,7 @@ "removeCountriesWarning_other": "You are about to remove {{count}} countries from the region. This action cannot be undone.", "removeCountryWarning": "You are about to remove the country {{name}} from the region. This action cannot be undone.", "taxInclusiveHint": "When enabled prices in the region will be tax inclusive.", - "providersHint": " Add which fulfillment and payment providers should be available in this region.", + "providersHint": " Add which payment providers should be available in this region.", "shippingOptions": "Shipping Options", "deleteShippingOptionWarning": "You are about to delete the shipping option {{name}}. This action cannot be undone.", "return": "Return", diff --git a/packages/admin-next/dashboard/scripts/generate-countries.js b/packages/admin-next/dashboard/scripts/generate-countries.js index 491310e677..ccce255034 100644 --- a/packages/admin-next/dashboard/scripts/generate-countries.js +++ b/packages/admin-next/dashboard/scripts/generate-countries.js @@ -24,7 +24,7 @@ async function generateCountries() { const dest = path.join(__dirname, "../src/lib/countries.ts") const destDir = path.dirname(dest) - const fileContent = `/** This file is auto-generated. Do not modify it manually. */\nimport type { Country } from "@medusajs/medusa"\n\nexport const countries: Omit[] = ${json}` + const fileContent = `/** This file is auto-generated. Do not modify it manually. */\nimport type { RegionCountryDTO } from "@medusajs/types"\n\nexport const countries: Omit[] = ${json}` if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }) diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/region/countries-cell/countries-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/region/countries-cell/countries-cell.tsx index 4cef4e3c6c..85ec0e0141 100644 --- a/packages/admin-next/dashboard/src/components/table/table-cells/region/countries-cell/countries-cell.tsx +++ b/packages/admin-next/dashboard/src/components/table/table-cells/region/countries-cell/countries-cell.tsx @@ -1,9 +1,12 @@ -import { Country } from "@medusajs/medusa" import { useTranslation } from "react-i18next" +import { RegionCountryDTO } from "@medusajs/types" + import { PlaceholderCell } from "../../common/placeholder-cell" +import { ListSummary } from "../../../../common/list-summary" +import { countries as COUNTRIES } from "../../../../../lib/countries" type CountriesCellProps = { - countries?: Country[] | null + countries?: RegionCountryDTO[] | null } export const CountriesCell = ({ countries }: CountriesCellProps) => { @@ -13,26 +16,14 @@ export const CountriesCell = ({ countries }: CountriesCellProps) => { return } - const displayValue = countries - .slice(0, 2) - .map((c) => c.display_name) - .join(", ") - - const additionalCountries = countries - .slice(2) - .map((c) => c.display_name).length - - const text = `${displayValue}${ - additionalCountries > 0 - ? ` ${t("general.plusCountMore", { - count: additionalCountries, - })}` - : "" - }` - return (
- {text} + + COUNTRIES.find((c) => c.iso_2 === country.iso_2)!.display_name + )} + />
) } diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/region/payment-providers-cell/payment-providers-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/region/payment-providers-cell/payment-providers-cell.tsx index 76e50cbe7a..c738534100 100644 --- a/packages/admin-next/dashboard/src/components/table/table-cells/region/payment-providers-cell/payment-providers-cell.tsx +++ b/packages/admin-next/dashboard/src/components/table/table-cells/region/payment-providers-cell/payment-providers-cell.tsx @@ -1,39 +1,26 @@ -import { PaymentProvider } from "@medusajs/medusa" import { useTranslation } from "react-i18next" +import { PaymentProviderDTO } from "@medusajs/types" + import { formatProvider } from "../../../../../lib/format-provider" import { PlaceholderCell } from "../../common/placeholder-cell" +import { ListSummary } from "../../../../common/list-summary" type PaymentProvidersCellProps = { - paymentProviders?: PaymentProvider[] | null + paymentProviders?: PaymentProviderDTO[] | null } export const PaymentProvidersCell = ({ paymentProviders, }: PaymentProvidersCellProps) => { - const { t } = useTranslation() - if (!paymentProviders || paymentProviders.length === 0) { return } - const displayValue = paymentProviders - .slice(0, 2) - .map((p) => formatProvider(p.id)) - .join(", ") - - const additionalProviders = paymentProviders.slice(2).length - - const text = `${displayValue}${ - additionalProviders > 0 - ? ` ${t("general.plusCountMore", { - count: additionalProviders, - })}` - : "" - }` + const displayValues = paymentProviders.map((p) => formatProvider(p.id)) return (
- {text} +
) } diff --git a/packages/admin-next/dashboard/src/hooks/api/payments.ts b/packages/admin-next/dashboard/src/hooks/api/payments.ts new file mode 100644 index 0000000000..f3bab9cafc --- /dev/null +++ b/packages/admin-next/dashboard/src/hooks/api/payments.ts @@ -0,0 +1,24 @@ +import { QueryKey, useQuery, UseQueryOptions } from "@tanstack/react-query" +import { PaymentProvidersListRes } from "../../types/api-responses" +import { client } from "../../lib/client" + +export const usePaymentProviders = ( + query?: Record, + options?: Omit< + UseQueryOptions< + PaymentProvidersListRes, + Error, + PaymentProvidersListRes, + QueryKey + >, + "queryKey" | "queryFn" + > +) => { + const { data, ...rest } = useQuery({ + queryFn: async () => client.payments.listPaymentProviders(query), + queryKey: [], + ...options, + }) + + return { ...data, ...rest } +} diff --git a/packages/admin-next/dashboard/src/hooks/api/regions.tsx b/packages/admin-next/dashboard/src/hooks/api/regions.tsx index f456fa3f9c..c009f8c2fb 100644 --- a/packages/admin-next/dashboard/src/hooks/api/regions.tsx +++ b/packages/admin-next/dashboard/src/hooks/api/regions.tsx @@ -20,6 +20,7 @@ const regionsQueryKeys = queryKeysFactory(REGIONS_QUERY_KEY) export const useRegion = ( id: string, + query?: Record, options?: Omit< UseQueryOptions, "queryFn" | "queryKey" @@ -27,7 +28,7 @@ export const useRegion = ( ) => { const { data, ...rest } = useQuery({ queryKey: regionsQueryKeys.detail(id), - queryFn: async () => client.regions.retrieve(id), + queryFn: async () => client.regions.retrieve(id, query), ...options, }) diff --git a/packages/admin-next/dashboard/src/hooks/table/columns/use-region-table-columns.tsx b/packages/admin-next/dashboard/src/hooks/table/columns/use-region-table-columns.tsx index e27ce172ca..059cedcd6d 100644 --- a/packages/admin-next/dashboard/src/hooks/table/columns/use-region-table-columns.tsx +++ b/packages/admin-next/dashboard/src/hooks/table/columns/use-region-table-columns.tsx @@ -1,15 +1,11 @@ -import { Region } from "@medusajs/medusa" import { createColumnHelper } from "@tanstack/react-table" import { useMemo } from "react" +import { RegionDTO } from "@medusajs/types" import { CountriesCell, CountriesHeader, } from "../../../components/table/table-cells/region/countries-cell" -import { - FulfillmentProvidersCell, - FulfillmentProvidersHeader, -} from "../../../components/table/table-cells/region/fulfillment-providers-cell" import { PaymentProvidersCell, PaymentProvidersHeader, @@ -19,7 +15,7 @@ import { RegionHeader, } from "../../../components/table/table-cells/region/region-cell" -const columnHelper = createColumnHelper() +const columnHelper = createColumnHelper() export const useRegionTableColumns = () => { return useMemo( @@ -38,12 +34,6 @@ export const useRegionTableColumns = () => { ), }), - columnHelper.accessor("fulfillment_providers", { - header: () => , - cell: ({ getValue }) => ( - - ), - }), ], [] ) diff --git a/packages/admin-next/dashboard/src/lib/api-v2/index.ts b/packages/admin-next/dashboard/src/lib/api-v2/index.ts index 4b23d2e698..be0a9d42f0 100644 --- a/packages/admin-next/dashboard/src/lib/api-v2/index.ts +++ b/packages/admin-next/dashboard/src/lib/api-v2/index.ts @@ -1,2 +1,3 @@ export * from "./auth" -export * from "./store" +export * from "./campaign" +export * from "./currencies" diff --git a/packages/admin-next/dashboard/src/lib/api-v2/region.ts b/packages/admin-next/dashboard/src/lib/api-v2/region.ts deleted file mode 100644 index 333c523334..0000000000 --- a/packages/admin-next/dashboard/src/lib/api-v2/region.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { RegionDTO } from "@medusajs/types" -import { adminRegionKeys, useAdminCustomQuery } from "medusa-react" -import { V2ListRes } from "./types/common" - -export const useV2Regions = (query?: any, options?: any) => { - const { data, ...rest } = useAdminCustomQuery( - "/regions", - adminRegionKeys.list(query), - query, - options - ) - - const typedData: { - regions: RegionDTO[] | undefined - } & V2ListRes = { - regions: data?.regions, - count: data?.count, - offset: data?.offset, - limit: data?.limit, - } - - return { ...typedData, ...rest } -} diff --git a/packages/admin-next/dashboard/src/lib/api-v2/store.ts b/packages/admin-next/dashboard/src/lib/api-v2/store.ts deleted file mode 100644 index b318a5c170..0000000000 --- a/packages/admin-next/dashboard/src/lib/api-v2/store.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { - adminStoreKeys, - useAdminCustomPost, - useAdminCustomQuery, -} from "medusa-react" -import { Store } from "./types/store" - -// TODO: Add types once we export V2 API types -export const useV2Store = (options?: any) => { - const { data, isLoading, isError, error, ...rest } = useAdminCustomQuery( - "/admin/stores", - adminStoreKeys.details(), - undefined, - options - ) - - const store = data?.stores[0] as Store | undefined - - let hasError = isError - let err: Error | null = error - - if (!isLoading && !isError && typeof store === "undefined") { - hasError = true - err = new Error("Store not found") - } - - return { store, isLoading, isError: hasError, error: err, ...rest } -} - -export const useV2UpdateStore = (id: string) => { - return useAdminCustomPost(`/admin/stores/${id}`, adminStoreKeys.detail(id)) -} diff --git a/packages/admin-next/dashboard/src/lib/api-v2/types/store.ts b/packages/admin-next/dashboard/src/lib/api-v2/types/store.ts index df47f8788a..5e1e9ee69f 100644 --- a/packages/admin-next/dashboard/src/lib/api-v2/types/store.ts +++ b/packages/admin-next/dashboard/src/lib/api-v2/types/store.ts @@ -1,5 +1,7 @@ -import { CurrencyDTO, StoreDTO } from "@medusajs/types" +import { CurrencyDTO, PaymentProviderDTO, StoreDTO } from "@medusajs/types" export type Store = StoreDTO & { default_currency: CurrencyDTO | null + currencies?: CurrencyDTO[] + payment_providers?: PaymentProviderDTO[] } diff --git a/packages/admin-next/dashboard/src/lib/client/client.ts b/packages/admin-next/dashboard/src/lib/client/client.ts index 6de8dee44f..c365a9a258 100644 --- a/packages/admin-next/dashboard/src/lib/client/client.ts +++ b/packages/admin-next/dashboard/src/lib/client/client.ts @@ -8,6 +8,7 @@ import { customers } from "./customers" import { invites } from "./invites" import { productTypes } from "./product-types" import { products } from "./products" +import { payments } from "./payments" import { promotions } from "./promotions" import { regions } from "./regions" import { salesChannels } from "./sales-channels" @@ -26,6 +27,7 @@ export const client = { currencies: currencies, collections: collections, promotions: promotions, + payments: payments, stores: stores, salesChannels: salesChannels, tags: tags, diff --git a/packages/admin-next/dashboard/src/lib/client/payments.ts b/packages/admin-next/dashboard/src/lib/client/payments.ts new file mode 100644 index 0000000000..d17fe09474 --- /dev/null +++ b/packages/admin-next/dashboard/src/lib/client/payments.ts @@ -0,0 +1,13 @@ +import { getRequest } from "./common" +import { PaymentProvidersListRes } from "../../types/api-responses" + +async function listPaymentProviders(query?: Record) { + return getRequest>( + `/admin/payments/payment-providers`, + query + ) +} + +export const payments = { + listPaymentProviders, +} diff --git a/packages/admin-next/dashboard/src/lib/countries.ts b/packages/admin-next/dashboard/src/lib/countries.ts index 8e4efca026..62ce8cea73 100644 --- a/packages/admin-next/dashboard/src/lib/countries.ts +++ b/packages/admin-next/dashboard/src/lib/countries.ts @@ -1,7 +1,7 @@ /** This file is auto-generated. Do not modify it manually. */ -import type { Country } from "@medusajs/medusa" +import type { RegionCountryDTO } from "@medusajs/types" -export const countries: Omit[] = [ +export const countries: Omit[] = [ { iso_2: "af", iso_3: "afg", @@ -888,8 +888,8 @@ export const countries: Omit[] = [ iso_2: "ly", iso_3: "lby", num_code: 434, - name: "LIBYAN ARAB JAMAHIRIYA", - display_name: "Libyan Arab Jamahiriya", + name: "LIBYA", + display_name: "Libya", }, { iso_2: "li", diff --git a/packages/admin-next/dashboard/src/lib/currencies.ts b/packages/admin-next/dashboard/src/lib/currencies.ts index 2f28d86f1d..b9d523659d 100644 --- a/packages/admin-next/dashboard/src/lib/currencies.ts +++ b/packages/admin-next/dashboard/src/lib/currencies.ts @@ -1,5 +1,5 @@ /** This file is auto-generated. Do not modify it manually. */ -type CurrencyInfo = { +export type CurrencyInfo = { code: string name: string symbol_native: string diff --git a/packages/admin-next/dashboard/src/lib/format-provider.ts b/packages/admin-next/dashboard/src/lib/format-provider.ts index ecd74fb1df..1c023682e3 100644 --- a/packages/admin-next/dashboard/src/lib/format-provider.ts +++ b/packages/admin-next/dashboard/src/lib/format-provider.ts @@ -1,12 +1,18 @@ /** * Providers only have an ID to identify them. This function formats the ID * into a human-readable string. + * + * Format example: pp_stripe-blik_dkk + * * @param id - The ID of the provider * @returns A formatted string */ export const formatProvider = (id: string) => { - return id - .split("-") - .map((s) => s.charAt(0).toUpperCase() + s.slice(1)) - .join(" ") + const [_, name, type] = id.split("_") + return ( + name + .split("-") + .map((s) => s.charAt(0).toUpperCase() + s.slice(1)) + .join(" ") + (type ? ` (${type})` : "") + ) } diff --git a/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx b/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx index cf56b7063d..34e14b5691 100644 --- a/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx +++ b/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx @@ -254,6 +254,43 @@ export const v2Routes: RouteObject[] = [ }, ], }, + { + path: "regions", + element: , + handle: { + crumb: () => "Regions", + }, + children: [ + { + path: "", + lazy: () => import("../../v2-routes/regions/region-list"), + children: [ + { + path: "create", + lazy: () => import("../../v2-routes/regions/region-create"), + }, + ], + }, + { + path: ":id", + lazy: () => import("../../v2-routes/regions/region-detail"), + handle: { + crumb: (data: AdminRegionsRes) => data.region.name, + }, + children: [ + { + path: "edit", + lazy: () => import("../../v2-routes/regions/region-edit"), + }, + { + path: "countries/add", + lazy: () => + import("../../v2-routes/regions/region-add-countries"), + }, + ], + }, + ], + }, { path: "store", lazy: () => import("../../v2-routes/store/store-detail"), diff --git a/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/components/create-shipping-option-form/create-shipping-option-form.tsx b/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/components/create-shipping-option-form/create-shipping-option-form.tsx deleted file mode 100644 index f14c7d5d12..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/components/create-shipping-option-form/create-shipping-option-form.tsx +++ /dev/null @@ -1,563 +0,0 @@ -import { zodResolver } from "@hookform/resolvers/zod" -import { - FulfillmentOption, - Region, - ShippingOptionRequirement, - ShippingProfile, -} from "@medusajs/medusa" -import { - Button, - CurrencyInput, - Heading, - Input, - RadioGroup, - Select, - Switch, - Text, - clx, -} from "@medusajs/ui" -import { useAdminCreateShippingOption } from "medusa-react" -import { useForm, useWatch } from "react-hook-form" -import { useTranslation } from "react-i18next" -import * as zod from "zod" -import { Form } from "../../../../../components/common/form" -import { IncludesTaxTooltip } from "../../../../../components/common/tax-badge/tax-badge" -import { - RouteFocusModal, - useRouteModal, -} from "../../../../../components/route-modal" -import { formatProvider } from "../../../../../lib/format-provider" -import { getDbAmount } from "../../../../../lib/money-amount-helpers" -import { ShippingOptionPriceType } from "../../../shared/constants" - -type CreateShippingOptionProps = { - region: Region - shippingProfiles: ShippingProfile[] - fulfillmentOptions: FulfillmentOption[] -} - -enum ShippingOptionType { - OUTBOUND = "outbound", - RETURN = "return", -} - -const CreateShippingOptionSchema = zod - .object({ - name: zod.string().min(1), - type: zod.nativeEnum(ShippingOptionType), - admin_only: zod.boolean(), - provider_id: zod.string().min(1), - profile_id: zod.string().min(1), - includes_tax: zod.boolean(), - price_type: zod.nativeEnum(ShippingOptionPriceType), - amount: zod - .union([zod.string(), zod.number()]) - .refine((value) => { - if (value === "") { - return false - } - - const num = Number(value) - - if (isNaN(num)) { - return false - } - - return num >= 0 - }, "Amount must be a positive number") - .optional(), - min_subtotal: zod - .union([zod.string(), zod.number()]) - .refine((value) => { - if (value === "") { - return true - } - - const num = Number(value) - - if (isNaN(num)) { - return false - } - - return num >= 0 - }, "Min. subtotal must be a positive number") - .optional(), - max_subtotal: zod - .union([zod.string(), zod.number()]) - .refine((value) => { - if (value === "") { - return true - } - - const num = Number(value) - - if (isNaN(num)) { - return false - } - - return num >= 0 - }, "Max. subtotal must be a positive number") - .optional(), - }) - .superRefine((data, ctx) => { - if (data.price_type === ShippingOptionPriceType.FLAT_RATE) { - if (typeof data.amount === "string" && data.amount === "") { - return ctx.addIssue({ - code: "custom", - message: "Amount is required", - path: ["amount"], - }) - } - } - }) - -export const CreateShippingOptionForm = ({ - region, - fulfillmentOptions, - shippingProfiles, -}: CreateShippingOptionProps) => { - const { t } = useTranslation() - const { handleSuccess } = useRouteModal() - - const form = useForm>({ - defaultValues: { - name: "", - type: ShippingOptionType.OUTBOUND, - admin_only: false, - provider_id: "", - profile_id: "", - price_type: ShippingOptionPriceType.FLAT_RATE, - includes_tax: false, - amount: "", - min_subtotal: "", - max_subtotal: "", - }, - resolver: zodResolver(CreateShippingOptionSchema), - }) - - const watchedPriceType = useWatch({ - control: form.control, - name: "price_type", - defaultValue: ShippingOptionPriceType.FLAT_RATE, - }) - - const isFlatRate = watchedPriceType === ShippingOptionPriceType.FLAT_RATE - - const includesTax = useWatch({ - control: form.control, - name: "includes_tax", - defaultValue: false, - }) - - const { mutateAsync, isLoading } = useAdminCreateShippingOption() - - const getPricePayload = (amount?: string | number) => { - if (!amount) { - return undefined - } - - const amountValue = typeof amount === "string" ? Number(amount) : amount - return getDbAmount(amountValue, region.currency_code) - } - - const handleSubmit = form.handleSubmit(async (values) => { - const { type, amount, min_subtotal, max_subtotal, ...rest } = values - - const amountPayload = getPricePayload(amount) - - const minSubtotalPayload = getPricePayload(min_subtotal) - const maxSubtotalPayload = getPricePayload(max_subtotal) - - const minSubtotalRequirement = minSubtotalPayload - ? { - amount: minSubtotalPayload, - type: "min_subtotal", - } - : undefined - - const maxSubtotalRequirement = maxSubtotalPayload - ? { - amount: maxSubtotalPayload, - type: "max_subtotal", - } - : undefined - - const requirements = [ - minSubtotalRequirement, - maxSubtotalRequirement, - ].filter(Boolean) as ShippingOptionRequirement[] - - await mutateAsync( - { - region_id: region.id, - data: {}, - is_return: type === ShippingOptionType.RETURN, - amount: isFlatRate ? amountPayload : undefined, - requirements: requirements.length ? requirements : undefined, - ...rest, - }, - { - onSuccess: () => { - handleSuccess() - }, - onError: (error) => { - console.error(error) - }, - } - ) - }) - - return ( - -
- -
- - - - -
-
- -
-
-
- - {t("regions.shippingOption.createShippingOption")} - - - {t("regions.shippingOption.createShippingOptionHint")} - -
- { - return ( - - {t("fields.type")} - - - - - - - - ) - }} - /> -
- { - return ( - -
-
- - {t("regions.shippingOption.availability.adminOnly")} - - - - -
- - {t( - "regions.shippingOption.availability.adminOnlyHint" - )} - -
- -
- ) - }} - /> -
- { - return ( - -
-
- - {t("fields.taxInclusivePricing")} - - - - -
- - {t("regions.shippingOption.taxInclusiveHint")} - - -
-
- ) - }} - /> -
-
-
- { - return ( - - {t("fields.name")} - - - - - - ) - }} - /> - { - return ( - - - {t("regions.shippingOption.priceType.label")} - - - - - - - ) - }} - /> - {isFlatRate && ( - { - return ( - - - } - > - {t("fields.price")} - - - - - - - ) - }} - /> - )} -
-
-
-
-
- { - return ( - - {t("fields.shippingProfile")} - - - - - - ) - }} - /> - { - return ( - - - {t("fields.fulfillmentProvider")} - - - - - - - ) - }} - /> -
-
-
-
-
- - {t("regions.shippingOption.requirements.label")} - - - {t("regions.shippingOption.requirements.hint")} - -
-
- { - return ( - - - } - optional - > - {t("fields.minSubtotal")} - - - - - - - ) - }} - /> - { - return ( - - - } - optional - > - {t("fields.maxSubtotal")} - - - - - - - ) - }} - /> -
-
-
-
- - - - ) -} diff --git a/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/components/create-shipping-option-form/index.ts b/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/components/create-shipping-option-form/index.ts deleted file mode 100644 index 70cf97cc0c..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/components/create-shipping-option-form/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./create-shipping-option-form" diff --git a/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/index.ts b/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/index.ts deleted file mode 100644 index b0de3f611e..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { RegionCreateShippingOption as Component } from "./region-create-shipping-option" diff --git a/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/region-create-shipping-option.tsx b/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/region-create-shipping-option.tsx deleted file mode 100644 index 816ac59015..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-create-shipping-option/region-create-shipping-option.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { - useAdminRegion, - useAdminRegionFulfillmentOptions, - useAdminShippingProfiles, -} from "medusa-react" -import { useParams } from "react-router-dom" -import { RouteFocusModal } from "../../../components/route-modal" -import { CreateShippingOptionForm } from "./components/create-shipping-option-form" - -export const RegionCreateShippingOption = () => { - const { id } = useParams() - - const { - region, - isLoading: isLoadingRegion, - isError: isRegionError, - error: regionError, - } = useAdminRegion(id!) - - const { - shipping_profiles, - isLoading: isLoadingProfiles, - isError: isProfilesError, - error: profileError, - } = useAdminShippingProfiles() - - const { - fulfillment_options, - isLoading: isLoadingOptions, - isError: isOptionsError, - error: optionsError, - } = useAdminRegionFulfillmentOptions(id!) - - const isLoading = isLoadingProfiles || isLoadingOptions || isLoadingRegion - - if (isRegionError) { - throw regionError - } - - if (isProfilesError) { - throw profileError - } - - if (isOptionsError) { - throw optionsError - } - - return ( - - {!isLoading && region && shipping_profiles && fulfillment_options && ( - - )} - - ) -} diff --git a/packages/admin-next/dashboard/src/routes/regions/region-create/region-create.tsx b/packages/admin-next/dashboard/src/routes/regions/region-create/region-create.tsx deleted file mode 100644 index 261de930bb..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-create/region-create.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { useAdminStore } from "medusa-react" -import { RouteFocusModal } from "../../../components/route-modal/route-focus-modal" -import { CreateRegionForm } from "./components/create-region-form" - -export const RegionCreate = () => { - const { store, isLoading, isError, error } = useAdminStore() - - const currencies = store?.currencies ?? [] - const paymentProviders = store?.payment_providers ?? [] - const fulfillmentProviders = store?.fulfillment_providers ?? [] - - if (isError) { - throw error - } - - return ( - - {!isLoading && store && ( - - )} - - ) -} diff --git a/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-shipping-option-section/index.ts b/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-shipping-option-section/index.ts deleted file mode 100644 index f7841f26fc..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-shipping-option-section/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./region-shipping-option-section" diff --git a/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-shipping-option-section/region-shipping-option-section.tsx b/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-shipping-option-section/region-shipping-option-section.tsx deleted file mode 100644 index 0ae150d1e3..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-shipping-option-section/region-shipping-option-section.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import { Region } from "@medusajs/medusa" -import { Container, Heading, usePrompt } from "@medusajs/ui" -import { - useAdminDeleteShippingOption, - useAdminShippingOptions, -} from "medusa-react" -import { useTranslation } from "react-i18next" - -import { PencilSquare, PlusMini, Trash } from "@medusajs/icons" -import { PricedShippingOption } from "@medusajs/medusa/dist/types/pricing" -import { createColumnHelper } from "@tanstack/react-table" -import { useMemo } from "react" -import { ActionMenu } from "../../../../../components/common/action-menu" -import { DataTable } from "../../../../../components/table/data-table" -import { useShippingOptionTableColumns } from "../../../../../hooks/table/columns/use-shipping-option-table-columns" -import { useShippingOptionTableFilters } from "../../../../../hooks/table/filters/use-shipping-option-table-filters" -import { useShippingOptionTableQuery } from "../../../../../hooks/table/query/use-shipping-option-table-query" -import { useDataTable } from "../../../../../hooks/use-data-table" - -type RegionShippingOptionSectionProps = { - region: Region -} - -const PAGE_SIZE = 10 - -export const RegionShippingOptionSection = ({ - region, -}: RegionShippingOptionSectionProps) => { - const { searchParams, raw } = useShippingOptionTableQuery({ - pageSize: PAGE_SIZE, - regionId: region.id, - }) - const { shipping_options, count, isError, error, isLoading } = - useAdminShippingOptions( - { - ...searchParams, - }, - { - keepPreviousData: true, - } - ) - - const filters = useShippingOptionTableFilters() - const columns = useColumns() - - const { table } = useDataTable({ - data: (shipping_options ?? []) as unknown as PricedShippingOption[], - columns, - count, - enablePagination: true, - getRowId: (row) => row.id!, - pageSize: PAGE_SIZE, - }) - - const { t } = useTranslation() - - if (isError) { - throw error - } - - return ( - -
- {t("regions.shippingOptions")} - , - to: "shipping-options/create", - }, - ], - }, - ]} - /> -
- -
- ) -} - -const ShippingOptionActions = ({ - shippingOption, -}: { - shippingOption: PricedShippingOption -}) => { - const { t } = useTranslation() - const prompt = usePrompt() - - const { mutateAsync } = useAdminDeleteShippingOption(shippingOption.id!) - - const handleDelete = async () => { - const res = await prompt({ - title: t("general.areYouSure"), - description: t("regions.deleteShippingOptionWarning", { - name: shippingOption.name, - }), - confirmText: t("actions.delete"), - cancelText: t("actions.cancel"), - }) - - if (!res) { - return - } - - await mutateAsync() - } - - return ( - , - }, - ], - }, - { - actions: [ - { - label: t("actions.delete"), - onClick: handleDelete, - icon: , - }, - ], - }, - ]} - /> - ) -} - -const columnHelper = createColumnHelper() - -const useColumns = () => { - const base = useShippingOptionTableColumns() - - return useMemo( - () => [ - ...base, - columnHelper.display({ - id: "actions", - cell: ({ row }) => { - return - }, - }), - ], - [base] - ) -} diff --git a/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/components/edit-shipping-option-form/edit-shipping-option-form.tsx b/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/components/edit-shipping-option-form/edit-shipping-option-form.tsx deleted file mode 100644 index fdfb1504cf..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/components/edit-shipping-option-form/edit-shipping-option-form.tsx +++ /dev/null @@ -1,428 +0,0 @@ -import { zodResolver } from "@hookform/resolvers/zod" -import { - Region, - ShippingOption, - ShippingOptionRequirement, -} from "@medusajs/medusa" -import { - Button, - CurrencyInput, - Input, - Select, - Switch, - Text, -} from "@medusajs/ui" -import { useAdminUpdateShippingOption } from "medusa-react" -import { useForm, useWatch } from "react-hook-form" -import { useTranslation } from "react-i18next" -import * as zod from "zod" - -import { Form } from "../../../../../components/common/form" -import { IncludesTaxTooltip } from "../../../../../components/common/tax-badge/tax-badge" -import { - RouteDrawer, - useRouteModal, -} from "../../../../../components/route-modal" -import { - getDbAmount, - getPresentationalAmount, -} from "../../../../../lib/money-amount-helpers" -import { ShippingOptionPriceType } from "../../../shared/constants" - -type EditShippingOptionFormProps = { - region: Region - shippingOption: ShippingOption -} - -const EditShippingOptionSchema = zod - .object({ - name: zod.string().min(1), - admin_only: zod.boolean(), - price_type: zod.nativeEnum(ShippingOptionPriceType), - includes_tax: zod.boolean(), - amount: zod - .union([zod.string(), zod.number()]) - .refine((value) => { - if (value === "") { - return false - } - - const num = Number(value) - - if (isNaN(num)) { - return false - } - - return num >= 0 - }, "Amount must be a positive number") - .optional(), - min_subtotal: zod - .union([zod.string(), zod.number()]) - .refine((value) => { - if (value === "") { - return true - } - - const num = Number(value) - - if (isNaN(num)) { - return false - } - - return num >= 0 - }, "Min. subtotal must be a positive number") - .optional(), - max_subtotal: zod - .union([zod.string(), zod.number()]) - .refine((value) => { - if (value === "") { - return true - } - - const num = Number(value) - - if (isNaN(num)) { - return false - } - - return num >= 0 - }, "Max. subtotal must be a positive number") - .optional(), - }) - .superRefine((data, ctx) => { - if (data.price_type === ShippingOptionPriceType.FLAT_RATE) { - if (typeof data.amount === "string" && data.amount === "") { - return ctx.addIssue({ - code: "custom", - message: "Amount is required", - path: ["amount"], - }) - } - } - }) - -export const EditShippingOptionForm = ({ - region, - shippingOption, -}: EditShippingOptionFormProps) => { - const { t } = useTranslation() - const { handleSuccess } = useRouteModal() - - const defaultAmount = shippingOption.amount - ? getPresentationalAmount(shippingOption.amount, region.currency_code) - : "" - - const defaultMinSubtotal = shippingOption.requirements.find( - (r) => r.type === "min_subtotal" - ) - const defaultMinSubtotalAmount = defaultMinSubtotal - ? getPresentationalAmount(defaultMinSubtotal.amount, region.currency_code) - : "" - - const defaultMaxSubtotal = shippingOption.requirements.find( - (r) => r.type === "max_subtotal" - ) - const defaultMaxSubtotalAmount = defaultMaxSubtotal - ? getPresentationalAmount(defaultMaxSubtotal.amount, region.currency_code) - : "" - - const form = useForm>({ - defaultValues: { - admin_only: shippingOption.admin_only, - name: shippingOption.name, - amount: defaultAmount, - max_subtotal: defaultMaxSubtotalAmount, - min_subtotal: defaultMinSubtotalAmount, - price_type: shippingOption.price_type, - includes_tax: shippingOption.includes_tax, - }, - resolver: zodResolver(EditShippingOptionSchema), - }) - - const watchedPriceType = useWatch({ - control: form.control, - name: "price_type", - defaultValue: ShippingOptionPriceType.FLAT_RATE, - }) - - const isFlatRate = watchedPriceType === ShippingOptionPriceType.FLAT_RATE - - const includesTax = useWatch({ - control: form.control, - name: "includes_tax", - }) - - const { mutateAsync, isLoading } = useAdminUpdateShippingOption( - shippingOption.id - ) - - const getPricePayload = (amount?: string | number) => { - if (!amount) { - return undefined - } - - const amountValue = typeof amount === "string" ? Number(amount) : amount - return getDbAmount(amountValue, region.currency_code) - } - - const handleSubmit = form.handleSubmit(async (values) => { - const { amount, min_subtotal, max_subtotal, ...rest } = values - - const amountPayload = getPricePayload(amount) - - const minSubtotalPayload = getPricePayload(min_subtotal) - const maxSubtotalPayload = getPricePayload(max_subtotal) - - const minSubtotalRequirement = minSubtotalPayload - ? { - amount: minSubtotalPayload, - type: "min_subtotal", - } - : undefined - - const maxSubtotalRequirement = maxSubtotalPayload - ? { - amount: maxSubtotalPayload, - type: "max_subtotal", - } - : undefined - - const requirements = [ - minSubtotalRequirement, - maxSubtotalRequirement, - ].filter(Boolean) as ShippingOptionRequirement[] - - await mutateAsync( - { - amount: amountPayload, - requirements, - ...rest, - }, - { - onSuccess: () => { - handleSuccess() - }, - } - ) - }) - - return ( - -
- - { - return ( - -
-
- - {t("regions.shippingOption.availability.adminOnly")} - - - - -
- - {t("regions.shippingOption.availability.adminOnlyHint")} - -
- -
- ) - }} - /> -
- { - return ( - -
-
- {t("fields.taxInclusivePricing")} - - - -
- {t("regions.taxInclusiveHint")} - -
-
- ) - }} - /> -
-
- { - return ( - - {t("fields.name")} - - - - - - ) - }} - /> - { - return ( - - - {t("regions.shippingOption.priceType.label")} - - - - - - - ) - }} - /> - {isFlatRate && ( - { - return ( - - } - > - {t("fields.price")} - - - - - - - ) - }} - /> - )} -
-
-
-
- - {t("regions.shippingOption.requirements.label")} - - - {t("regions.shippingOption.requirements.hint")} - -
-
- { - return ( - - } - optional - > - {t("fields.minSubtotal")} - - - - - - - ) - }} - /> - { - return ( - - } - optional - > - {t("fields.maxSubtotal")} - - - - - - - ) - }} - /> -
-
- - -
- - - - -
-
- - - ) -} diff --git a/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/components/edit-shipping-option-form/index.ts b/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/components/edit-shipping-option-form/index.ts deleted file mode 100644 index 0c64e93b32..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/components/edit-shipping-option-form/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./edit-shipping-option-form" diff --git a/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/index.ts b/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/index.ts deleted file mode 100644 index 359b8d4e83..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { RegionEditShippingOption as Component } from "./region-edit-shipping-option" diff --git a/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/region-edit-shipping-option.tsx b/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/region-edit-shipping-option.tsx deleted file mode 100644 index 366b65a321..0000000000 --- a/packages/admin-next/dashboard/src/routes/regions/region-edit-shipping-option/region-edit-shipping-option.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Heading } from "@medusajs/ui" -import { useAdminRegion, useAdminShippingOption } from "medusa-react" -import { useTranslation } from "react-i18next" -import { useParams } from "react-router-dom" -import { RouteDrawer } from "../../../components/route-modal" -import { EditShippingOptionForm } from "./components/edit-shipping-option-form" - -export const RegionEditShippingOption = () => { - const { id, so_id } = useParams() - const { t } = useTranslation() - - const { - region, - isLoading: isLoadingRegion, - isError: isRegionError, - error: regionError, - } = useAdminRegion(id!) - - const { - shipping_option, - isLoading: isLoadingOption, - isError: isOptionError, - error: optionError, - } = useAdminShippingOption(so_id!) - - const isLoading = isLoadingRegion || isLoadingOption - - if (isRegionError) { - throw regionError - } - - if (isOptionError) { - throw optionError - } - - return ( - - - {t("regions.shippingOption.editShippingOption")} - - {!isLoading && region && shipping_option && ( - - )} - - ) -} diff --git a/packages/admin-next/dashboard/src/types/api-responses.ts b/packages/admin-next/dashboard/src/types/api-responses.ts index cd64f62357..88c9226387 100644 --- a/packages/admin-next/dashboard/src/types/api-responses.ts +++ b/packages/admin-next/dashboard/src/types/api-responses.ts @@ -8,6 +8,7 @@ import { CurrencyDTO, CustomerDTO, InviteDTO, + PaymentProviderDTO, ProductCategoryDTO, ProductCollectionDTO, ProductDTO, @@ -122,6 +123,12 @@ export type TagsListRes = { tags: ProductTagDTO[] } & ListRes export type ProductTypeRes = { product_type: ProductTypeDTO } export type ProductTypeListRes = { product_types: ProductTypeDTO[] } & ListRes +// Payments + +export type PaymentProvidersListRes = { + payment_providers: PaymentProviderDTO[] +} + // Stock Locations export type ExtendedStockLocationDTO = StockLocationDTO & { address: StockLocationAddressDTO | null diff --git a/packages/admin-next/dashboard/src/routes/regions/shared/constants.ts b/packages/admin-next/dashboard/src/v2-routes/regions/common/constants.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/shared/constants.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/common/constants.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/shared/hooks/use-countries.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/common/hooks/use-countries.tsx similarity index 94% rename from packages/admin-next/dashboard/src/routes/regions/shared/hooks/use-countries.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/common/hooks/use-countries.tsx index 32ba79b90f..edbec55659 100644 --- a/packages/admin-next/dashboard/src/routes/regions/shared/hooks/use-countries.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/common/hooks/use-countries.tsx @@ -1,5 +1,5 @@ -import { Country } from "@medusajs/medusa" import { json } from "react-router-dom" +import { RegionCountryDTO } from "@medusajs/types" const acceptedOrderKeys = ["name", "code"] @@ -14,7 +14,7 @@ export const useCountries = ({ limit, offset = 0, }: { - countries: Country[] + countries: RegionCountryDTO[] limit: number offset?: number order?: string diff --git a/packages/admin-next/dashboard/src/routes/regions/shared/hooks/use-country-table-columns.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/common/hooks/use-country-table-columns.tsx similarity index 83% rename from packages/admin-next/dashboard/src/routes/regions/shared/hooks/use-country-table-columns.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/common/hooks/use-country-table-columns.tsx index 9dbe7e46ef..6a98ae8f9d 100644 --- a/packages/admin-next/dashboard/src/routes/regions/shared/hooks/use-country-table-columns.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/common/hooks/use-country-table-columns.tsx @@ -1,9 +1,10 @@ -import { Country } from "@medusajs/medusa" +import { RegionCountryDTO } from "@medusajs/types" + import { createColumnHelper } from "@tanstack/react-table" import { useMemo } from "react" import { useTranslation } from "react-i18next" -const columnHelper = createColumnHelper() +const columnHelper = createColumnHelper() export const useCountryTableColumns = () => { const { t } = useTranslation() diff --git a/packages/admin-next/dashboard/src/routes/regions/shared/hooks/use-country-table-query.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/common/hooks/use-country-table-query.tsx similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/shared/hooks/use-country-table-query.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/common/hooks/use-country-table-query.tsx diff --git a/packages/admin-next/dashboard/src/routes/regions/region-add-countries/components/add-countries-form/add-countries-form.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-add-countries/components/add-countries-form/add-countries-form.tsx similarity index 89% rename from packages/admin-next/dashboard/src/routes/regions/region-add-countries/components/add-countries-form/add-countries-form.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/region-add-countries/components/add-countries-form/add-countries-form.tsx index 12151a5b78..9149a16d52 100644 --- a/packages/admin-next/dashboard/src/routes/regions/region-add-countries/components/add-countries-form/add-countries-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-add-countries/components/add-countries-form/add-countries-form.tsx @@ -1,5 +1,4 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { Country, Region } from "@medusajs/medusa" import { ColumnDef, RowSelectionState, @@ -11,7 +10,7 @@ import { useTranslation } from "react-i18next" import * as zod from "zod" import { Button, Checkbox } from "@medusajs/ui" -import { useAdminUpdateRegion } from "medusa-react" +import { RegionCountryDTO, RegionDTO } from "@medusajs/types" import { RouteFocusModal, useRouteModal, @@ -19,12 +18,13 @@ import { import { DataTable } from "../../../../../components/table/data-table" import { useDataTable } from "../../../../../hooks/use-data-table" import { countries as staticCountries } from "../../../../../lib/countries" -import { useCountries } from "../../../shared/hooks/use-countries" -import { useCountryTableColumns } from "../../../shared/hooks/use-country-table-columns" -import { useCountryTableQuery } from "../../../shared/hooks/use-country-table-query" +import { useCountries } from "../../../common/hooks/use-countries" +import { useCountryTableColumns } from "../../../common/hooks/use-country-table-columns" +import { useCountryTableQuery } from "../../../common/hooks/use-country-table-query" +import { useUpdateRegion } from "../../../../../hooks/api/regions.tsx" type AddCountriesFormProps = { - region: Region + region: RegionDTO } const AddCountriesSchema = zod.object({ @@ -66,12 +66,12 @@ export const AddCountriesForm = ({ region }: AddCountriesFormProps) => { countries: staticCountries.map((c, i) => ({ display_name: c.display_name, name: c.name, - id: i, + id: i as any, iso_2: c.iso_2, iso_3: c.iso_3, num_code: c.num_code, region_id: null, - region: {} as Region, + region: {} as RegionDTO, })), ...searchParams, }) @@ -98,7 +98,7 @@ export const AddCountriesForm = ({ region }: AddCountriesFormProps) => { prefix: PREFIX, }) - const { mutateAsync, isLoading } = useAdminUpdateRegion(region.id) + const { mutateAsync, isLoading } = useUpdateRegion(region.id) const handleSubmit = form.handleSubmit(async (values) => { const payload = [ @@ -155,7 +155,7 @@ export const AddCountriesForm = ({ region }: AddCountriesFormProps) => { ) } -const columnHelper = createColumnHelper() +const columnHelper = createColumnHelper() const useColumns = () => { const base = useCountryTableColumns() @@ -196,5 +196,5 @@ const useColumns = () => { ...base, ], [base] - ) as ColumnDef[] + ) as ColumnDef[] } diff --git a/packages/admin-next/dashboard/src/routes/regions/region-add-countries/components/add-countries-form/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-add-countries/components/add-countries-form/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-add-countries/components/add-countries-form/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-add-countries/components/add-countries-form/index.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/region-add-countries/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-add-countries/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-add-countries/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-add-countries/index.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/region-add-countries/region-add-countries.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-add-countries/region-add-countries.tsx similarity index 72% rename from packages/admin-next/dashboard/src/routes/regions/region-add-countries/region-add-countries.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/region-add-countries/region-add-countries.tsx index 4bb3e92371..197b393c1e 100644 --- a/packages/admin-next/dashboard/src/routes/regions/region-add-countries/region-add-countries.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-add-countries/region-add-countries.tsx @@ -1,12 +1,14 @@ -import { useAdminRegion } from "medusa-react" import { useParams } from "react-router-dom" import { RouteFocusModal } from "../../../components/route-modal" import { AddCountriesForm } from "./components/add-countries-form" +import { useRegion } from "../../../hooks/api/regions" export const RegionAddCountries = () => { const { id } = useParams() - const { region, isLoading, isError, error } = useAdminRegion(id!) + const { region, isLoading, isError, error } = useRegion(id!, { + fields: "*payment_providers", + }) if (isError) { throw error diff --git a/packages/admin-next/dashboard/src/routes/regions/region-create/components/create-region-form/create-region-form.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-create/components/create-region-form/create-region-form.tsx similarity index 78% rename from packages/admin-next/dashboard/src/routes/regions/region-create/components/create-region-form/create-region-form.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/region-create/components/create-region-form/create-region-form.tsx index d466a58063..72fce11122 100644 --- a/packages/admin-next/dashboard/src/routes/regions/region-create/components/create-region-form/create-region-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-create/components/create-region-form/create-region-form.tsx @@ -1,11 +1,5 @@ import { zodResolver } from "@hookform/resolvers/zod" import { XMarkMini } from "@medusajs/icons" -import { - Country, - Currency, - FulfillmentProvider, - PaymentProvider, -} from "@medusajs/medusa" import { Button, Checkbox, @@ -17,29 +11,33 @@ import { clx, } from "@medusajs/ui" import { RowSelectionState, createColumnHelper } from "@tanstack/react-table" -import { useAdminCreateRegion } from "medusa-react" import { useMemo, useState } from "react" import { useForm, useWatch } from "react-hook-form" import { useTranslation } from "react-i18next" import * as zod from "zod" +import { RegionCountryDTO, PaymentProviderDTO } from "@medusajs/types" + import { Combobox } from "../../../../../components/common/combobox" import { Form } from "../../../../../components/common/form" import { SplitView } from "../../../../../components/layout/split-view" -import { useRouteModal } from "../../../../../components/route-modal" -import { RouteFocusModal } from "../../../../../components/route-modal/route-focus-modal" +import { + useRouteModal, + RouteFocusModal, +} from "../../../../../components/route-modal" import { DataTable } from "../../../../../components/table/data-table" import { useDataTable } from "../../../../../hooks/use-data-table" import { countries as staticCountries } from "../../../../../lib/countries" import { formatProvider } from "../../../../../lib/format-provider" -import { useCountries } from "../../../shared/hooks/use-countries" -import { useCountryTableColumns } from "../../../shared/hooks/use-country-table-columns" -import { useCountryTableQuery } from "../../../shared/hooks/use-country-table-query" +import { useCountries } from "../../../common/hooks/use-countries" +import { useCountryTableColumns } from "../../../common/hooks/use-country-table-columns" +import { useCountryTableQuery } from "../../../common/hooks/use-country-table-query" +import { CurrencyInfo } from "../../../../../lib/currencies" +import { useCreateRegion } from "../../../../../hooks/api/regions" type CreateRegionFormProps = { - currencies: Currency[] - paymentProviders: PaymentProvider[] - fulfillmentProviders: FulfillmentProvider[] + currencies: CurrencyInfo[] + paymentProviders: PaymentProviderDTO[] } const CreateRegionSchema = zod.object({ @@ -47,22 +45,7 @@ const CreateRegionSchema = zod.object({ currency_code: zod.string().min(2, "Select a currency"), includes_tax: zod.boolean(), countries: zod.array(zod.object({ code: zod.string(), name: zod.string() })), - fulfillment_providers: zod.array(zod.string()).min(1), payment_providers: zod.array(zod.string()).min(1), - tax_rate: zod.union([zod.string(), zod.number()]).refine((value) => { - if (value === "") { - return false - } - - const num = Number(value) - - if (num >= 0 && num <= 100) { - return true - } - - return false - }, "Tax rate must be a number between 0 and 100"), - tax_code: zod.string().optional(), }) const PREFIX = "cr" @@ -71,7 +54,6 @@ const PAGE_SIZE = 50 export const CreateRegionForm = ({ currencies, paymentProviders, - fulfillmentProviders, }: CreateRegionFormProps) => { const [open, setOpen] = useState(false) const [rowSelection, setRowSelection] = useState({}) @@ -83,10 +65,7 @@ export const CreateRegionForm = ({ currency_code: "", includes_tax: false, countries: [], - fulfillment_providers: [], payment_providers: [], - tax_code: "", - tax_rate: "", }, resolver: zodResolver(CreateRegionSchema), }) @@ -99,7 +78,7 @@ export const CreateRegionForm = ({ const { t } = useTranslation() - const { mutateAsync, isLoading } = useAdminCreateRegion() + const { mutateAsync, isLoading } = useCreateRegion() const handleSubmit = form.handleSubmit(async (values) => { await mutateAsync( @@ -107,14 +86,8 @@ export const CreateRegionForm = ({ name: values.name, countries: values.countries.map((c) => c.code), currency_code: values.currency_code, - fulfillment_providers: values.fulfillment_providers, payment_providers: values.payment_providers, - tax_rate: - typeof values.tax_rate === "string" - ? Number(values.tax_rate) - : values.tax_rate, - tax_code: values.tax_code, - includes_tax: values.includes_tax, + automatic_taxes: values.includes_tax, }, { onSuccess: ({ region }) => { @@ -290,40 +263,6 @@ export const CreateRegionForm = ({ }} />
-
- { - return ( - - {t("fields.taxRate")} - - - - - - ) - }} - /> - { - return ( - - - {t("fields.taxCode")} - - - - - - - ) - }} - /> -
)}
- +
@@ -422,29 +361,6 @@ export const CreateRegionForm = ({ ) }} /> - { - return ( - - - {t("fields.fulfillmentProviders")} - - - ({ - label: formatProvider(fp.id), - value: fp.id, - }))} - {...field} - /> - - - - ) - }} - />
@@ -481,7 +397,7 @@ export const CreateRegionForm = ({ ) } -const columnHelper = createColumnHelper() +const columnHelper = createColumnHelper() const useColumns = () => { const base = useCountryTableColumns() diff --git a/packages/admin-next/dashboard/src/routes/regions/region-create/components/create-region-form/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-create/components/create-region-form/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-create/components/create-region-form/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-create/components/create-region-form/index.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/region-create/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-create/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-create/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-create/index.ts diff --git a/packages/admin-next/dashboard/src/v2-routes/regions/region-create/region-create.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-create/region-create.tsx new file mode 100644 index 0000000000..7c87e90a05 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-create/region-create.tsx @@ -0,0 +1,29 @@ +import { RouteFocusModal } from "../../../components/route-modal/route-focus-modal" +import { CreateRegionForm } from "./components/create-region-form" +import { currencies } from "../../../lib/currencies" +import { usePaymentProviders } from "../../../hooks/api/payments" +import { useStore } from "../../../hooks/api/store" + +export const RegionCreate = () => { + const { store, isLoading, isError, error } = useStore() + + const storeCurrencies = (store?.supported_currency_codes ?? []).map( + (code) => currencies[code.toUpperCase()] + ) + const { payment_providers: paymentProviders = [] } = usePaymentProviders() + + if (isError) { + throw error + } + + return ( + + {!isLoading && store && ( + + )} + + ) +} diff --git a/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-country-section/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-country-section/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-country-section/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-country-section/index.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-country-section/region-country-section.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-country-section/region-country-section.tsx similarity index 88% rename from packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-country-section/region-country-section.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-country-section/region-country-section.tsx index 82bfad3967..26d1121dd3 100644 --- a/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-country-section/region-country-section.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-country-section/region-country-section.tsx @@ -1,32 +1,23 @@ import { PlusMini, Trash } from "@medusajs/icons" -import { Region } from "@medusajs/medusa" import { Checkbox, Container, Heading, usePrompt } from "@medusajs/ui" +import { RegionCountryDTO, RegionDTO } from "@medusajs/types" import { ColumnDef, RowSelectionState, createColumnHelper, } from "@tanstack/react-table" -import { useAdminUpdateRegion } from "medusa-react" import { useMemo, useState } from "react" import { useTranslation } from "react-i18next" import { ActionMenu } from "../../../../../components/common/action-menu" import { DataTable } from "../../../../../components/table/data-table" import { useDataTable } from "../../../../../hooks/use-data-table" -import { useCountries } from "../../../shared/hooks/use-countries" -import { useCountryTableColumns } from "../../../shared/hooks/use-country-table-columns" -import { useCountryTableQuery } from "../../../shared/hooks/use-country-table-query" +import { useCountries } from "../../../common/hooks/use-countries" +import { useCountryTableColumns } from "../../../common/hooks/use-country-table-columns" +import { useCountryTableQuery } from "../../../common/hooks/use-country-table-query" +import { useUpdateRegion } from "../../../../../hooks/api/regions.tsx" type RegionCountrySectionProps = { - region: Region -} - -type Country = { - id: number - iso_2: string - iso_3: string - num_code: number - name: string - display_name: string + region: RegionDTO } const PREFIX = "c" @@ -67,7 +58,7 @@ export const RegionCountrySection = ({ region }: RegionCountrySectionProps) => { }, }) - const { mutateAsync } = useAdminUpdateRegion(region.id) + const { mutateAsync } = useUpdateRegion(region.id) const handleRemoveCountries = async () => { const ids = Object.keys(rowSelection).filter((k) => rowSelection[k]) @@ -140,12 +131,12 @@ const CountryActions = ({ country, region, }: { - country: Country - region: Region + country: RegionCountryDTO + region: RegionDTO }) => { const { t } = useTranslation() const prompt = usePrompt() - const { mutateAsync } = useAdminUpdateRegion(region.id) + const { mutateAsync } = useUpdateRegion(region.id) const payload = region.countries ?.filter((c) => c.iso_2 !== country.iso_2) @@ -189,7 +180,7 @@ const CountryActions = ({ ) } -const columnHelper = createColumnHelper() +const columnHelper = createColumnHelper() const useColumns = () => { const base = useCountryTableColumns() @@ -228,12 +219,12 @@ const useColumns = () => { columnHelper.display({ id: "actions", cell: ({ row, table }) => { - const { region } = table.options.meta as { region: Region } + const { region } = table.options.meta as { region: RegionDTO } return }, }), ], [base] - ) as ColumnDef[] + ) as ColumnDef[] } diff --git a/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-general-section/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-general-section/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-general-section/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-general-section/index.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-general-section/region-general-section.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-general-section/region-general-section.tsx similarity index 65% rename from packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-general-section/region-general-section.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-general-section/region-general-section.tsx index 66b18e9b1b..0666df1062 100644 --- a/packages/admin-next/dashboard/src/routes/regions/region-detail/components/region-general-section/region-general-section.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-general-section/region-general-section.tsx @@ -1,13 +1,17 @@ -import { BuildingTax, PencilSquare, Trash } from "@medusajs/icons" -import { Region } from "@medusajs/medusa" +import { PencilSquare, Trash } from "@medusajs/icons" +import { RegionDTO } from "@medusajs/types" import { Badge, Container, Heading, Text, usePrompt } from "@medusajs/ui" -import { useAdminDeleteRegion } from "medusa-react" import { useTranslation } from "react-i18next" + import { ActionMenu } from "../../../../../components/common/action-menu" import { formatProvider } from "../../../../../lib/format-provider" +import { currencies } from "../../../../../lib/currencies" +import { useDeleteRegion } from "../../../../../hooks/api/regions.tsx" +import { ListSummary } from "../../../../../components/common/list-summary" +import { useNavigate } from "react-router-dom" type RegionGeneralSectionProps = { - region: Region + region: RegionDTO } export const RegionGeneralSection = ({ region }: RegionGeneralSectionProps) => { @@ -28,7 +32,7 @@ export const RegionGeneralSection = ({ region }: RegionGeneralSectionProps) => { {region.currency_code} - {region.currency?.name} + {currencies[region.currency_code.toUpperCase()].name}
@@ -36,33 +40,24 @@ export const RegionGeneralSection = ({ region }: RegionGeneralSectionProps) => { {t("fields.paymentProviders")} - - {region.payment_providers.length > 0 - ? region.payment_providers - .map((p) => formatProvider(p.id)) - .join(", ") - : "-"} - -
-
- - {t("fields.fulfillmentProviders")} - - - {region.fulfillment_providers.length > 0 - ? region.fulfillment_providers - .map((p) => formatProvider(p.id)) - .join(", ") - : "-"} - +
+ {region.payment_providers?.length > 0 ? ( + formatProvider(p.id))} + /> + ) : ( + "-" + )} +
) } -const RegionActions = ({ region }: { region: Region }) => { +const RegionActions = ({ region }: { region: RegionDTO }) => { + const navigate = useNavigate() const { t } = useTranslation() - const { mutateAsync } = useAdminDeleteRegion(region.id) + const { mutateAsync } = useDeleteRegion(region.id) const prompt = usePrompt() const handleDelete = async () => { @@ -82,6 +77,7 @@ const RegionActions = ({ region }: { region: Region }) => { } await mutateAsync(undefined) + navigate("/settings/regions", { replace: true }) } return ( @@ -94,11 +90,6 @@ const RegionActions = ({ region }: { region: Region }) => { label: t("actions.edit"), to: `/settings/regions/${region.id}/edit`, }, - { - icon: , - label: "Tax settings", - to: `/settings/taxes/${region.id}`, - }, ], }, { diff --git a/packages/admin-next/dashboard/src/routes/regions/region-detail/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-detail/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-detail/index.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/region-detail/loader.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/loader.ts similarity index 86% rename from packages/admin-next/dashboard/src/routes/regions/region-detail/loader.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-detail/loader.ts index f49ba72e67..97e8701061 100644 --- a/packages/admin-next/dashboard/src/routes/regions/region-detail/loader.ts +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/loader.ts @@ -7,7 +7,8 @@ import { medusa, queryClient } from "../../../lib/medusa" const regionQuery = (id: string) => ({ queryKey: adminRegionKeys.detail(id), - queryFn: async () => medusa.admin.regions.retrieve(id), + queryFn: async () => + medusa.admin.regions.retrieve(id, { fields: "*payment_providers" }), }) export const regionLoader = async ({ params }: LoaderFunctionArgs) => { diff --git a/packages/admin-next/dashboard/src/routes/regions/region-detail/region-detail.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/region-detail.tsx similarity index 66% rename from packages/admin-next/dashboard/src/routes/regions/region-detail/region-detail.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/region-detail/region-detail.tsx index 3f47372f13..1b5fe35a7d 100644 --- a/packages/admin-next/dashboard/src/routes/regions/region-detail/region-detail.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/region-detail.tsx @@ -1,11 +1,9 @@ -import { useAdminRegion } from "medusa-react" import { Outlet, useLoaderData, useParams } from "react-router-dom" -import { JsonViewSection } from "../../../components/common/json-view-section" import { RegionCountrySection } from "./components/region-country-section" import { RegionGeneralSection } from "./components/region-general-section" -import { RegionShippingOptionSection } from "./components/region-shipping-option-section" import { regionLoader } from "./loader" +import { useRegion } from "../../../hooks/api/regions" export const RegionDetail = () => { const initialData = useLoaderData() as Awaited< @@ -13,9 +11,13 @@ export const RegionDetail = () => { > const { id } = useParams() - const { region, isLoading, isError, error } = useAdminRegion(id!, { - initialData, - }) + const { region, isLoading, isError, error } = useRegion( + id!, + { fields: "*payment_providers" }, + { + initialData, + } + ) // TODO: Move to loading.tsx and set as Suspense fallback for the route if (isLoading || !region) { @@ -30,8 +32,6 @@ export const RegionDetail = () => {
- -
) diff --git a/packages/admin-next/dashboard/src/routes/regions/region-edit/components/edit-region-form/edit-region-form.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-edit/components/edit-region-form/edit-region-form.tsx similarity index 75% rename from packages/admin-next/dashboard/src/routes/regions/region-edit/components/edit-region-form/edit-region-form.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/region-edit/components/edit-region-form/edit-region-form.tsx index 13ed33e53f..c4b11fcfc1 100644 --- a/packages/admin-next/dashboard/src/routes/regions/region-edit/components/edit-region-form/edit-region-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-edit/components/edit-region-form/edit-region-form.tsx @@ -1,14 +1,8 @@ -import { - Currency, - FulfillmentProvider, - PaymentProvider, - Region, -} from "@medusajs/medusa" import { Button, Input, Select, Text } from "@medusajs/ui" -import { useAdminUpdateRegion } from "medusa-react" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import * as zod from "zod" +import { PaymentProviderDTO, RegionDTO } from "@medusajs/types" import { Combobox } from "../../../../../components/common/combobox" import { Form } from "../../../../../components/common/form" @@ -17,26 +11,25 @@ import { useRouteModal, } from "../../../../../components/route-modal" import { formatProvider } from "../../../../../lib/format-provider" +import { CurrencyInfo } from "../../../../../lib/currencies" +import { useUpdateRegion } from "../../../../../hooks/api/regions.tsx" type EditRegionFormProps = { - region: Region - currencies: Currency[] - paymentProviders: PaymentProvider[] - fulfillmentProviders: FulfillmentProvider[] + region: RegionDTO + currencies: CurrencyInfo[] + paymentProviders: PaymentProviderDTO[] } const EditRegionSchema = zod.object({ name: zod.string().min(1), currency_code: zod.string(), payment_providers: zod.array(zod.string()), - fulfillment_providers: zod.array(zod.string()), }) export const EditRegionForm = ({ region, currencies, paymentProviders, - fulfillmentProviders, }: EditRegionFormProps) => { const { t } = useTranslation() const { handleSuccess } = useRouteModal() @@ -44,20 +37,18 @@ export const EditRegionForm = ({ const form = useForm>({ defaultValues: { name: region.name, - currency_code: region.currency_code, - fulfillment_providers: region.fulfillment_providers.map((fp) => fp.id), - payment_providers: region.payment_providers.map((pp) => pp.id), + currency_code: region.currency_code.toUpperCase(), + payment_providers: region.payment_providers?.map((pp) => pp.id) || [], }, }) - const { mutateAsync, isLoading } = useAdminUpdateRegion(region.id) + const { mutateAsync, isLoading } = useUpdateRegion(region.id) const handleSubmit = form.handleSubmit(async (values) => { await mutateAsync( { name: values.name, - currency_code: values.currency_code, - fulfillment_providers: values.fulfillment_providers, + currency_code: values.currency_code.toLowerCase(), payment_providers: values.payment_providers, }, { @@ -146,29 +137,6 @@ export const EditRegionForm = ({ ) }} /> - { - return ( - - - {t("fields.fulfillmentProviders")} - - - ({ - label: formatProvider(fp.id), - value: fp.id, - }))} - {...field} - /> - - - - ) - }} - /> diff --git a/packages/admin-next/dashboard/src/routes/regions/region-edit/components/edit-region-form/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-edit/components/edit-region-form/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-edit/components/edit-region-form/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-edit/components/edit-region-form/index.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/region-edit/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-edit/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-edit/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-edit/index.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/region-edit/region-edit.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-edit/region-edit.tsx similarity index 64% rename from packages/admin-next/dashboard/src/routes/regions/region-edit/region-edit.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/region-edit/region-edit.tsx index 165a63676e..dab4bfa9e6 100644 --- a/packages/admin-next/dashboard/src/routes/regions/region-edit/region-edit.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-edit/region-edit.tsx @@ -1,10 +1,13 @@ import { Heading } from "@medusajs/ui" -import { useAdminRegion, useAdminStore } from "medusa-react" import { useTranslation } from "react-i18next" import { useParams } from "react-router-dom" import { RouteDrawer } from "../../../components/route-modal" import { EditRegionForm } from "./components/edit-region-form" +import { currencies } from "../../../lib/currencies" +import { useRegion } from "../../../hooks/api/regions" +import { usePaymentProviders } from "../../../hooks/api/payments" +import { useStore } from "../../../hooks/api/store" export const RegionEdit = () => { const { t } = useTranslation() @@ -15,20 +18,23 @@ export const RegionEdit = () => { isLoading: isRegionLoading, isError: isRegionError, error: regionError, - } = useAdminRegion(id!) + } = useRegion(id!, { fields: "*payment_providers" }) const { store, isLoading: isStoreLoading, isError: isStoreError, error: storeError, - } = useAdminStore() + } = useStore() const isLoading = isRegionLoading || isStoreLoading - const currencies = store?.currencies || [] - const paymentProviders = store?.payment_providers || [] - const fulfillmentProviders = store?.fulfillment_providers || [] + const storeCurrencies = (store?.supported_currency_codes ?? []).map( + (code) => currencies[code.toUpperCase()] + ) + const { payment_providers: paymentProviders = [] } = usePaymentProviders({ + limit: 999, + }) if (isRegionError) { throw regionError @@ -46,9 +52,8 @@ export const RegionEdit = () => { {!isLoading && region && ( )} diff --git a/packages/admin-next/dashboard/src/routes/regions/region-list/components/region-list-table/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-list/components/region-list-table/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-list/components/region-list-table/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-list/components/region-list-table/index.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/region-list/components/region-list-table/region-list-table.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-list/components/region-list-table/region-list-table.tsx similarity index 88% rename from packages/admin-next/dashboard/src/routes/regions/region-list/components/region-list-table/region-list-table.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/region-list/components/region-list-table/region-list-table.tsx index ab52fea0de..b07fef8289 100644 --- a/packages/admin-next/dashboard/src/routes/regions/region-list/components/region-list-table/region-list-table.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-list/components/region-list-table/region-list-table.tsx @@ -1,11 +1,10 @@ import { PencilSquare, Trash } from "@medusajs/icons" -import { Region } from "@medusajs/medusa" import { Button, Container, Heading, usePrompt } from "@medusajs/ui" import { createColumnHelper } from "@tanstack/react-table" -import { useAdminDeleteRegion, useAdminRegions } from "medusa-react" import { useMemo } from "react" import { useTranslation } from "react-i18next" import { Link } from "react-router-dom" +import { RegionDTO } from "@medusajs/types" import { ActionMenu } from "../../../../../components/common/action-menu" import { DataTable } from "../../../../../components/table/data-table" @@ -13,6 +12,7 @@ import { useRegionTableColumns } from "../../../../../hooks/table/columns/use-re import { useRegionTableFilters } from "../../../../../hooks/table/filters/use-region-table-filters" import { useRegionTableQuery } from "../../../../../hooks/table/query/use-region-table-query" import { useDataTable } from "../../../../../hooks/use-data-table" +import { useDeleteRegion, useRegions } from "../../../../../hooks/api/regions" const PAGE_SIZE = 20 @@ -20,9 +20,10 @@ export const RegionListTable = () => { const { t } = useTranslation() const { searchParams, raw } = useRegionTableQuery({ pageSize: PAGE_SIZE }) - const { regions, count, isLoading, isError, error } = useAdminRegions( + const { regions, count, isLoading, isError, error } = useRegions( { ...searchParams, + fields: "*payment_providers", }, { keepPreviousData: true, @@ -33,7 +34,7 @@ export const RegionListTable = () => { const columns = useColumns() const { table } = useDataTable({ - data: (regions ?? []) as Region[], + data: (regions ?? []) as RegionDTO[], columns, count, enablePagination: true, @@ -72,11 +73,11 @@ export const RegionListTable = () => { ) } -const RegionActions = ({ region }: { region: Region }) => { +const RegionActions = ({ region }: { region: RegionDTO }) => { const { t } = useTranslation() const prompt = usePrompt() - const { mutateAsync } = useAdminDeleteRegion(region.id) + const { mutateAsync } = useDeleteRegion(region.id) const handleDelete = async () => { const res = await prompt({ @@ -123,7 +124,7 @@ const RegionActions = ({ region }: { region: Region }) => { ) } -const columnHelper = createColumnHelper() +const columnHelper = createColumnHelper() const useColumns = () => { const base = useRegionTableColumns() diff --git a/packages/admin-next/dashboard/src/routes/regions/region-list/index.ts b/packages/admin-next/dashboard/src/v2-routes/regions/region-list/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-list/index.ts rename to packages/admin-next/dashboard/src/v2-routes/regions/region-list/index.ts diff --git a/packages/admin-next/dashboard/src/routes/regions/region-list/region-list.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-list/region-list.tsx similarity index 100% rename from packages/admin-next/dashboard/src/routes/regions/region-list/region-list.tsx rename to packages/admin-next/dashboard/src/v2-routes/regions/region-list/region-list.tsx diff --git a/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/components/add-currencies-form/add-currencies-form.tsx b/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/components/add-currencies-form/add-currencies-form.tsx index 3654ac6ce9..efb874d7cf 100644 --- a/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/components/add-currencies-form/add-currencies-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/components/add-currencies-form/add-currencies-form.tsx @@ -19,9 +19,9 @@ import { } from "../../../../../components/route-modal" import { DataTable } from "../../../../../components/table/data-table" import { useDataTable } from "../../../../../hooks/use-data-table" -import { useV2UpdateStore } from "../../../../../lib/api-v2" import { useCurrenciesTableColumns } from "../../../common/hooks/use-currencies-table-columns" import { useCurrenciesTableQuery } from "../../../common/hooks/use-currencies-table-query" +import { useUpdateStore } from "../../../../../hooks/api/store" type AddCurrenciesFormProps = { store: StoreDTO @@ -95,7 +95,7 @@ export const AddCurrenciesForm = ({ store }: AddCurrenciesFormProps) => { }, }) - const { mutateAsync, isLoading: isMutating } = useV2UpdateStore(store.id) + const { mutateAsync, isLoading: isMutating } = useUpdateStore(store.id) const handleSubmit = form.handleSubmit(async (data) => { const currencies = Array.from( diff --git a/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/store-add-currencies.tsx b/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/store-add-currencies.tsx index e9c5c1644b..08d408b149 100644 --- a/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/store-add-currencies.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/store-add-currencies.tsx @@ -1,9 +1,9 @@ import { RouteFocusModal } from "../../../components/route-modal" import { AddCurrenciesForm } from "./components/add-currencies-form/add-currencies-form" -import { useV2Store } from "../../../lib/api-v2" +import { useStore } from "../../../hooks/api/store" export const StoreAddCurrencies = () => { - const { store, isLoading, isError, error } = useV2Store({}) + const { store, isLoading, isError, error } = useStore({}) if (isError) { throw error diff --git a/packages/medusa-js/src/resources/admin/regions.ts b/packages/medusa-js/src/resources/admin/regions.ts index 8f4d1c2103..006a623e6b 100644 --- a/packages/medusa-js/src/resources/admin/regions.ts +++ b/packages/medusa-js/src/resources/admin/regions.ts @@ -9,6 +9,7 @@ import { AdminPostRegionsRegionFulfillmentProvidersReq, AdminPostRegionsRegionPaymentProvidersReq, AdminGetRegionsRegionFulfillmentOptionsRes, + AdminGetRegionsRegionParams, } from "@medusajs/medusa" import qs from "qs" import { ResponsePromise } from "../../typings" @@ -17,12 +18,12 @@ import BaseResource from "../base" /** * This class is used to send requests to [Admin Region API Routes](https://docs.medusajs.com/api/admin#regions). All its method * are available in the JS Client under the `medusa.admin.regions` property. - * + * * All methods in this class require {@link AdminAuthResource.createSession | user authentication}. - * + * * Regions are different countries or geographical regions that the commerce store serves customers in. * Admins can manage these regions, their providers, and more. - * + * * Related Guide: [How to manage regions](https://docs.medusajs.com/modules/regions-and-currencies/admin/manage-regions). */ class AdminRegionsResource extends BaseResource { @@ -31,7 +32,7 @@ class AdminRegionsResource extends BaseResource { * @param {AdminPostRegionsReq} payload - The region to create. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the region's details. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -68,7 +69,7 @@ class AdminRegionsResource extends BaseResource { * @param {AdminPostRegionsRegionReq} payload - The attributes to update in the region. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the region's details. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -94,7 +95,7 @@ class AdminRegionsResource extends BaseResource { * @param {string} id - The region's ID. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the deletion operation's details. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -115,9 +116,10 @@ class AdminRegionsResource extends BaseResource { /** * Retrieve a region's details. * @param {string} id - The region's ID. + * @param query - Query params * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the region's details. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -129,9 +131,16 @@ class AdminRegionsResource extends BaseResource { */ retrieve( id: string, + query?: AdminGetRegionsRegionParams, customHeaders: Record = {} ): ResponsePromise { - const path = `/admin/regions/${id}` + let path = `/admin/regions/${id}` + + if (query) { + const queryString = qs.stringify(query) + path = `/admin/regions/${id}?${queryString}` + } + return this.client.request("GET", path, undefined, {}, customHeaders) } @@ -140,10 +149,10 @@ class AdminRegionsResource extends BaseResource { * @param {AdminGetRegionsParams} query - Filters and pagination configurations to apply on the retrieved regions. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the list of regions with pagination fields. - * + * * @example * To list regions: - * + * * ```ts * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -153,9 +162,9 @@ class AdminRegionsResource extends BaseResource { * console.log(regions.length); * }) * ``` - * + * * By default, only the first `50` records are retrieved. You can control pagination by specifying the `limit` and `offset` properties: - * + * * ```ts * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -189,7 +198,7 @@ class AdminRegionsResource extends BaseResource { * @param {AdminPostRegionsRegionCountriesReq} payload - The country to add. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the region's details. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -216,7 +225,7 @@ class AdminRegionsResource extends BaseResource { * @param {string} country_code - The code of the country to delete from the region. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the region's details. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -241,7 +250,7 @@ class AdminRegionsResource extends BaseResource { * @param {AdminPostRegionsRegionFulfillmentProvidersReq} payload - The fulfillment provider to add. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the region's details. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -268,7 +277,7 @@ class AdminRegionsResource extends BaseResource { * @param {string} provider_id - The ID of the fulfillment provider to delete from the region. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the region's details. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -292,7 +301,7 @@ class AdminRegionsResource extends BaseResource { * @param {string} id - The region's ID. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the list of fulfillment options. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -316,7 +325,7 @@ class AdminRegionsResource extends BaseResource { * @param {AdminPostRegionsRegionPaymentProvidersReq} payload - The payment provider to add. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the region's details. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) @@ -339,11 +348,11 @@ class AdminRegionsResource extends BaseResource { /** * Delete a payment provider from a region. The payment provider will still be available for usage in other regions. - * @param {string} id - The region's ID. + * @param {string} id - The region's ID. * @param {string} provider_id - The ID of the payment provider to delete from the region. * @param {Record} customHeaders - Custom headers to attach to the request. * @returns {ResponsePromise} Resolves to the region's details. - * + * * @example * import Medusa from "@medusajs/medusa-js" * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) diff --git a/packages/medusa/src/api-v2/admin/payments/middlewares.ts b/packages/medusa/src/api-v2/admin/payments/middlewares.ts index 80f740068d..ac72d3004e 100644 --- a/packages/medusa/src/api-v2/admin/payments/middlewares.ts +++ b/packages/medusa/src/api-v2/admin/payments/middlewares.ts @@ -4,6 +4,7 @@ import { authenticate } from "../../../utils/authenticate-middleware" import * as queryConfig from "./query-config" import { AdminGetPaymentsParams, + AdminGetPaymentsPaymentProvidersParams, AdminPostPaymentsCapturesReq, AdminPostPaymentsRefundsReq, } from "./validators" @@ -24,6 +25,16 @@ export const adminPaymentRoutesMiddlewares: MiddlewareRoute[] = [ ), ], }, + { + method: ["GET"], + matcher: "/admin/payments/payment-providers", + middlewares: [ + transformQuery( + AdminGetPaymentsPaymentProvidersParams, + queryConfig.listTransformPaymentProvidersQueryConfig + ), + ], + }, { method: ["GET"], matcher: "/admin/payments/:id", diff --git a/packages/medusa/src/api-v2/admin/payments/payment-providers/route.ts b/packages/medusa/src/api-v2/admin/payments/payment-providers/route.ts new file mode 100644 index 0000000000..a0b9bef1f6 --- /dev/null +++ b/packages/medusa/src/api-v2/admin/payments/payment-providers/route.ts @@ -0,0 +1,30 @@ +import { ModuleRegistrationName } from "@medusajs/modules-sdk" + +import { IPaymentModuleService } from "@medusajs/types" +import { + AuthenticatedMedusaRequest, + MedusaResponse, +} from "../../../../types/routing" +import { AdminGetPaymentsPaymentProvidersParams } from "../validators" + +export const GET = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse +) => { + const paymentModule = req.scope.resolve( + ModuleRegistrationName.PAYMENT + ) + + const [payment_providers, count] = + await paymentModule.listAndCountPaymentProviders(req.filterableFields, { + skip: req.listConfig.skip, + take: req.listConfig.take, + }) + + res.status(200).json({ + count, + payment_providers, + offset: req.listConfig.skip, + limit: req.listConfig.take, + }) +} diff --git a/packages/medusa/src/api-v2/admin/payments/query-config.ts b/packages/medusa/src/api-v2/admin/payments/query-config.ts index e0e79c7b03..7206c43056 100644 --- a/packages/medusa/src/api-v2/admin/payments/query-config.ts +++ b/packages/medusa/src/api-v2/admin/payments/query-config.ts @@ -28,3 +28,12 @@ export const retrieveTransformQueryConfig = { allowedRelations: allowedAdminPaymentRelations, isList: false, } + +export const defaultAdminPaymentPaymentProviderFields = ["id", "is_enabled"] + +export const listTransformPaymentProvidersQueryConfig = { + defaultFields: defaultAdminPaymentPaymentProviderFields, + defaultRelations: [], + allowedRelations: [], + isList: true, +} diff --git a/packages/medusa/src/api-v2/admin/payments/validators.ts b/packages/medusa/src/api-v2/admin/payments/validators.ts index 69d474b30c..59b1c1d55d 100644 --- a/packages/medusa/src/api-v2/admin/payments/validators.ts +++ b/packages/medusa/src/api-v2/admin/payments/validators.ts @@ -1,5 +1,5 @@ import { Type } from "class-transformer" -import { IsInt, IsOptional, ValidateNested } from "class-validator" +import { IsBoolean, IsInt, IsOptional, ValidateNested } from "class-validator" import { DateComparisonOperator, FindParams, @@ -56,3 +56,24 @@ export class AdminPostPaymentsRefundsReq { @IsOptional() amount?: number } + +export class AdminGetPaymentsPaymentProvidersParams extends extendedFindParamsMixin( + { + limit: 20, + offset: 0, + } +) { + /** + * IDs to filter users by. + */ + @IsOptional() + @IsType([String, [String]]) + id?: string | string[] + + /** + * Filter providers by `enabled` flag + */ + @IsBoolean() + @IsOptional() + is_enabled?: boolean +} diff --git a/packages/medusa/src/api-v2/admin/regions/validators.ts b/packages/medusa/src/api-v2/admin/regions/validators.ts index 833739030d..67621c0649 100644 --- a/packages/medusa/src/api-v2/admin/regions/validators.ts +++ b/packages/medusa/src/api-v2/admin/regions/validators.ts @@ -2,6 +2,7 @@ import { OperatorMap } from "@medusajs/types" import { Type } from "class-transformer" import { IsArray, + IsBoolean, IsObject, IsOptional, IsString, @@ -87,6 +88,10 @@ export class AdminPostRegionsReq { @IsOptional() countries?: string[] + @IsBoolean() + @IsOptional() + automatic_taxes?: boolean + @IsObject() @IsOptional() metadata?: Record @@ -110,6 +115,10 @@ export class AdminPostRegionsRegionReq { @IsOptional() countries?: string[] + @IsBoolean() + @IsOptional() + automatic_taxes?: boolean + @IsObject() @IsOptional() metadata?: Record diff --git a/packages/medusa/src/api/routes/admin/regions/index.ts b/packages/medusa/src/api/routes/admin/regions/index.ts index 98cbef6bde..c564b3e224 100644 --- a/packages/medusa/src/api/routes/admin/regions/index.ts +++ b/packages/medusa/src/api/routes/admin/regions/index.ts @@ -231,3 +231,4 @@ export * from "./add-payment-provider" export * from "./create-region" export * from "./list-regions" export * from "./update-region" +export * from "./get-region" diff --git a/packages/payment/src/services/payment-module.ts b/packages/payment/src/services/payment-module.ts index c44802af22..136b05dbf9 100644 --- a/packages/payment/src/services/payment-module.ts +++ b/packages/payment/src/services/payment-module.ts @@ -733,4 +733,24 @@ export default class PaymentModuleService< } ) } + + @InjectManager("baseRepository_") + async listAndCountPaymentProviders( + filters: FilterablePaymentProviderProps = {}, + config: FindConfig = {}, + @MedusaContext() sharedContext?: Context + ): Promise<[PaymentProviderDTO[], number]> { + const [providers, count] = await this.paymentProviderService_.listAndCount( + filters, + config, + sharedContext + ) + + return [ + await this.baseRepository_.serialize(providers, { + populate: true, + }), + count, + ] + } } diff --git a/packages/payment/src/services/payment-provider.ts b/packages/payment/src/services/payment-provider.ts index cf1f8f8c9b..048d77af9b 100644 --- a/packages/payment/src/services/payment-provider.ts +++ b/packages/payment/src/services/payment-provider.ts @@ -71,6 +71,23 @@ export default class PaymentProviderService { ) } + @InjectManager("paymentProviderRepository_") + async listAndCount( + filters: FilterablePaymentProviderProps, + config: FindConfig, + @MedusaContext() sharedContext?: Context + ): Promise<[PaymentProvider[], number]> { + const queryOptions = ModulesSdkUtils.buildQuery( + filters, + config + ) + + return await this.paymentProviderRepository_.findAndCount( + queryOptions, + sharedContext + ) + } + retrieveProvider(providerId: string): IPaymentProvider { try { return this.container_[providerId] as IPaymentProvider diff --git a/packages/types/src/payment/service.ts b/packages/types/src/payment/service.ts index dba2019055..15cce66886 100644 --- a/packages/types/src/payment/service.ts +++ b/packages/types/src/payment/service.ts @@ -701,6 +701,12 @@ export interface IPaymentModuleService extends IModuleService { sharedContext?: Context ): Promise + listAndCountPaymentProviders( + filters?: FilterablePaymentProviderProps, + config?: FindConfig, + sharedContext?: Context + ): Promise<[PaymentProviderDTO[], number]> + /** * This method retrieves a paginated list of captures based on optional filters and configuration. * diff --git a/packages/types/src/region/common.ts b/packages/types/src/region/common.ts index d9b24d70fc..5a14aa2cb6 100644 --- a/packages/types/src/region/common.ts +++ b/packages/types/src/region/common.ts @@ -1,4 +1,5 @@ import { BaseFilterable, OperatorMap } from "../dal" +import { PaymentProviderDTO } from "../payment" /** * The region details. @@ -28,6 +29,10 @@ export interface RegionDTO { * The countries of the region. */ countries: RegionCountryDTO[] + /** + * Payment providers available in the region + */ + payment_providers: PaymentProviderDTO[] /** * Holds custom data in key-value pairs. diff --git a/packages/types/src/region/mutations.ts b/packages/types/src/region/mutations.ts index 4c6bf2cc88..df4c5389e0 100644 --- a/packages/types/src/region/mutations.ts +++ b/packages/types/src/region/mutations.ts @@ -18,6 +18,10 @@ export interface CreateRegionDTO { * The region's countries. */ countries?: string[] + /** + * The region's payment providers. + */ + payment_providers?: string[] /** * Holds custom data in key-value pairs. */