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 a6cfc68e25..a4b222ca3d 100644 --- a/packages/admin-next/dashboard/public/locales/en-US/translation.json +++ b/packages/admin-next/dashboard/public/locales/en-US/translation.json @@ -854,7 +854,7 @@ } }, "taxes": { - "domain": "Taxes", + "domain": "Tax Regions", "countries": { "taxCountriesHint": "Tax settings apply to the listed countries." }, diff --git a/packages/admin-next/dashboard/src/hooks/api/tax-regions.tsx b/packages/admin-next/dashboard/src/hooks/api/tax-regions.tsx new file mode 100644 index 0000000000..b98230d3d7 --- /dev/null +++ b/packages/admin-next/dashboard/src/hooks/api/tax-regions.tsx @@ -0,0 +1,53 @@ +import { QueryKey, UseQueryOptions, useQuery } from "@tanstack/react-query" +import { client } from "../../lib/client" +import { queryKeysFactory } from "../../lib/query-key-factory" +import { + AdminTaxRegionResponse, + AdminTaxRegionListResponse, +} from "@medusajs/types" + +const TAX_REGIONS_QUERY_KEY = "tax_regions" as const +const taxRegionsQueryKeys = queryKeysFactory(TAX_REGIONS_QUERY_KEY) + +export const useTaxRegion = ( + id: string, + query?: Record, + options?: Omit< + UseQueryOptions< + AdminTaxRegionResponse, + Error, + AdminTaxRegionResponse, + QueryKey + >, + "queryFn" | "queryKey" + > +) => { + const { data, ...rest } = useQuery({ + queryKey: taxRegionsQueryKeys.detail(id), + queryFn: async () => client.taxes.retrieveTaxRegion(id, query), + ...options, + }) + + return { ...data, ...rest } +} + +export const useTaxRegions = ( + query?: Record, + options?: Omit< + UseQueryOptions< + AdminTaxRegionListResponse, + Error, + AdminTaxRegionListResponse, + QueryKey + >, + "queryFn" | "queryKey" + > +) => { + const { data, ...rest } = useQuery({ + queryFn: () => client.taxes.listTaxRegions(query), + queryKey: taxRegionsQueryKeys.list(query), + ...options, + }) + + return { ...data, ...rest } +} diff --git a/packages/admin-next/dashboard/src/hooks/table/query/use-tax-region-table-query copy.tsx b/packages/admin-next/dashboard/src/hooks/table/query/use-tax-region-table-query copy.tsx new file mode 100644 index 0000000000..29ac40c7a6 --- /dev/null +++ b/packages/admin-next/dashboard/src/hooks/table/query/use-tax-region-table-query copy.tsx @@ -0,0 +1,32 @@ +import { useQueryParams } from "../../use-query-params" + +type UseTaxRegionTableQueryProps = { + prefix?: string + pageSize?: number +} + +export const useTaxRegionTableQuery = ({ + prefix, + pageSize = 20, +}: UseTaxRegionTableQueryProps) => { + const queryObject = useQueryParams( + ["offset", "q", "order", "created_at", "updated_at"], + prefix + ) + + const { offset, q, order, created_at, updated_at } = queryObject + + const searchParams = { + limit: pageSize, + offset: offset ? Number(offset) : 0, + order, + created_at: created_at ? JSON.parse(created_at) : undefined, + updated_at: updated_at ? JSON.parse(updated_at) : undefined, + q, + } + + return { + searchParams, + raw: queryObject, + } +} diff --git a/packages/admin-next/dashboard/src/lib/client/client.ts b/packages/admin-next/dashboard/src/lib/client/client.ts index c365a9a258..c10ad98d07 100644 --- a/packages/admin-next/dashboard/src/lib/client/client.ts +++ b/packages/admin-next/dashboard/src/lib/client/client.ts @@ -6,15 +6,16 @@ import { collections } from "./collections" import { currencies } from "./currencies" import { customers } from "./customers" import { invites } from "./invites" +import { payments } from "./payments" 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" import { stockLocations } from "./stock-locations" import { stores } from "./stores" import { tags } from "./tags" +import { taxes } from "./taxes" import { users } from "./users" import { workflowExecutions } from "./workflow-executions" @@ -33,6 +34,7 @@ export const client = { tags: tags, users: users, regions: regions, + taxes: taxes, invites: invites, products: products, productTypes: productTypes, diff --git a/packages/admin-next/dashboard/src/lib/client/taxes.ts b/packages/admin-next/dashboard/src/lib/client/taxes.ts new file mode 100644 index 0000000000..4edb7f0aac --- /dev/null +++ b/packages/admin-next/dashboard/src/lib/client/taxes.ts @@ -0,0 +1,18 @@ +import { + AdminTaxRegionListResponse, + AdminTaxRegionResponse, +} from "@medusajs/types" +import { getRequest } from "./common" + +async function retrieveTaxRegion(id: string, query?: Record) { + return getRequest(`/admin/tax-regions/${id}`, query) +} + +async function listTaxRegions(query?: Record) { + return getRequest(`/admin/tax-regions`, query) +} + +export const taxes = { + retrieveTaxRegion, + listTaxRegions, +} diff --git a/packages/admin-next/dashboard/src/providers/router-provider/v1.tsx b/packages/admin-next/dashboard/src/providers/router-provider/v1.tsx index ea6206e898..2d3106d977 100644 --- a/packages/admin-next/dashboard/src/providers/router-provider/v1.tsx +++ b/packages/admin-next/dashboard/src/providers/router-provider/v1.tsx @@ -5,9 +5,6 @@ import type { AdminDraftOrdersRes, AdminGiftCardsRes, AdminOrdersRes, - AdminRegionsRes, - AdminSalesChannelsRes, - AdminUserRes, } from "@medusajs/medusa" import { Outlet, RouteObject } from "react-router-dom" 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 e0f23a4007..dc7eb48771 100644 --- a/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx +++ b/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx @@ -512,6 +512,20 @@ export const v2Routes: RouteObject[] = [ }, ], }, + { + path: "taxes", + element: , + handle: { + crumb: () => "Taxes", + }, + children: [ + { + path: "", + lazy: () => import("../../v2-routes/taxes/tax-region-list"), + children: [], + }, + ], + }, ], }, ], diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/components/override-chip/index.ts b/packages/admin-next/dashboard/src/routes/taxes/common/components/override-chip/index.ts deleted file mode 100644 index 1e406647de..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/components/override-chip/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./override-chip" diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/components/override-chip/override-chip.tsx b/packages/admin-next/dashboard/src/routes/taxes/common/components/override-chip/override-chip.tsx deleted file mode 100644 index 3cd46dd22b..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/components/override-chip/override-chip.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { XMarkMini } from "@medusajs/icons" -import { OverrideOption } from "../../types" - -type OverrideChipProps = { - override: OverrideOption - onRemove: (value: string) => void -} - -export const OverrideChip = ({ override, onRemove }: OverrideChipProps) => { - return ( -
-
- {override.label} -
- -
- ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/components/override-grid/index.ts b/packages/admin-next/dashboard/src/routes/taxes/common/components/override-grid/index.ts deleted file mode 100644 index cbe1f25826..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/components/override-grid/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./override-grid" diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/components/override-grid/override-grid.tsx b/packages/admin-next/dashboard/src/routes/taxes/common/components/override-grid/override-grid.tsx deleted file mode 100644 index c1fc79a9ea..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/components/override-grid/override-grid.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { Button } from "@medusajs/ui" -import { useTranslation } from "react-i18next" -import { OverrideOption } from "../../types" -import { OverrideChip } from "../override-chip" - -type OverrideGridProps = { - overrides: OverrideOption[] - onRemove: (value: string) => void - onClear: () => void -} - -export const OverrideGrid = ({ - overrides, - onRemove, - onClear, -}: OverrideGridProps) => { - const { t } = useTranslation() - - if (!overrides.length) { - return null - } - - return ( -
- {overrides.map((override) => ( - - ))} - -
- ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/components/overrides-drawer/index.ts b/packages/admin-next/dashboard/src/routes/taxes/common/components/overrides-drawer/index.ts deleted file mode 100644 index d245a68c1e..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/components/overrides-drawer/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./overrides-drawer" diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/components/overrides-drawer/overrides-drawer.tsx b/packages/admin-next/dashboard/src/routes/taxes/common/components/overrides-drawer/overrides-drawer.tsx deleted file mode 100644 index 271c20bd79..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/components/overrides-drawer/overrides-drawer.tsx +++ /dev/null @@ -1,394 +0,0 @@ -import { Product } from "@medusajs/medusa" -import { PricedShippingOption } from "@medusajs/medusa/dist/types/pricing" -import { Button } from "@medusajs/ui" -import { OnChangeFn, RowSelectionState } from "@tanstack/react-table" -import { - useAdminProductTypes, - useAdminProducts, - useAdminShippingOptions, -} from "medusa-react" -import { useState } from "react" -import { useTranslation } from "react-i18next" - -import { SplitView } from "../../../../../components/layout/split-view" -import { DataTable } from "../../../../../components/table/data-table" -import { useProductTableFilters } from "../../../../../hooks/table/filters/use-product-table-filters" -import { useShippingOptionTableFilters } from "../../../../../hooks/table/filters/use-shipping-option-table-filters" -import { useProductTableQuery } from "../../../../../hooks/table/query/use-product-table-query" -import { useShippingOptionTableQuery } from "../../../../../hooks/table/query/use-shipping-option-table-query" -import { useDataTable } from "../../../../../hooks/use-data-table" -import { Override } from "../../constants" -import { useProductOverrideTableColumns } from "../../hooks/columns/use-product-override-table-columns" -import { useProductTypeOverrideTableColumns } from "../../hooks/columns/use-product-type-override-table-columns" -import { useShippingOptionOverrideTableColumns } from "../../hooks/columns/use-shipping-option-override-table-columns" -import { useProductTypeOverrideTableFilters } from "../../hooks/filters/use-product-type-override-table-filters" -import { useProductTypeOverrideTableQuery } from "../../hooks/query/use-product-type-override-table-query" -import { OverrideOption } from "../../types" - -const PAGE_SIZE = 50 - -const PRODUCT_PREFIX = "product" -const PRODUCT_TYPE_PREFIX = "product_type" -const SHIPPING_OPTION_PREFIX = "shipping_option" - -type OverrideProps = { - selected: OverrideOption[] - onSave: (options: OverrideOption[]) => void -} - -const initRowState = (selected: OverrideOption[] = []): RowSelectionState => { - return selected.reduce((acc, { value }) => { - acc[value] = true - return acc - }, {} as RowSelectionState) -} - -const OverrideFooter = ({ onSave }: { onSave: () => void }) => { - const { t } = useTranslation() - - return ( -
- - - - -
- ) -} - -const ProductOverrideTable = ({ selected = [], onSave }: OverrideProps) => { - const [rowSelection, setRowSelection] = useState( - initRowState(selected) - ) - const [intermediate, setIntermediate] = useState(selected) - - const { searchParams, raw } = useProductTableQuery({ - pageSize: PAGE_SIZE, - prefix: PRODUCT_PREFIX, - }) - const { products, count, isLoading, isError, error } = useAdminProducts( - { - ...searchParams, - }, - { - keepPreviousData: true, - } - ) - - const updater: OnChangeFn = (fn) => { - const newState: RowSelectionState = - typeof fn === "function" ? fn(rowSelection) : fn - - const diff = Object.keys(newState).filter( - (k) => newState[k] !== rowSelection[k] - ) - - if (diff.length === 0) { - return - } - - const addedProducts = (products?.filter((p) => diff.includes(p.id!)) ?? - []) as Product[] - - if (addedProducts.length > 0) { - const newOverrides = addedProducts.map((p) => ({ - label: p.title, - value: p.id!, - })) - - setIntermediate((prev) => { - const filteredPrev = prev.filter((p) => - Object.keys(newState).includes(p.value) - ) - const update = Array.from(new Set([...filteredPrev, ...newOverrides])) - return update - }) - } - - setRowSelection(newState) - } - - const handleSave = () => { - onSave(intermediate) - } - - const columns = useProductOverrideTableColumns() - const filters = useProductTableFilters() - - const { table } = useDataTable({ - data: (products ?? []) as Product[], - columns: columns, - count, - enablePagination: true, - getRowId: (row) => row.id, - pageSize: PAGE_SIZE, - enableRowSelection: true, - rowSelection: { - state: rowSelection, - updater, - }, - prefix: PRODUCT_PREFIX, - }) - - if (isError) { - throw error - } - - return ( -
- - -
- ) -} - -const ProductTypeOverrideTable = ({ onSave, selected = [] }: OverrideProps) => { - const [rowSelection, setRowSelection] = useState( - initRowState(selected) - ) - const [intermediate, setIntermediate] = useState(selected) - - const { searchParams, raw } = useProductTypeOverrideTableQuery({ - pageSize: PAGE_SIZE, - prefix: PRODUCT_TYPE_PREFIX, - }) - const { product_types, count, isLoading, isError, error } = - useAdminProductTypes( - { - ...searchParams, - }, - { - keepPreviousData: true, - } - ) - - const updater: OnChangeFn = (fn) => { - const newState: RowSelectionState = - typeof fn === "function" ? fn(rowSelection) : fn - - const diff = Object.keys(newState).filter( - (k) => newState[k] !== rowSelection[k] - ) - - if (diff.length === 0) { - return - } - - const addedProductTypes = - product_types?.filter((p) => diff.includes(p.id!)) ?? [] - - if (addedProductTypes.length > 0) { - const newOverrides = addedProductTypes.map((p) => ({ - label: p.value, - value: p.id!, - })) - - setIntermediate((prev) => { - const filteredPrev = prev.filter((p) => - Object.keys(newState).includes(p.value) - ) - const update = Array.from(new Set([...filteredPrev, ...newOverrides])) - return update - }) - } - - setRowSelection(newState) - } - - const handleSave = () => { - onSave(intermediate) - } - - const columns = useProductTypeOverrideTableColumns() - const filters = useProductTypeOverrideTableFilters() - - const { table } = useDataTable({ - data: product_types ?? [], - columns: columns, - count, - enablePagination: true, - getRowId: (row) => row.id, - pageSize: PAGE_SIZE, - enableRowSelection: true, - rowSelection: { - state: rowSelection, - updater, - }, - prefix: PRODUCT_TYPE_PREFIX, - }) - - if (isError) { - throw error - } - - return ( -
- - -
- ) -} - -const ShippingOptionOverrideTable = ({ - onSave, - selected = [], - regionId, -}: OverrideProps & { regionId: string }) => { - const [rowSelection, setRowSelection] = useState( - initRowState(selected) - ) - const [intermediate, setIntermediate] = useState(selected) - - const { searchParams, raw } = useShippingOptionTableQuery({ - regionId, - pageSize: PAGE_SIZE, - prefix: SHIPPING_OPTION_PREFIX, - }) - const { shipping_options, count, isLoading, isError, error } = - useAdminShippingOptions( - { - ...searchParams, - }, - { - keepPreviousData: true, - } - ) - - const updater: OnChangeFn = (fn) => { - const newState: RowSelectionState = - typeof fn === "function" ? fn(rowSelection) : fn - - const diff = Object.keys(newState).filter( - (k) => newState[k] !== rowSelection[k] - ) - - if (diff.length === 0) { - return - } - - const addedShippingOptions = - shipping_options?.filter((p) => diff.includes(p.id!)) ?? [] - - if (addedShippingOptions.length > 0) { - const newOverrides = addedShippingOptions.map((p) => ({ - label: p.name, - value: p.id!, - })) - - setIntermediate((prev) => { - const filteredPrev = prev.filter((p) => - Object.keys(newState).includes(p.value) - ) - const update = Array.from(new Set([...filteredPrev, ...newOverrides])) - return update - }) - } - - setRowSelection(newState) - } - - const handleSave = () => { - onSave(intermediate) - } - - const columns = useShippingOptionOverrideTableColumns() - const filters = useShippingOptionTableFilters() - - const { table } = useDataTable({ - data: (shipping_options ?? []) as unknown as PricedShippingOption[], - columns: columns, - count, - enablePagination: true, - getRowId: (row) => row.id!, - pageSize: PAGE_SIZE, - enableRowSelection: true, - rowSelection: { - state: rowSelection, - updater, - }, - prefix: SHIPPING_OPTION_PREFIX, - }) - - if (isError) { - throw error - } - - return ( -
- - -
- ) -} - -type OverrideTableProps = { - product: OverrideProps - productType: OverrideProps - shippingOption: OverrideProps - regionId: string - selected: Override | null -} - -export const OverrideTable = ({ - product, - productType, - shippingOption, - regionId, - selected, -}: OverrideTableProps) => { - switch (selected) { - case Override.PRODUCT: - return - case Override.PRODUCT_TYPE: - return - case Override.SHIPPING_OPTION: - return ( - - ) - default: - return null - } -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/constants.ts b/packages/admin-next/dashboard/src/routes/taxes/common/constants.ts deleted file mode 100644 index a3b64e64ea..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/constants.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum Override { - PRODUCT = "product", - PRODUCT_TYPE = "product_type", - SHIPPING_OPTION = "shipping_option", -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/hooks/columns/use-product-override-table-columns.tsx b/packages/admin-next/dashboard/src/routes/taxes/common/hooks/columns/use-product-override-table-columns.tsx deleted file mode 100644 index 83c74c5139..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/hooks/columns/use-product-override-table-columns.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Product } from "@medusajs/medusa" -import { Checkbox } from "@medusajs/ui" -import { createColumnHelper } from "@tanstack/react-table" -import { useMemo } from "react" -import { useProductTableColumns } from "../../../../../hooks/table/columns/use-product-table-columns" - -const columnHelper = createColumnHelper() - -export const useProductOverrideTableColumns = () => { - const base = useProductTableColumns() - - return useMemo( - () => [ - columnHelper.display({ - id: "select", - header: ({ table }) => { - return ( - - table.toggleAllPageRowsSelected(!!value) - } - /> - ) - }, - cell: ({ row }) => { - return ( - row.toggleSelected(!!value)} - onClick={(e) => { - e.stopPropagation() - }} - /> - ) - }, - }), - ...base, - ], - [base] - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/hooks/columns/use-product-type-override-table-columns.tsx b/packages/admin-next/dashboard/src/routes/taxes/common/hooks/columns/use-product-type-override-table-columns.tsx deleted file mode 100644 index 3c653659c7..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/hooks/columns/use-product-type-override-table-columns.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { ProductType } from "@medusajs/medusa" -import { Checkbox } from "@medusajs/ui" -import { createColumnHelper } from "@tanstack/react-table" -import { useMemo } from "react" -import { useTranslation } from "react-i18next" - -const columnHelper = createColumnHelper() - -export const useProductTypeOverrideTableColumns = () => { - const { t } = useTranslation() - - return useMemo( - () => [ - columnHelper.display({ - id: "select", - header: ({ table }) => { - return ( - - table.toggleAllPageRowsSelected(!!value) - } - /> - ) - }, - cell: ({ row }) => { - return ( - row.toggleSelected(!!value)} - onClick={(e) => { - e.stopPropagation() - }} - /> - ) - }, - }), - columnHelper.accessor("value", { - header: t("fields.value"), - cell: ({ getValue }) => getValue(), - }), - ], - [t] - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/hooks/columns/use-shipping-option-override-table-columns.tsx b/packages/admin-next/dashboard/src/routes/taxes/common/hooks/columns/use-shipping-option-override-table-columns.tsx deleted file mode 100644 index 541c024060..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/hooks/columns/use-shipping-option-override-table-columns.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { PricedShippingOption } from "@medusajs/medusa/dist/types/pricing" -import { Checkbox } from "@medusajs/ui" -import { createColumnHelper } from "@tanstack/react-table" -import { useMemo } from "react" -import { useShippingOptionTableColumns } from "../../../../../hooks/table/columns/use-shipping-option-table-columns" - -const columnHelper = createColumnHelper() - -export const useShippingOptionOverrideTableColumns = () => { - const base = useShippingOptionTableColumns() - - return useMemo( - () => [ - columnHelper.display({ - id: "select", - header: ({ table }) => { - return ( - - table.toggleAllPageRowsSelected(!!value) - } - /> - ) - }, - cell: ({ row }) => { - return ( - row.toggleSelected(!!value)} - onClick={(e) => { - e.stopPropagation() - }} - /> - ) - }, - }), - ...base, - ], - [base] - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/hooks/filters/use-product-type-override-table-filters.tsx b/packages/admin-next/dashboard/src/routes/taxes/common/hooks/filters/use-product-type-override-table-filters.tsx deleted file mode 100644 index 3acaf64870..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/hooks/filters/use-product-type-override-table-filters.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { useTranslation } from "react-i18next" -import { Filter } from "../../../../../components/table/data-table" - -export const useProductTypeOverrideTableFilters = () => { - const { t } = useTranslation() - - const filters: Filter[] = [ - { label: t("fields.createdAt"), key: "created_at" }, - { label: t("fields.updatedAt"), key: "updated_at" }, - ].map((f) => ({ - key: f.key, - label: f.label, - type: "date", - })) - - return filters -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/hooks/query/use-product-type-override-table-query.tsx b/packages/admin-next/dashboard/src/routes/taxes/common/hooks/query/use-product-type-override-table-query.tsx deleted file mode 100644 index 163f069d56..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/hooks/query/use-product-type-override-table-query.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { AdminGetProductTypesParams } from "@medusajs/medusa" -import { useQueryParams } from "../../../../../hooks/use-query-params" - -export const useProductTypeOverrideTableQuery = ({ - pageSize = 50, - prefix, -}: { - pageSize?: number - prefix: string -}) => { - const raw = useQueryParams( - ["offset", "q", "order", "created_at", "updated_at"], - prefix - ) - - const searchParams: AdminGetProductTypesParams = { - limit: pageSize, - offset: raw.offset ? Number(raw.offset) : 0, - q: raw.q, - created_at: raw.created_at ? JSON.parse(raw.created_at) : undefined, - updated_at: raw.updated_at ? JSON.parse(raw.updated_at) : undefined, - order: raw.order, - } - - return { - searchParams, - raw, - } -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/common/types.ts b/packages/admin-next/dashboard/src/routes/taxes/common/types.ts deleted file mode 100644 index 814de0e349..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/common/types.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Override } from "./constants" - -export type OverrideOption = { - value: string - label: string -} - -export type OverrideState = { - [K in Override]: boolean -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-countries-section/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-countries-section/index.ts deleted file mode 100644 index 5455db9edf..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-countries-section/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./tax-countries-section" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-countries-section/tax-countries-section.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-countries-section/tax-countries-section.tsx deleted file mode 100644 index 61966e38c9..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-countries-section/tax-countries-section.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { GlobeEurope } from "@medusajs/icons" -import { Region } from "@medusajs/medusa" -import { Container, Heading, Text, Tooltip } from "@medusajs/ui" -import { useTranslation } from "react-i18next" - -type TaxCountriesSectionProps = { - region: Region -} - -export const TaxCountriesSection = ({ region }: TaxCountriesSectionProps) => { - const { t } = useTranslation() - - const countries = region.countries ?? [] - - const firstCountries = countries.slice(0, 3) - const restCountries = countries.slice(3) - - return ( - -
- {t("fields.countries")} -
-
-
-
- -
-
- {countries.length > 0 ? ( -
- - {firstCountries.map((sc) => sc.display_name).join(", ")} - - {restCountries.length > 0 && ( - - {restCountries.map((sc) => ( -
  • {sc.display_name}
  • - ))} - - } - > - - {t("general.plusCountMore", { - count: restCountries.length, - })} - -
    - )} -
    - ) : ( - - {t("products.noSalesChannels")} - - )} -
    -
    - - {t("taxes.countries.taxCountriesHint")} - -
    -
    - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-default-tax-rate-section/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-default-tax-rate-section/index.ts deleted file mode 100644 index d578a89519..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-default-tax-rate-section/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./tax-default-tax-rate-section" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-default-tax-rate-section/tax-default-tax-rate-section.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-default-tax-rate-section/tax-default-tax-rate-section.tsx deleted file mode 100644 index 9ac611b00d..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-default-tax-rate-section/tax-default-tax-rate-section.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { PencilSquare } from "@medusajs/icons" -import { Region } from "@medusajs/medusa" -import { Container, Heading, Text } from "@medusajs/ui" -import { useTranslation } from "react-i18next" -import { ActionMenu } from "../../../../../components/common/action-menu" -import { formatPercentage } from "../../../../../lib/percentage-helpers" - -type TaxDefaultRateSectionProps = { - region: Region -} - -export const TaxDefaultTaxRateSection = ({ - region, -}: TaxDefaultRateSectionProps) => { - const { t } = useTranslation() - - const defaultTaxCode = region.tax_code - const defaultTaxRate = region.tax_rate - - return ( - -
    - {t("taxes.defaultRate.sectionTitle")} - , - }, - ], - }, - ]} - /> -
    -
    - - {t("fields.rate")} - - - {formatPercentage(defaultTaxRate)} - -
    -
    - - {t("fields.code")} - - - {defaultTaxCode || "-"} - -
    -
    - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-general-section/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-general-section/index.ts deleted file mode 100644 index 01d3c1d183..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-general-section/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./tax-general-section" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-general-section/tax-general-section.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-general-section/tax-general-section.tsx deleted file mode 100644 index fe54cf11c1..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-general-section/tax-general-section.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { PencilSquare } from "@medusajs/icons" -import { Region } from "@medusajs/medusa" -import { Badge, Container, Heading, StatusBadge, Text } from "@medusajs/ui" -import { useTranslation } from "react-i18next" -import { ActionMenu } from "../../../../../components/common/action-menu" -import { formatPercentage } from "../../../../../lib/percentage-helpers" - -type Props = { - region: Region -} - -export const TaxDetailsSection = ({ region }: Props) => { - const { t } = useTranslation() - - return ( - -
    - {region.name} - , - to: "edit", - }, - ], - }, - ]} - /> -
    -
    - - {t("taxes.settings.taxProviderLabel")} - - - {region.tax_provider_id - ? region.tax_provider_id - : t("taxes.settings.systemTaxProviderLabel")} - -
    -
    - - {t("taxes.settings.calculateTaxesAutomaticallyLabel")} - - - {region.automatic_taxes - ? t("general.enabled") - : t("general.disabled")} - -
    -
    - - {t("taxes.settings.applyTaxesOnGiftCardsLabel")} - - - {region.gift_cards_taxable - ? t("general.enabled") - : t("general.disabled")} - -
    -
    - - {t("fields.taxInclusivePricing")} - - - {region.includes_tax ? t("general.enabled") : t("general.disabled")} - -
    -
    - - {t("taxes.settings.defaultTaxRateLabel")} - -
    - - {formatPercentage(region.tax_rate)} - - {region.tax_code && {region.tax_code}} -
    -
    -
    - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/index.ts deleted file mode 100644 index e6d46bf5fe..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./tax-rates-section" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/tax-rate-actions.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/tax-rate-actions.tsx deleted file mode 100644 index 3029700aeb..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/tax-rate-actions.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import type { TaxRate } from "@medusajs/medusa" -import { useTranslation } from "react-i18next" - -import { ExclamationCircle, PencilSquare, Trash } from "@medusajs/icons" -import { usePrompt } from "@medusajs/ui" -import { useAdminDeleteTaxRate } from "medusa-react" -import { ActionMenu } from "../../../../../components/common/action-menu" - -export const TaxRateActions = ({ taxRate }: { taxRate: TaxRate }) => { - const { t } = useTranslation() - const prompt = usePrompt() - - const { mutateAsync } = useAdminDeleteTaxRate(taxRate.id) - - const handleDelete = async () => { - const res = await prompt({ - title: t("general.areYouSure"), - description: t("taxes.taxRate.deleteRateDescription", { - name: taxRate.name, - }), - confirmText: t("actions.delete"), - cancelText: t("actions.cancel"), - }) - - if (!res) { - return - } - - await mutateAsync() - } - - return ( - , - }, - { - label: t("taxes.taxRate.editOverridesAction"), - to: `tax-rates/${taxRate.id}/edit-overrides`, - icon: , - }, - ], - }, - { - actions: [ - { - label: t("actions.delete"), - icon: , - onClick: handleDelete, - }, - ], - }, - ]} - /> - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/tax-rates-section.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/tax-rates-section.tsx deleted file mode 100644 index a5e242b677..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/tax-rates-section.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Plus } from "@medusajs/icons" -import { Region } from "@medusajs/medusa" -import { Container, Heading } from "@medusajs/ui" -import { useAdminTaxRates } from "medusa-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 { useTaxRateTableColumns } from "./use-tax-rate-table-columns" -import { useTaxRateTableFilters } from "./use-tax-rate-table-filters" -import { useTaxRateTableQuery } from "./use-tax-rate-table-query" - -type TaxRatesSectionProps = { - region: Region -} - -const PAGE_SIZE = 10 - -export const TaxRatesSection = ({ region }: TaxRatesSectionProps) => { - const { t } = useTranslation() - - const { searchParams, raw } = useTaxRateTableQuery({ pageSize: PAGE_SIZE }) - const { tax_rates, count, isLoading, isError, error } = useAdminTaxRates( - { - region_id: region.id, - expand: ["products", "product_types", "shipping_options"], - fields: [ - "id", - "name", - "code", - "rate", - "created_at", - "updated_at", - "products.id", - "product_types.id", - "shipping_options.id", - ], - ...searchParams, - }, - { - keepPreviousData: true, - } - ) - - const filters = useTaxRateTableFilters() - const columns = useTaxRateTableColumns() - - const { table } = useDataTable({ - data: tax_rates ?? [], - columns, - count, - enablePagination: true, - getRowId: (row) => row.id, - pageSize: PAGE_SIZE, - }) - - if (isError) { - throw error - } - - return ( - -
    - {t("taxes.taxRate.sectionTitle")} - , - }, - ], - }, - ]} - /> -
    - -
    - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/use-tax-rate-table-columns.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/use-tax-rate-table-columns.tsx deleted file mode 100644 index 60a794dbc1..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/use-tax-rate-table-columns.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import type { TaxRate } from "@medusajs/medusa" -import { createColumnHelper } from "@tanstack/react-table" -import { useMemo } from "react" -import { useTranslation } from "react-i18next" -import { PlaceholderCell } from "../../../../../components/table/table-cells/common/placeholder-cell" -import { formatPercentage } from "../../../../../lib/percentage-helpers" -import { TaxRateActions } from "./tax-rate-actions" - -const columnHelper = createColumnHelper() - -export const useTaxRateTableColumns = () => { - const { t } = useTranslation() - - return useMemo( - () => [ - columnHelper.accessor("name", { - header: t("fields.name"), - cell: ({ getValue }) => { - return ( -
    - {getValue()} -
    - ) - }, - }), - columnHelper.accessor("code", { - header: t("fields.code"), - cell: ({ getValue }) => { - return ( -
    - {getValue()} -
    - ) - }, - }), - columnHelper.accessor("rate", { - header: t("fields.rate"), - cell: ({ getValue }) => { - const rate = getValue() - - return ( -
    - {formatPercentage(rate)} -
    - ) - }, - }), - columnHelper.accessor("products", { - header: () => { - return ( -
    - - {t("taxes.taxRate.productOverridesHeader")} - -
    - ) - }, - cell: ({ getValue }) => { - const count = getValue()?.length - - if (!count) { - return - } - - return ( -
    - {count} -
    - ) - }, - }), - columnHelper.accessor("product_types", { - header: () => { - return ( -
    - - {t("taxes.taxRate.productTypeOverridesHeader")} - -
    - ) - }, - cell: ({ getValue }) => { - const count = getValue()?.length - - if (!count) { - return - } - - return ( -
    - {count} -
    - ) - }, - }), - columnHelper.accessor("shipping_options", { - header: () => { - return ( -
    - - {t("taxes.taxRate.shippingOptionOverridesHeader")} - -
    - ) - }, - cell: ({ getValue }) => { - const count = getValue()?.length - - if (!count) { - return - } - - return ( -
    - {count} -
    - ) - }, - }), - columnHelper.display({ - id: "actions", - cell: ({ row }) => , - }), - ], - [t] - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/use-tax-rate-table-filters.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/use-tax-rate-table-filters.tsx deleted file mode 100644 index 415d2b0b52..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/use-tax-rate-table-filters.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { useTranslation } from "react-i18next" -import type { Filter } from "../../../../../components/table/data-table" - -export const useTaxRateTableFilters = () => { - const { t } = useTranslation() - - const dateFilters: Filter[] = [ - { label: t("fields.createdAt"), key: "created_at" }, - { label: t("fields.updatedAt"), key: "updated_at" }, - ].map((f) => ({ - key: f.key, - label: f.label, - type: "date", - })) - - const filters = [...dateFilters] - - return filters -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/use-tax-rate-table-query.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/use-tax-rate-table-query.tsx deleted file mode 100644 index 7745062340..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/components/tax-rates-section/use-tax-rate-table-query.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { AdminGetTaxRatesParams } from "@medusajs/medusa" -import { useQueryParams } from "../../../../../hooks/use-query-params" - -export const useTaxRateTableQuery = ({ - pageSize = 10, - prefix, -}: { - pageSize?: number - prefix?: string -}) => { - const raw = useQueryParams( - ["offset", "q", "order", "created_at", "updated_at"], - prefix - ) - - const searchParams: AdminGetTaxRatesParams = { - limit: pageSize, - offset: raw.offset ? parseInt(raw.offset) : 0, - q: raw.q, - order: raw.order, - created_at: raw.created_at ? JSON.parse(raw.created_at) : undefined, - updated_at: raw.updated_at ? JSON.parse(raw.updated_at) : undefined, - } - - return { - searchParams, - raw, - } -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/index.ts deleted file mode 100644 index 6d75308596..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { taxRegionLoader as loader } from "./loader" -export { TaxDetail as Component } from "./tax-detail" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/loader.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/loader.ts deleted file mode 100644 index 1c455cbbd1..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/loader.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AdminRegionsRes } from "@medusajs/medusa" -import { Response } from "@medusajs/medusa-js" -import { adminRegionKeys } from "medusa-react" -import { LoaderFunctionArgs } from "react-router-dom" - -import { medusa, queryClient } from "../../../lib/medusa" - -const regionQuery = (id: string) => ({ - queryKey: adminRegionKeys.detail(id), - queryFn: async () => medusa.admin.regions.retrieve(id), -}) - -export const taxRegionLoader = async ({ params }: LoaderFunctionArgs) => { - const id = params.id - const query = regionQuery(id!) - - return ( - queryClient.getQueryData>(query.queryKey) ?? - (await queryClient.fetchQuery(query)) - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/tax-detail.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-detail/tax-detail.tsx deleted file mode 100644 index caf757a27d..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-detail/tax-detail.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { useAdminRegion } from "medusa-react" -import { Outlet, useLoaderData, useParams } from "react-router-dom" -import { JsonViewSection } from "../../../components/common/json-view-section" -import { TaxCountriesSection } from "./components/tax-countries-section" -import { TaxDetailsSection } from "./components/tax-general-section" -import { TaxRatesSection } from "./components/tax-rates-section" -import { taxRegionLoader } from "./loader" - -export const TaxDetail = () => { - const { id } = useParams() - const initialData = useLoaderData() as Awaited< - ReturnType - > - - const { region, isLoading, isError, error } = useAdminRegion(id!, { - initialData, - }) - - if (isLoading || !region) { - return
    Loading...
    - } - - if (isError) { - throw error - } - - return ( -
    -
    -
    - - -
    - -
    - -
    -
    - -
    -
    - -
    - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-edit/components/edit-tax-form/edit-tax-form.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-edit/components/edit-tax-form/edit-tax-form.tsx deleted file mode 100644 index 57012bf82e..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-edit/components/edit-tax-form/edit-tax-form.tsx +++ /dev/null @@ -1,257 +0,0 @@ -import { useForm } from "react-hook-form" -import { z } from "zod" - -import { zodResolver } from "@hookform/resolvers/zod" -import { Region, TaxProvider } from "@medusajs/medusa" -import { Button, Input, Select, Switch } from "@medusajs/ui" -import { useAdminUpdateRegion } from "medusa-react" -import { useTranslation } from "react-i18next" -import { Form } from "../../../../../components/common/form" -import { PercentageInput } from "../../../../../components/common/percentage-input" -import { - RouteDrawer, - useRouteModal, -} from "../../../../../components/route-modal" -import { formatProvider } from "../../../../../lib/format-provider" - -type EditTaxRateFormProps = { - region: Region - taxProviders: TaxProvider[] -} - -const EditTaxSettingsSchema = z.object({ - tax_code: z.string().optional(), - tax_rate: z.union([z.string(), z.number()]).refine((value) => { - if (value === "") { - return false - } - - const num = Number(value) - - if (num >= 0 && num <= 100) { - return true - } - - return false - }, "Default tax rate must be a number between 0 and 100"), - includes_tax: z.boolean(), - automatic_taxes: z.boolean(), - gift_cards_taxable: z.boolean(), - tax_provider_id: z.string(), -}) - -const SYSTEM_PROVIDER_ID = "system" - -export const EditTaxSettingsForm = ({ - region, - taxProviders, -}: EditTaxRateFormProps) => { - const { t } = useTranslation() - const { handleSuccess } = useRouteModal() - - const form = useForm>({ - defaultValues: { - tax_code: region.tax_code || "", - tax_rate: region.tax_rate, - includes_tax: region.includes_tax, - automatic_taxes: region.automatic_taxes, - gift_cards_taxable: region.gift_cards_taxable, - tax_provider_id: region.tax_provider_id || SYSTEM_PROVIDER_ID, - }, - resolver: zodResolver(EditTaxSettingsSchema), - }) - - const { mutateAsync, isLoading } = useAdminUpdateRegion(region.id) - - const handleSubmit = form.handleSubmit(async (data) => { - const { tax_provider_id, tax_rate, ...rest } = data - - await mutateAsync( - { - tax_provider_id: - tax_provider_id === SYSTEM_PROVIDER_ID ? null : tax_provider_id, - tax_rate: Number(tax_rate), - ...rest, - }, - { - onSuccess: () => { - handleSuccess() - }, - } - ) - }) - - return ( - -
    - -
    -
    - { - return ( - - - {t("taxes.settings.taxProviderLabel")} - - - - - - - ) - }} - /> - { - return ( - - - {t("taxes.settings.defaultTaxRateLabel")} - - - - - - - ) - }} - /> - { - return ( - - - {t("taxes.settings.defaultTaxCodeLabel")} - - - - - - - ) - }} - /> -
    - { - return ( - -
    -
    - - {t("taxes.settings.calculateTaxesAutomaticallyLabel")} - - - {t("taxes.settings.calculateTaxesAutomaticallyHint")} - -
    - - - -
    - -
    - ) - }} - /> - { - return ( - -
    -
    - - {t("taxes.settings.applyTaxesOnGiftCardsLabel")} - - - {t("taxes.settings.applyTaxesOnGiftCardsHint")} - -
    - - - -
    - -
    - ) - }} - /> - { - return ( - -
    -
    - - {t("fields.taxInclusivePricing")} - - - {t("regions.taxInclusiveHint")} - -
    - - - -
    - -
    - ) - }} - /> -
    -
    - -
    - - - - -
    -
    -
    -
    - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-edit/components/edit-tax-form/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-edit/components/edit-tax-form/index.ts deleted file mode 100644 index 56956a34fa..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-edit/components/edit-tax-form/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./edit-tax-form" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-edit/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-edit/index.ts deleted file mode 100644 index 614c5e55d8..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-edit/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { TaxEdit as Component } from "./tax-edit" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-edit/tax-edit.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-edit/tax-edit.tsx deleted file mode 100644 index 7e77eefc11..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-edit/tax-edit.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Heading } from "@medusajs/ui" -import { useAdminRegion, useAdminStoreTaxProviders } from "medusa-react" -import { useTranslation } from "react-i18next" -import { useParams } from "react-router-dom" -import { RouteDrawer } from "../../../components/route-modal" -import { EditTaxSettingsForm } from "./components/edit-tax-form" - -export const TaxEdit = () => { - const { id } = useParams() - const { t } = useTranslation() - - const { region, isLoading, isError, error } = useAdminRegion(id!) - const { - tax_providers, - isLoading: isLoadingTaxProvider, - isError: isTaxProviderError, - error: taxProviderError, - } = useAdminStoreTaxProviders() - - const ready = !isLoading && region && !isLoadingTaxProvider && tax_providers - - if (isError) { - throw error - } - - if (isTaxProviderError) { - throw taxProviderError - } - - return ( - - - {t("taxes.settings.editTaxSettings")} - - {ready && ( - - )} - - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-callout/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-callout/index.ts deleted file mode 100644 index b5c05581cd..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-callout/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./tax-list-callout" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-callout/tax-list-callout.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-callout/tax-list-callout.tsx deleted file mode 100644 index bfa15baf49..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-callout/tax-list-callout.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Button, Container, Heading, Text } from "@medusajs/ui" -import { Link } from "react-router-dom" - -export const TaxListCallout = () => { - return ( - -
    - Taxes - - Tax settings are specific to each region. To modify tax settings, - please select a region from the list. - -
    - -
    - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-table/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-table/index.ts deleted file mode 100644 index 1f23c91012..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-table/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "../tax-list-table/tax-list-table" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-table/tax-list-table.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-table/tax-list-table.tsx deleted file mode 100644 index b321fc56f7..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-list/components/tax-list-table/tax-list-table.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { Container, Heading } from "@medusajs/ui" -import { useAdminRegions } from "medusa-react" -import { useMemo } from "react" -import { useTranslation } from "react-i18next" -import { DataTable } from "../../../../../components/table/data-table" -import { useRegionTableColumns } from "../../../../../hooks/table/columns/use-region-table-columns" -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" - -const PAGE_SIZE = 20 - -export const TaxListTable = () => { - const { t } = useTranslation() - - const { searchParams, raw } = useRegionTableQuery({ - pageSize: PAGE_SIZE, - }) - const { regions, count, isLoading, isError, error } = useAdminRegions( - { - ...searchParams, - }, - { - keepPreviousData: true, - } - ) - - const columns = useColumns() - const filters = useRegionTableFilters() - - const { table } = useDataTable({ - data: regions || [], - columns, - count, - enablePagination: true, - getRowId: (row) => row.id, - pageSize: PAGE_SIZE, - }) - - if (isError) { - throw error - } - - return ( - -
    - {t("regions.domain")} -
    - `${row.original.id}`} - orderBy={["name", "created_at", "updated_at"]} - /> -
    - ) -} - -const useColumns = () => { - const base = useRegionTableColumns() - - return useMemo(() => [...base], [base]) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-list/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-list/index.ts deleted file mode 100644 index dada0aa95c..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-list/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { TaxList as Component } from "./tax-list" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-list/tax-list.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-list/tax-list.tsx deleted file mode 100644 index 80c5b79522..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-list/tax-list.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { TaxListCallout } from "./components/tax-list-callout" -import { TaxListTable } from "./components/tax-list-table" - -export const TaxList = () => { - return ( -
    - - -
    - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/components/create-tax-rate-form/create-tax-rate-form.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/components/create-tax-rate-form/create-tax-rate-form.tsx deleted file mode 100644 index 3c744aa678..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/components/create-tax-rate-form/create-tax-rate-form.tsx +++ /dev/null @@ -1,474 +0,0 @@ -import { zodResolver } from "@hookform/resolvers/zod" -import { Button, Heading, Input, Switch, Text, clx } from "@medusajs/ui" -import * as Collapsible from "@radix-ui/react-collapsible" -import { useAdminCreateTaxRate } from "medusa-react" -import { useState } from "react" -import { useForm, useWatch } from "react-hook-form" -import { useTranslation } from "react-i18next" -import { useParams, useSearchParams } from "react-router-dom" -import { z } from "zod" - -import { Form } from "../../../../../components/common/form" -import { PercentageInput } from "../../../../../components/common/percentage-input" -import { SplitView } from "../../../../../components/layout/split-view" -import { - RouteFocusModal, - useRouteModal, -} from "../../../../../components/route-modal" -import { OverrideGrid } from "../../../common/components/override-grid" -import { OverrideTable } from "../../../common/components/overrides-drawer/overrides-drawer" -import { Override } from "../../../common/constants" -import { OverrideOption, OverrideState } from "../../../common/types" - -const CreateTaxRateSchema = z.object({ - name: z.string().min(1), - code: z.string().min(1), - rate: z.union([z.string(), z.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"), - products: z.array( - z.object({ - label: z.string(), - value: z.string(), - }) - ), - product_types: z.array( - z.object({ - label: z.string(), - value: z.string(), - }) - ), - shipping_options: z.array( - z.object({ - label: z.string(), - value: z.string(), - }) - ), -}) - -export const CreateTaxRateForm = () => { - const [open, setOpen] = useState(false) - - const [override, setOverride] = useState(null) - const [state, setState] = useState({ - [Override.PRODUCT]: false, - [Override.PRODUCT_TYPE]: false, - [Override.SHIPPING_OPTION]: false, - }) - - const [, setSearchParams] = useSearchParams() - - const { id } = useParams() - const { t } = useTranslation() - const { handleSuccess } = useRouteModal() - - const form = useForm>({ - defaultValues: { - name: "", - code: "", - rate: "", - products: [], - product_types: [], - shipping_options: [], - }, - resolver: zodResolver(CreateTaxRateSchema), - }) - - const selectedProducts = useWatch({ - control: form.control, - name: "products", - defaultValue: [], - }) - const selectedProductTypes = useWatch({ - control: form.control, - name: "product_types", - defaultValue: [], - }) - - const selectedShippingOptions = useWatch({ - control: form.control, - name: "shipping_options", - defaultValue: [], - }) - - const { mutateAsync, isLoading } = useAdminCreateTaxRate() - - const handleSubmit = form.handleSubmit(async (data) => { - const { rate, products, product_types, shipping_options, ...rest } = data - - const productsPaylaod = state[Override.PRODUCT] - ? products.map((p) => p.value) - : undefined - - const productTypesPayload = state[Override.PRODUCT_TYPE] - ? product_types.map((p) => p.value) - : undefined - - const shippingOptionsPayload = state[Override.SHIPPING_OPTION] - ? shipping_options.map((p) => p.value) - : undefined - - await mutateAsync( - { - region_id: id!, - rate: Number(rate), - products: productsPaylaod, - product_types: productTypesPayload, - shipping_options: shippingOptionsPayload, - ...rest, - }, - { - onSuccess: () => { - handleSuccess() - }, - } - ) - }) - - const handleOpenDrawer = (override: Override) => { - setOverride(override) - setOpen(true) - } - - const handleSaveOverrides = (override: Override) => { - let field: "products" | "product_types" | "shipping_options" - - switch (override) { - case Override.PRODUCT: - field = "products" - break - case Override.PRODUCT_TYPE: - field = "product_types" - break - case Override.SHIPPING_OPTION: - field = "shipping_options" - break - } - - return (options: OverrideOption[]) => { - form.setValue(field, options, { - shouldDirty: true, - shouldTouch: true, - }) - - setOpen(false) - } - } - - const handleRemoveOverride = (override: Override) => { - let field: "products" | "product_types" | "shipping_options" - - switch (override) { - case Override.PRODUCT: - field = "products" - break - case Override.PRODUCT_TYPE: - field = "product_types" - break - case Override.SHIPPING_OPTION: - field = "shipping_options" - break - } - - return (value: string) => { - const current = form.getValues(field) - - const newValue = current.filter((c: OverrideOption) => c.value !== value) - - form.setValue(field, newValue, { - shouldDirty: true, - shouldTouch: true, - }) - } - } - - const handleClearOverrides = (override: Override) => { - let field: "products" | "product_types" | "shipping_options" - - switch (override) { - case Override.PRODUCT: - field = "products" - break - case Override.PRODUCT_TYPE: - field = "product_types" - break - case Override.SHIPPING_OPTION: - field = "shipping_options" - break - } - - return () => { - form.setValue(field, [], { - shouldDirty: true, - shouldTouch: true, - }) - } - } - - const handleStateChange = (override: Override) => { - return (enabled: boolean) => { - setState((prev) => ({ - ...prev, - [override]: enabled, - })) - } - } - - const handleOpenChange = (open: boolean) => { - if (!open) { - setOverride(null) - setSearchParams( - {}, - { - replace: true, - } - ) - } - - setOpen(open) - } - - return ( - -
    - -
    - - - - -
    -
    - - - -
    -
    -
    - {t("taxes.taxRate.createTaxRate")} - - {t("taxes.taxRate.createTaxRateHint")} - -
    -
    -
    - { - return ( - - {t("fields.name")} - - - - - - ) - }} - /> - { - return ( - - {t("fields.rate")} - - - - - - ) - }} - /> - { - return ( - - {t("fields.code")} - - - - - - ) - }} - /> -
    -
    -
    - -
    -
    - - {t("taxes.taxRate.productOverridesLabel")} - - - {t("taxes.taxRate.productOverridesHint")} - -
    - - - -
    - -
    - -
    - -
    -
    -
    -
    -
    - -
    -
    - - {t("taxes.taxRate.productTypeOverridesLabel")} - - - {t("taxes.taxRate.productTypeOverridesHint")} - -
    - - - -
    - -
    - -
    - -
    -
    -
    -
    -
    - -
    -
    - - {t("taxes.taxRate.shippingOptionOverridesLabel")} - - - {t("taxes.taxRate.shippingOptionOverridesHint")} - -
    - - - -
    - -
    - -
    - -
    -
    -
    -
    -
    -
    - - - - - - - - - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/components/create-tax-rate-form/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/components/create-tax-rate-form/index.ts deleted file mode 100644 index d13cabc07e..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/components/create-tax-rate-form/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./create-tax-rate-form" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/index.ts deleted file mode 100644 index e956477331..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { TaxRateCreate as Component } from "./tax-rate-create" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/tax-rate-create.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/tax-rate-create.tsx deleted file mode 100644 index f33d0095e7..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-create/tax-rate-create.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { RouteFocusModal } from "../../../components/route-modal" -import { CreateTaxRateForm } from "./components/create-tax-rate-form" - -export const TaxRateCreate = () => { - return ( - - - - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/components/edit-tax-rate-overrides-form/edit-tax-rate-overrides-form.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/components/edit-tax-rate-overrides-form/edit-tax-rate-overrides-form.tsx deleted file mode 100644 index 3664600fdf..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/components/edit-tax-rate-overrides-form/edit-tax-rate-overrides-form.tsx +++ /dev/null @@ -1,414 +0,0 @@ -import { TaxRate } from "@medusajs/medusa" -import { Button, Heading, Switch, Text, clx } from "@medusajs/ui" -import * as Collapsible from "@radix-ui/react-collapsible" -import { useAdminUpdateTaxRate } from "medusa-react" -import { useState } from "react" -import { useForm, useWatch } from "react-hook-form" -import { useTranslation } from "react-i18next" -import { z } from "zod" - -import { zodResolver } from "@hookform/resolvers/zod" -import { useSearchParams } from "react-router-dom" -import { SplitView } from "../../../../../components/layout/split-view" -import { - RouteFocusModal, - useRouteModal, -} from "../../../../../components/route-modal" -import { OverrideGrid } from "../../../common/components/override-grid" -import { OverrideTable } from "../../../common/components/overrides-drawer/overrides-drawer" -import { Override } from "../../../common/constants" -import { OverrideOption, OverrideState } from "../../../common/types" - -type EditTaxRateOverridesFormProps = { - taxRate: TaxRate -} - -const EditTaxRateOverridesSchema = z.object({ - products: z.array( - z.object({ - label: z.string(), - value: z.string(), - }) - ), - product_types: z.array( - z.object({ - label: z.string(), - value: z.string(), - }) - ), - shipping_options: z.array( - z.object({ - label: z.string(), - value: z.string(), - }) - ), -}) - -export const EditTaxRateOverridesForm = ({ - taxRate, -}: EditTaxRateOverridesFormProps) => { - const [open, setOpen] = useState(false) - - const [override, setOverride] = useState(null) - const [state, setState] = useState({ - [Override.PRODUCT]: taxRate.products?.length > 0, - [Override.PRODUCT_TYPE]: taxRate.product_types?.length > 0, - [Override.SHIPPING_OPTION]: taxRate.shipping_options?.length > 0, - }) - - const [, setSearchParams] = useSearchParams() - - const { t } = useTranslation() - const { handleSuccess } = useRouteModal() - - const form = useForm>({ - defaultValues: { - products: - taxRate.products?.map((p) => ({ - label: p.title, - value: p.id, - })) || [], - product_types: - taxRate.product_types?.map((pt) => ({ - label: pt.value, - value: pt.id, - })) || [], - shipping_options: - taxRate.shipping_options?.map((so) => ({ - label: so.name, - value: so.id, - })) || [], - }, - resolver: zodResolver(EditTaxRateOverridesSchema), - }) - - const selectedProducts = useWatch({ - control: form.control, - name: "products", - }) - const selectedProductTypes = useWatch({ - control: form.control, - name: "product_types", - }) - - const selectedShippingOptions = useWatch({ - control: form.control, - name: "shipping_options", - }) - - const { mutateAsync, isLoading } = useAdminUpdateTaxRate(taxRate.id) - const handleSubmit = form.handleSubmit(async (data) => { - const { products, product_types, shipping_options } = data - - const productsPaylaod = state[Override.PRODUCT] - ? products.map((p) => p.value) - : [] - - const productTypesPayload = state[Override.PRODUCT_TYPE] - ? product_types.map((p) => p.value) - : [] - - const shippingOptionsPayload = state[Override.SHIPPING_OPTION] - ? shipping_options.map((p) => p.value) - : [] - - await mutateAsync( - { - products: productsPaylaod, - product_types: productTypesPayload, - shipping_options: shippingOptionsPayload, - }, - { - onSuccess: () => { - handleSuccess() - }, - } - ) - }) - - const handleOpenDrawer = (override: Override) => { - setOverride(override) - setOpen(true) - } - - const handleSaveOverrides = (override: Override) => { - let field: "products" | "product_types" | "shipping_options" - - switch (override) { - case Override.PRODUCT: - field = "products" - break - case Override.PRODUCT_TYPE: - field = "product_types" - break - case Override.SHIPPING_OPTION: - field = "shipping_options" - break - } - - return (options: OverrideOption[]) => { - form.setValue(field, options, { - shouldDirty: true, - shouldTouch: true, - }) - - setOpen(false) - } - } - - const handleRemoveOverride = (override: Override) => { - let field: "products" | "product_types" | "shipping_options" - - switch (override) { - case Override.PRODUCT: - field = "products" - break - case Override.PRODUCT_TYPE: - field = "product_types" - break - case Override.SHIPPING_OPTION: - field = "shipping_options" - break - } - - return (value: string) => { - const current = form.getValues(field) - - const newValue = current.filter((c: OverrideOption) => c.value !== value) - - form.setValue(field, newValue, { - shouldDirty: true, - shouldTouch: true, - }) - } - } - - const handleClearOverrides = (override: Override) => { - let field: "products" | "product_types" | "shipping_options" - - switch (override) { - case Override.PRODUCT: - field = "products" - break - case Override.PRODUCT_TYPE: - field = "product_types" - break - case Override.SHIPPING_OPTION: - field = "shipping_options" - break - } - - return () => { - form.setValue(field, [], { - shouldDirty: true, - shouldTouch: true, - }) - } - } - - const handleStateChange = (override: Override) => { - return (enabled: boolean) => { - setState((prev) => ({ - ...prev, - [override]: enabled, - })) - } - } - - const handleOpenChange = (open: boolean) => { - if (!open) { - setOverride(null) - setSearchParams( - {}, - { - replace: true, - } - ) - } - - setOpen(open) - } - - return ( - -
    - -
    - - - - -
    -
    - - - -
    -
    -
    - {t("taxes.taxRate.editOverridesTitle")} - - {t("taxes.taxRate.editOverridesHint")} - -
    - -
    -
    - - {t("taxes.taxRate.productOverridesLabel")} - - - {t("taxes.taxRate.productOverridesHint")} - -
    - - - -
    - -
    - -
    - -
    -
    -
    -
    -
    - -
    -
    - - {t("taxes.taxRate.productTypeOverridesLabel")} - - - {t("taxes.taxRate.productTypeOverridesHint")} - -
    - - - -
    - -
    - -
    - -
    -
    -
    -
    -
    - -
    -
    - - {t("taxes.taxRate.shippingOptionOverridesLabel")} - - - {t("taxes.taxRate.shippingOptionOverridesHint")} - -
    - - - -
    - -
    - -
    - -
    -
    -
    -
    -
    -
    - - - - - - - - - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/components/edit-tax-rate-overrides-form/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/components/edit-tax-rate-overrides-form/index.ts deleted file mode 100644 index 5ed67b5511..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/components/edit-tax-rate-overrides-form/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./edit-tax-rate-overrides-form" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/index.ts deleted file mode 100644 index 1344dc3e28..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { TaxRateEditOverrides as Component } from "./tax-rate-edit-overrides" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/tax-rate-edit-overrides.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/tax-rate-edit-overrides.tsx deleted file mode 100644 index e06d15e9d1..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit-overrides/tax-rate-edit-overrides.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { useAdminTaxRate } from "medusa-react" -import { useParams } from "react-router-dom" -import { RouteFocusModal } from "../../../components/route-modal" -import { EditTaxRateOverridesForm } from "./components/edit-tax-rate-overrides-form" - -export const TaxRateEditOverrides = () => { - const { rate_id } = useParams() - - const { tax_rate, isLoading, isError, error } = useAdminTaxRate(rate_id!, { - expand: ["products", "shipping_options", "product_types"], - }) - - const ready = !isLoading && tax_rate - - if (isError) { - throw error - } - - return ( - - {ready && } - - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/components/edit-tax-rate-form/edit-tax-rate-form.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/components/edit-tax-rate-form/edit-tax-rate-form.tsx deleted file mode 100644 index 70703b029a..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/components/edit-tax-rate-form/edit-tax-rate-form.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import { zodResolver } from "@hookform/resolvers/zod" -import { useForm } from "react-hook-form" -import { z } from "zod" - -import { TaxRate } from "@medusajs/medusa" -import { Button, Input } from "@medusajs/ui" -import { useAdminUpdateTaxRate } from "medusa-react" -import { useTranslation } from "react-i18next" -import { Form } from "../../../../../components/common/form" -import { PercentageInput } from "../../../../../components/common/percentage-input" -import { - RouteDrawer, - RouteFocusModal, - useRouteModal, -} from "../../../../../components/route-modal" - -type EditTaxRateFormProps = { - taxRate: TaxRate -} - -const EditTaxRateSchema = z.object({ - name: z.string().min(1), - code: z.string().min(1), - rate: z.union([z.string(), z.number()]).refine((value) => { - if (value === "") { - return true // we allow empty string and read it as null - } - - const num = Number(value) - - if (num >= 0 && num <= 100) { - return true - } - - return false - }, "Tax rate must be a number between 0 and 100"), -}) - -export const EditTaxRateForm = ({ taxRate }: EditTaxRateFormProps) => { - const { t } = useTranslation() - const { handleSuccess } = useRouteModal() - - const form = useForm>({ - defaultValues: { - name: taxRate.name, - code: taxRate.code || "", - rate: taxRate.rate || "", - }, - resolver: zodResolver(EditTaxRateSchema), - }) - - const { mutateAsync, isLoading } = useAdminUpdateTaxRate(taxRate.id) - - const handleSubmit = form.handleSubmit(async (data) => { - await mutateAsync( - { - ...data, - rate: data.rate ? Number(data.rate) : null, - }, - { - onSuccess: () => { - handleSuccess() - }, - } - ) - }) - - return ( - -
    - - { - return ( - - {t("fields.name")} - - - - - - ) - }} - /> - { - return ( - - {t("fields.rate")} - - - - - - ) - }} - /> - { - return ( - - {t("fields.code")} - - - - - - ) - }} - /> - - -
    - - - - -
    -
    -
    -
    - ) -} diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/components/edit-tax-rate-form/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/components/edit-tax-rate-form/index.ts deleted file mode 100644 index 7181c7e4be..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/components/edit-tax-rate-form/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./edit-tax-rate-form" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/index.ts b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/index.ts deleted file mode 100644 index ff668e0b3b..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { TaxRateEdit as Component } from "./tax-rate-edit" diff --git a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/tax-rate-edit.tsx b/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/tax-rate-edit.tsx deleted file mode 100644 index 2e826f19ce..0000000000 --- a/packages/admin-next/dashboard/src/routes/taxes/tax-rate-edit/tax-rate-edit.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Heading } from "@medusajs/ui" -import { useAdminTaxRate } from "medusa-react" -import { useTranslation } from "react-i18next" -import { useParams } from "react-router-dom" -import { RouteDrawer } from "../../../components/route-modal" -import { EditTaxRateForm } from "./components/edit-tax-rate-form" - -export const TaxRateEdit = () => { - const { rate_id } = useParams() - const { t } = useTranslation() - - const { tax_rate, isLoading, isError, error } = useAdminTaxRate(rate_id!) - - const ready = !isLoading && tax_rate - - if (isError) { - throw error - } - - return ( - - - {t("taxes.taxRate.editTaxRate")} - - {ready && } - - ) -} diff --git a/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/components/region-list-table/index.ts b/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/components/region-list-table/index.ts new file mode 100644 index 0000000000..3be79c1b50 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/components/region-list-table/index.ts @@ -0,0 +1 @@ +export * from "./tax-region-list-table" diff --git a/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/components/region-list-table/tax-region-list-table.tsx b/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/components/region-list-table/tax-region-list-table.tsx new file mode 100644 index 0000000000..95b66eedd8 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/components/region-list-table/tax-region-list-table.tsx @@ -0,0 +1,125 @@ +import { PencilSquare, Trash } from "@medusajs/icons" +import { Button, Container, Heading, usePrompt } from "@medusajs/ui" +import { createColumnHelper } from "@tanstack/react-table" +import { useMemo } from "react" +import { useTranslation } from "react-i18next" +import { Link } from "react-router-dom" +import { AdminTaxRegionResponse } from "@medusajs/types" +import { ActionMenu } from "../../../../../components/common/action-menu" +import { DataTable } from "../../../../../components/table/data-table" +import { useRegionTableFilters } from "../../../../../hooks/table/filters/use-region-table-filters" +import { useDataTable } from "../../../../../hooks/use-data-table" +import { useDeleteRegion } from "../../../../../hooks/api/regions" +import { useTaxRegions } from "../../../../../hooks/api/tax-regions" +import { useTaxRegionTableQuery } from "../../../../../hooks/table/query/use-tax-region-table-query copy" +import { t } from "i18next" +import { DateCell } from "../../../../../components/table/table-cells/common/date-cell" + +const PAGE_SIZE = 20 + +export const TaxRegionListTable = () => { + const { t } = useTranslation() + + const { searchParams, raw } = useTaxRegionTableQuery({ pageSize: PAGE_SIZE }) + const { tax_regions, count, isLoading, isError, error } = useTaxRegions({ + ...searchParams, + }) + + const filters = useRegionTableFilters() + const columns = useColumns() + + const { table } = useDataTable({ + data: tax_regions ?? [], + columns, + count, + enablePagination: true, + getRowId: (row) => row.id, + pageSize: PAGE_SIZE, + }) + + if (isError) { + throw error + } + + return ( + +
    + {t("taxes.domain")} + + + +
    + `${row.original.id}`} + pagination + search + queryObject={raw} + /> +
    + ) +} + +const TaxRegionActions = ({ + taxRegion, +}: { + taxRegion: AdminTaxRegionResponse["tax_region"] +}) => { + const { t } = useTranslation() + + return ( + , + }, + ], + }, + ]} + /> + ) +} + +const columnHelper = createColumnHelper() + +const useColumns = () => { + return useMemo( + () => [ + columnHelper.accessor("name", { + header: t("fields.code"), + cell: ({ getValue }) => ( +
    + {getValue()} +
    + ), + }), + columnHelper.accessor("created_at", { + header: t("fields.created"), + cell: ({ getValue }) => { + const date = getValue() + + return + }, + }), + columnHelper.display({ + id: "actions", + cell: ({ row }) => { + return + }, + }), + ], + [t] + ) +} diff --git a/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/index.ts b/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/index.ts new file mode 100644 index 0000000000..94fbf39b1c --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/index.ts @@ -0,0 +1 @@ +export { TaxRegionsList as Component } from "./tax-region-list" diff --git a/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/tax-region-list.tsx b/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/tax-region-list.tsx new file mode 100644 index 0000000000..b9e4b254f4 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/taxes/tax-region-list/tax-region-list.tsx @@ -0,0 +1,11 @@ +import { Outlet } from "react-router-dom" +import { TaxRegionListTable } from "./components/region-list-table" + +export const TaxRegionsList = () => { + return ( +
    + + +
    + ) +} diff --git a/packages/medusa/src/api-v2/admin/tax-regions/middlewares.ts b/packages/medusa/src/api-v2/admin/tax-regions/middlewares.ts index c09a14d629..fc149ee14f 100644 --- a/packages/medusa/src/api-v2/admin/tax-regions/middlewares.ts +++ b/packages/medusa/src/api-v2/admin/tax-regions/middlewares.ts @@ -1,10 +1,11 @@ import * as QueryConfig from "./query-config" -import { AdminGetTaxRegionsParams, AdminPostTaxRegionsReq } from "./validators" -import { transformBody, transformQuery } from "../../../api/middlewares" +import { AdminCreateTaxRegion, AdminGetTaxRegionsParams } from "./validators" import { MiddlewareRoute } from "../../../loaders/helpers/routing/types" import { authenticate } from "../../../utils/authenticate-middleware" +import { validateAndTransformBody } from "../../utils/validate-body" +import { validateAndTransformQuery } from "../../utils/validate-query" export const adminTaxRegionRoutesMiddlewares: MiddlewareRoute[] = [ { @@ -15,13 +16,19 @@ export const adminTaxRegionRoutesMiddlewares: MiddlewareRoute[] = [ { method: "POST", matcher: "/admin/tax-regions", - middlewares: [transformBody(AdminPostTaxRegionsReq)], + middlewares: [ + validateAndTransformBody(AdminCreateTaxRegion), + validateAndTransformQuery( + AdminGetTaxRegionsParams, + QueryConfig.listTransformQueryConfig + ), + ], }, { method: "GET", matcher: "/admin/tax-regions", middlewares: [ - transformQuery( + validateAndTransformQuery( AdminGetTaxRegionsParams, QueryConfig.listTransformQueryConfig ), diff --git a/packages/medusa/src/api-v2/admin/tax-regions/query-config.ts b/packages/medusa/src/api-v2/admin/tax-regions/query-config.ts index b7d44bc8f5..73ef61ff25 100644 --- a/packages/medusa/src/api-v2/admin/tax-regions/query-config.ts +++ b/packages/medusa/src/api-v2/admin/tax-regions/query-config.ts @@ -1,6 +1,4 @@ -export const defaultAdminTaxRegionRelations = [] -export const allowedAdminTaxRegionRelations = [] -export const defaultAdminTaxRegionFields = [ +export const defaults = [ "id", "country_code", "province_code", @@ -14,13 +12,11 @@ export const defaultAdminTaxRegionFields = [ ] export const retrieveTransformQueryConfig = { - defaultFields: defaultAdminTaxRegionFields, - defaultRelations: defaultAdminTaxRegionRelations, - allowedRelations: allowedAdminTaxRegionRelations, + defaults, isList: false, } export const listTransformQueryConfig = { - defaultLimit: 20, + ...retrieveTransformQueryConfig, isList: true, } diff --git a/packages/medusa/src/api-v2/admin/tax-regions/route.ts b/packages/medusa/src/api-v2/admin/tax-regions/route.ts index f5c601dc6c..0b4c4b9c32 100644 --- a/packages/medusa/src/api-v2/admin/tax-regions/route.ts +++ b/packages/medusa/src/api-v2/admin/tax-regions/route.ts @@ -1,14 +1,16 @@ import { createTaxRegionsWorkflow } from "@medusajs/core-flows" -import { remoteQueryObjectFromString } from "@medusajs/utils" +import { + ContainerRegistrationKeys, + remoteQueryObjectFromString, +} from "@medusajs/utils" import { AuthenticatedMedusaRequest, MedusaResponse, } from "../../../types/routing" -import { defaultAdminTaxRegionFields } from "./query-config" -import { AdminPostTaxRegionsReq } from "./validators" +import { AdminCreateTaxRegionType } from "./validators" export const POST = async ( - req: AuthenticatedMedusaRequest, + req: AuthenticatedMedusaRequest, res: MedusaResponse ) => { const { result, errors } = await createTaxRegionsWorkflow(req.scope).run({ @@ -30,10 +32,35 @@ export const POST = async ( const query = remoteQueryObjectFromString({ entryPoint: "tax_region", variables: { id: result[0].id }, - fields: defaultAdminTaxRegionFields, + fields: req.remoteQueryConfig.fields, }) const [taxRegion] = await remoteQuery(query) res.status(200).json({ tax_region: taxRegion }) } + +export const GET = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse +) => { + const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY) + + const { rows: tax_regions, metadata } = await remoteQuery( + remoteQueryObjectFromString({ + entryPoint: "tax_regions", + variables: { + filters: req.filterableFields, + ...req.remoteQueryConfig.pagination, + }, + fields: req.remoteQueryConfig.fields, + }) + ) + + res.status(200).json({ + tax_regions, + count: metadata.count, + offset: metadata.skip, + limit: metadata.take, + }) +} diff --git a/packages/medusa/src/api-v2/admin/tax-regions/validators.ts b/packages/medusa/src/api-v2/admin/tax-regions/validators.ts index a4c4addb8f..d107adf242 100644 --- a/packages/medusa/src/api-v2/admin/tax-regions/validators.ts +++ b/packages/medusa/src/api-v2/admin/tax-regions/validators.ts @@ -1,127 +1,45 @@ -import { OperatorMap } from "@medusajs/types" -import { Type } from "class-transformer" +import { z } from "zod" import { - IsNumber, - IsObject, - IsOptional, - IsString, - ValidateNested, -} from "class-validator" -import { extendedFindParamsMixin, FindParams } from "../../../types/common" -import { OperatorMapValidator } from "../../../types/validators/operator-map" + createFindParams, + createOperatorMap, + createSelectParams, +} from "../../utils/validators" -export class AdminGetTaxRegionsTaxRegionParams extends FindParams {} +export const AdminGetTaxRegionParams = createSelectParams() -export class AdminGetTaxRegionsParams extends extendedFindParamsMixin({ - limit: 50, +export type AdminCreateTaxRegionsParams = z.infer< + typeof AdminGetTaxRegionsParams +> +export const AdminGetTaxRegionsParams = createFindParams({ + limit: 20, offset: 0, -}) { - /** - * Search parameter for regions. - */ - @IsString({ each: true }) - @IsOptional() - id?: string | string[] +}).merge( + z.object({ + id: z.union([z.string(), z.array(z.string())]).optional(), + country_code: z.union([z.string(), z.array(z.string())]).optional(), + province_code: z.union([z.string(), z.array(z.string())]).optional(), + parent_id: z.union([z.string(), z.array(z.string())]).optional(), + created_by: z.union([z.string(), z.array(z.string())]).optional(), + created_at: createOperatorMap().optional(), + updated_at: createOperatorMap().optional(), + deleted_at: createOperatorMap().optional(), + $and: z.lazy(() => AdminGetTaxRegionsParams.array()).optional(), + $or: z.lazy(() => AdminGetTaxRegionsParams.array()).optional(), + }) +) - /** - * Filter by country code. - */ - @IsString({ each: true }) - @IsOptional() - country_code?: string | string[] - - /** - * Filter by province code - */ - @IsString({ each: true }) - @IsOptional() - province_code?: string | string[] - - /** - * Filter by id of parent Tax Region. - */ - @IsString({ each: true }) - @IsOptional() - parent_id?: string | string[] - - /** - * Filter by who created the Tax Region. - */ - @IsString({ each: true }) - @IsOptional() - created_by?: string | string[] - - /** - * Date filters to apply on the Tax Regions' `created_at` date. - */ - @IsOptional() - @ValidateNested() - @Type(() => OperatorMapValidator) - created_at?: OperatorMap - - /** - * Date filters to apply on the Tax Regions' `updated_at` date. - */ - @IsOptional() - @ValidateNested() - @Type(() => OperatorMapValidator) - updated_at?: OperatorMap - - /** - * Date filters to apply on the Tax Regions' `deleted_at` date. - */ - @ValidateNested() - @IsOptional() - @Type(() => OperatorMapValidator) - deleted_at?: OperatorMap - - // Additional filters from BaseFilterable - @IsOptional() - @ValidateNested({ each: true }) - @Type(() => AdminGetTaxRegionsParams) - $and?: AdminGetTaxRegionsParams[] - - @IsOptional() - @ValidateNested({ each: true }) - @Type(() => AdminGetTaxRegionsParams) - $or?: AdminGetTaxRegionsParams[] -} - -class CreateDefaultTaxRate { - @IsOptional() - @IsNumber() - rate?: number | null - - @IsOptional() - @IsString() - code?: string | null - - @IsString() - name: string - - @IsObject() - @IsOptional() - metadata?: Record -} - -export class AdminPostTaxRegionsReq { - @IsString() - country_code: string - - @IsString() - @IsOptional() - province_code?: string - - @IsString() - @IsOptional() - parent_id?: string - - @ValidateNested() - @IsOptional() - @Type(() => CreateDefaultTaxRate) - default_tax_rate?: CreateDefaultTaxRate - - @IsObject() - @IsOptional() - metadata?: Record -} +export type AdminCreateTaxRegionType = z.infer +export const AdminCreateTaxRegion = z.object({ + country_code: z.string(), + province_code: z.string().optional(), + parent_id: z.string().optional(), + default_tax_rate: z + .object({ + rate: z.number().optional(), + code: z.string().optional(), + name: z.string(), + metadata: z.record(z.unknown()).optional(), + }) + .optional(), + metadata: z.record(z.unknown()).optional(), +}) diff --git a/packages/types/src/http/index.ts b/packages/types/src/http/index.ts index 2a1fec4ce3..b012a3d07c 100644 --- a/packages/types/src/http/index.ts +++ b/packages/types/src/http/index.ts @@ -3,3 +3,4 @@ export * from "./fulfillment" export * from "./pricing" export * from "./sales-channel" export * from "./stock-locations" +export * from "./tax" diff --git a/packages/types/src/http/tax/admin/index.ts b/packages/types/src/http/tax/admin/index.ts new file mode 100644 index 0000000000..d69cd9a33b --- /dev/null +++ b/packages/types/src/http/tax/admin/index.ts @@ -0,0 +1 @@ +export * from "./tax-regions" diff --git a/packages/types/src/http/tax/admin/tax-regions.ts b/packages/types/src/http/tax/admin/tax-regions.ts new file mode 100644 index 0000000000..44d1d02979 --- /dev/null +++ b/packages/types/src/http/tax/admin/tax-regions.ts @@ -0,0 +1,33 @@ +import { PaginatedResponse } from "../../../common" + +/** + * @experimental + */ +interface TaxRegionResponse { + id: string + rate: number | null + code: string | null + name: string + metadata: Record | null + tax_region_id: string + is_combinable: boolean + is_default: boolean + created_at: string | Date + updated_at: string | Date + deleted_at: Date | null + created_by: string | null +} + +/** + * @experimental + */ +export interface AdminTaxRegionResponse { + tax_region: TaxRegionResponse +} + +/** + * @experimental + */ +export interface AdminTaxRegionListResponse extends PaginatedResponse { + tax_regions: TaxRegionResponse[] +} diff --git a/packages/types/src/http/tax/index.ts b/packages/types/src/http/tax/index.ts new file mode 100644 index 0000000000..26b8eb9dad --- /dev/null +++ b/packages/types/src/http/tax/index.ts @@ -0,0 +1 @@ +export * from "./admin"