feat(dashboard): Region refactor (#7083)
* wip: regions refactor * feat: finalize region domain * fix: cleanup error messages
This commit is contained in:
1 parent
e2fabc1c05
commit
f62de56b63
13 files changed
+127
-27
No files matched your search
@@ -17,6 +17,9 @@
|
|||||||
"next": "Next",
|
"next": "Next",
|
||||||
"prev": "Prev",
|
"prev": "Prev",
|
||||||
"is": "is",
|
"is": "is",
|
||||||
|
"timeline": "Timeline",
|
||||||
|
"success": "Success",
|
||||||
|
"error": "Error",
|
||||||
"select": "Select",
|
"select": "Select",
|
||||||
"selected": "Selected",
|
"selected": "Selected",
|
||||||
"enabled": "Enabled",
|
"enabled": "Enabled",
|
||||||
@@ -1057,6 +1060,12 @@
|
|||||||
"priceType": "Price Type",
|
"priceType": "Price Type",
|
||||||
"flatRate": "Flat Rate",
|
"flatRate": "Flat Rate",
|
||||||
"calculated": "Calculated",
|
"calculated": "Calculated",
|
||||||
|
"toast": {
|
||||||
|
"delete": "Region deleted successfully",
|
||||||
|
"edit": "Region edit saved",
|
||||||
|
"create": "Region created successfully",
|
||||||
|
"countries": "Region countries updated successfully"
|
||||||
|
},
|
||||||
"shippingOption": {
|
"shippingOption": {
|
||||||
"createShippingOption": "Create Shipping Option",
|
"createShippingOption": "Create Shipping Option",
|
||||||
"createShippingOptionHint": "Create a new shipping option for the region.",
|
"createShippingOptionHint": "Create a new shipping option for the region.",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
import { client } from "../../lib/client"
|
import { client } from "../../lib/client"
|
||||||
import { queryClient } from "../../lib/medusa"
|
import { queryClient } from "../../lib/medusa"
|
||||||
import { queryKeysFactory } from "../../lib/query-key-factory"
|
import { queryKeysFactory } from "../../lib/query-key-factory"
|
||||||
import { CreateRegionReq } from "../../types/api-payloads"
|
import { CreateRegionReq, UpdateRegionReq } from "../../types/api-payloads"
|
||||||
import {
|
import {
|
||||||
RegionDeleteRes,
|
RegionDeleteRes,
|
||||||
RegionListRes,
|
RegionListRes,
|
||||||
@@ -66,7 +66,7 @@ export const useCreateRegion = (
|
|||||||
|
|
||||||
export const useUpdateRegion = (
|
export const useUpdateRegion = (
|
||||||
id: string,
|
id: string,
|
||||||
options?: UseMutationOptions<RegionRes, Error, CreateRegionReq>
|
options?: UseMutationOptions<RegionRes, Error, UpdateRegionReq>
|
||||||
) => {
|
) => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: (payload) => client.regions.update(id, payload),
|
mutationFn: (payload) => client.regions.update(id, payload),
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const useCountries = ({
|
|||||||
throw json(`The key ${key} is not a valid order key`, 500)
|
throw json(`The key ${key} is not a valid order key`, 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
const sortKey: keyof Country = key === "code" ? "iso_2" : "name"
|
const sortKey: keyof RegionCountryDTO = key === "code" ? "iso_2" : "name"
|
||||||
|
|
||||||
data.sort((a, b) => {
|
data.sort((a, b) => {
|
||||||
if (a[sortKey] === null && b[sortKey] === null) {
|
if (a[sortKey] === null && b[sortKey] === null) {
|
||||||
|
|||||||
+18
-11
@@ -9,7 +9,7 @@ import { useForm } from "react-hook-form"
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
|
|
||||||
import { Button, Checkbox } from "@medusajs/ui"
|
import { Button, Checkbox, toast } from "@medusajs/ui"
|
||||||
import { RegionCountryDTO, RegionDTO } from "@medusajs/types"
|
import { RegionCountryDTO, RegionDTO } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
RouteFocusModal,
|
RouteFocusModal,
|
||||||
@@ -21,7 +21,7 @@ import { countries as staticCountries } from "../../../../../lib/countries"
|
|||||||
import { useCountries } from "../../../common/hooks/use-countries"
|
import { useCountries } from "../../../common/hooks/use-countries"
|
||||||
import { useCountryTableColumns } from "../../../common/hooks/use-country-table-columns"
|
import { useCountryTableColumns } from "../../../common/hooks/use-country-table-columns"
|
||||||
import { useCountryTableQuery } from "../../../common/hooks/use-country-table-query"
|
import { useCountryTableQuery } from "../../../common/hooks/use-country-table-query"
|
||||||
import { useUpdateRegion } from "../../../../../hooks/api/regions.tsx"
|
import { useUpdateRegion } from "../../../../../hooks/api/regions"
|
||||||
|
|
||||||
type AddCountriesFormProps = {
|
type AddCountriesFormProps = {
|
||||||
region: RegionDTO
|
region: RegionDTO
|
||||||
@@ -98,7 +98,7 @@ export const AddCountriesForm = ({ region }: AddCountriesFormProps) => {
|
|||||||
prefix: PREFIX,
|
prefix: PREFIX,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { mutateAsync, isLoading } = useUpdateRegion(region.id)
|
const { mutateAsync, isPending: isLoading } = useUpdateRegion(region.id)
|
||||||
|
|
||||||
const handleSubmit = form.handleSubmit(async (values) => {
|
const handleSubmit = form.handleSubmit(async (values) => {
|
||||||
const payload = [
|
const payload = [
|
||||||
@@ -106,16 +106,23 @@ export const AddCountriesForm = ({ region }: AddCountriesFormProps) => {
|
|||||||
...values.countries,
|
...values.countries,
|
||||||
]
|
]
|
||||||
|
|
||||||
await mutateAsync(
|
try {
|
||||||
{
|
await mutateAsync({
|
||||||
countries: payload,
|
countries: payload,
|
||||||
},
|
})
|
||||||
{
|
|
||||||
onSuccess: () => {
|
|
||||||
handleSuccess()
|
handleSuccess()
|
||||||
},
|
|
||||||
|
toast.success(t("general.success"), {
|
||||||
|
description: t("regions.toast.countries"),
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
toast.error(t("general.error"), {
|
||||||
|
description: e.message,
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -132,7 +139,7 @@ export const AddCountriesForm = ({ region }: AddCountriesFormProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</RouteFocusModal.Close>
|
</RouteFocusModal.Close>
|
||||||
<Button size="small" isLoading={isLoading} type="submit">
|
<Button size="small" isLoading={isLoading} type="submit">
|
||||||
{t("actions.save")}
|
{t("actions.add")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</RouteFocusModal.Header>
|
</RouteFocusModal.Header>
|
||||||
|
|||||||
+6
-1
@@ -6,7 +6,12 @@ import { useRegion } from "../../../hooks/api/regions"
|
|||||||
export const RegionAddCountries = () => {
|
export const RegionAddCountries = () => {
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
|
|
||||||
const { region, isLoading, isError, error } = useRegion(id!, {
|
const {
|
||||||
|
region,
|
||||||
|
isPending: isLoading,
|
||||||
|
isError,
|
||||||
|
error,
|
||||||
|
} = useRegion(id!, {
|
||||||
fields: "*payment_providers",
|
fields: "*payment_providers",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
+11
@@ -9,6 +9,7 @@ import {
|
|||||||
Switch,
|
Switch,
|
||||||
Text,
|
Text,
|
||||||
clx,
|
clx,
|
||||||
|
toast,
|
||||||
} from "@medusajs/ui"
|
} from "@medusajs/ui"
|
||||||
import { RowSelectionState, createColumnHelper } from "@tanstack/react-table"
|
import { RowSelectionState, createColumnHelper } from "@tanstack/react-table"
|
||||||
import { useMemo, useState } from "react"
|
import { useMemo, useState } from "react"
|
||||||
@@ -91,8 +92,18 @@ export const CreateRegionForm = ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
onSuccess: ({ region }) => {
|
onSuccess: ({ region }) => {
|
||||||
|
toast.success(t("general.success"), {
|
||||||
|
description: t("regions.toast.create"),
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
handleSuccess(`../${region.id}`)
|
handleSuccess(`../${region.id}`)
|
||||||
},
|
},
|
||||||
|
onError: (e) => {
|
||||||
|
toast.error(t("general.error"), {
|
||||||
|
description: e.message,
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { usePaymentProviders } from "../../../hooks/api/payments"
|
|||||||
import { useStore } from "../../../hooks/api/store"
|
import { useStore } from "../../../hooks/api/store"
|
||||||
|
|
||||||
export const RegionCreate = () => {
|
export const RegionCreate = () => {
|
||||||
const { store, isLoading, isError, error } = useStore()
|
const { store, isPending: isLoading, isError, error } = useStore()
|
||||||
|
|
||||||
const storeCurrencies = (store?.supported_currency_codes ?? []).map(
|
const storeCurrencies = (store?.supported_currency_codes ?? []).map(
|
||||||
(code) => currencies[code.toUpperCase()]
|
(code) => currencies[code.toUpperCase()]
|
||||||
|
|||||||
+26
-2
@@ -1,5 +1,5 @@
|
|||||||
import { PlusMini, Trash } from "@medusajs/icons"
|
import { PlusMini, Trash } from "@medusajs/icons"
|
||||||
import { Checkbox, Container, Heading, usePrompt } from "@medusajs/ui"
|
import { Checkbox, Container, Heading, toast, usePrompt } from "@medusajs/ui"
|
||||||
import { RegionCountryDTO, RegionDTO } from "@medusajs/types"
|
import { RegionCountryDTO, RegionDTO } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
@@ -14,7 +14,7 @@ import { useDataTable } from "../../../../../hooks/use-data-table"
|
|||||||
import { useCountries } from "../../../common/hooks/use-countries"
|
import { useCountries } from "../../../common/hooks/use-countries"
|
||||||
import { useCountryTableColumns } from "../../../common/hooks/use-country-table-columns"
|
import { useCountryTableColumns } from "../../../common/hooks/use-country-table-columns"
|
||||||
import { useCountryTableQuery } from "../../../common/hooks/use-country-table-query"
|
import { useCountryTableQuery } from "../../../common/hooks/use-country-table-query"
|
||||||
import { useUpdateRegion } from "../../../../../hooks/api/regions.tsx"
|
import { useUpdateRegion } from "../../../../../hooks/api/regions"
|
||||||
|
|
||||||
type RegionCountrySectionProps = {
|
type RegionCountrySectionProps = {
|
||||||
region: RegionDTO
|
region: RegionDTO
|
||||||
@@ -82,9 +82,21 @@ export const RegionCountrySection = ({ region }: RegionCountrySectionProps) => {
|
|||||||
.filter((c) => !ids.includes(c.iso_2))
|
.filter((c) => !ids.includes(c.iso_2))
|
||||||
.map((c) => c.iso_2)
|
.map((c) => c.iso_2)
|
||||||
|
|
||||||
|
try {
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
countries: payload,
|
countries: payload,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
toast.success(t("general.success"), {
|
||||||
|
description: t("regions.toast.countries"),
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
toast.error(t("general.error"), {
|
||||||
|
description: e.message,
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -158,9 +170,21 @@ const CountryActions = ({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
await mutateAsync({
|
await mutateAsync({
|
||||||
countries: payload,
|
countries: payload,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
toast.success(t("general.success"), {
|
||||||
|
description: t("regions.toast.countries"),
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
toast.error(t("general.error"), {
|
||||||
|
description: e.message,
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
+12
-1
@@ -1,6 +1,6 @@
|
|||||||
import { PencilSquare, Trash } from "@medusajs/icons"
|
import { PencilSquare, Trash } from "@medusajs/icons"
|
||||||
import { RegionDTO } from "@medusajs/types"
|
import { RegionDTO } from "@medusajs/types"
|
||||||
import { Badge, Container, Heading, Text, usePrompt } from "@medusajs/ui"
|
import { Badge, Container, Heading, Text, toast, usePrompt } from "@medusajs/ui"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
import { useNavigate } from "react-router-dom"
|
import { useNavigate } from "react-router-dom"
|
||||||
@@ -76,7 +76,18 @@ const RegionActions = ({ region }: { region: RegionDTO }) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
await mutateAsync(undefined)
|
await mutateAsync(undefined)
|
||||||
|
toast.success(t("general.success"), {
|
||||||
|
description: t("regions.toast.delete"),
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
toast.error(t("general.error"), {
|
||||||
|
description: e.message,
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
}
|
||||||
navigate("/settings/regions", { replace: true })
|
navigate("/settings/regions", { replace: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,12 @@ export const RegionDetail = () => {
|
|||||||
>
|
>
|
||||||
|
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
const { region, isLoading, isError, error } = useRegion(
|
const {
|
||||||
|
region,
|
||||||
|
isPending: isLoading,
|
||||||
|
isError,
|
||||||
|
error,
|
||||||
|
} = useRegion(
|
||||||
id!,
|
id!,
|
||||||
{ fields: "*payment_providers,*countries" },
|
{ fields: "*payment_providers,*countries" },
|
||||||
{
|
{
|
||||||
|
|||||||
+12
-2
@@ -1,4 +1,4 @@
|
|||||||
import { Button, Input, Select, Text } from "@medusajs/ui"
|
import { Button, Input, Select, Text, toast } from "@medusajs/ui"
|
||||||
import { useForm } from "react-hook-form"
|
import { useForm } from "react-hook-form"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import * as zod from "zod"
|
import * as zod from "zod"
|
||||||
@@ -42,7 +42,7 @@ export const EditRegionForm = ({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const { mutateAsync, isLoading } = useUpdateRegion(region.id)
|
const { mutateAsync, isPending: isLoading } = useUpdateRegion(region.id)
|
||||||
|
|
||||||
const handleSubmit = form.handleSubmit(async (values) => {
|
const handleSubmit = form.handleSubmit(async (values) => {
|
||||||
await mutateAsync(
|
await mutateAsync(
|
||||||
@@ -53,8 +53,18 @@ export const EditRegionForm = ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
|
toast.success(t("general.success"), {
|
||||||
|
description: t("regions.toast.edit"),
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
handleSuccess()
|
handleSuccess()
|
||||||
},
|
},
|
||||||
|
onError: (e) => {
|
||||||
|
toast.error(t("general.error"), {
|
||||||
|
description: e.message,
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ export const RegionEdit = () => {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
region,
|
region,
|
||||||
isLoading: isRegionLoading,
|
isPending: isRegionLoading,
|
||||||
isError: isRegionError,
|
isError: isRegionError,
|
||||||
error: regionError,
|
error: regionError,
|
||||||
} = useRegion(id!, { fields: "*payment_providers" })
|
} = useRegion(id!, { fields: "*payment_providers" })
|
||||||
|
|
||||||
const {
|
const {
|
||||||
store,
|
store,
|
||||||
isLoading: isStoreLoading,
|
isPending: isStoreLoading,
|
||||||
isError: isStoreError,
|
isError: isStoreError,
|
||||||
error: storeError,
|
error: storeError,
|
||||||
} = useStore()
|
} = useStore()
|
||||||
|
|||||||
+21
-3
@@ -1,10 +1,11 @@
|
|||||||
import { PencilSquare, Trash } from "@medusajs/icons"
|
import { PencilSquare, Trash } from "@medusajs/icons"
|
||||||
import { RegionDTO } from "@medusajs/types"
|
import { RegionDTO } from "@medusajs/types"
|
||||||
import { Button, Container, Heading, usePrompt } from "@medusajs/ui"
|
import { Button, Container, Heading, usePrompt, toast } from "@medusajs/ui"
|
||||||
import { createColumnHelper } from "@tanstack/react-table"
|
import { createColumnHelper } from "@tanstack/react-table"
|
||||||
import { useMemo } from "react"
|
import { useMemo } from "react"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom"
|
||||||
|
import { keepPreviousData } from "@tanstack/react-query"
|
||||||
|
|
||||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||||
import { DataTable } from "../../../../../components/table/data-table"
|
import { DataTable } from "../../../../../components/table/data-table"
|
||||||
@@ -20,13 +21,19 @@ export const RegionListTable = () => {
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const { searchParams, raw } = useRegionTableQuery({ pageSize: PAGE_SIZE })
|
const { searchParams, raw } = useRegionTableQuery({ pageSize: PAGE_SIZE })
|
||||||
const { regions, count, isLoading, isError, error } = useRegions(
|
const {
|
||||||
|
regions,
|
||||||
|
count,
|
||||||
|
isPending: isLoading,
|
||||||
|
isError,
|
||||||
|
error,
|
||||||
|
} = useRegions(
|
||||||
{
|
{
|
||||||
...searchParams,
|
...searchParams,
|
||||||
fields: "*payment_providers",
|
fields: "*payment_providers",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -96,7 +103,18 @@ const RegionActions = ({ region }: { region: RegionDTO }) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
await mutateAsync(undefined)
|
await mutateAsync(undefined)
|
||||||
|
toast.success(t("general.success"), {
|
||||||
|
description: t("regions.toast.delete"),
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
toast.error(t("general.error"), {
|
||||||
|
description: e.message,
|
||||||
|
dismissLabel: t("actions.close"),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in new issue
Block a user