feat(dashboard): Region refactor (#7083)

* wip: regions refactor

* feat:  finalize region domain

* fix: cleanup error messages
This commit is contained in:
Frane Polić authored and GitHub committed 2024-04-22 08:35:52 +02:00
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) {
@@ -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,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",
}) })
@@ -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()]
@@ -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 (
@@ -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" },
{ {
@@ -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()
@@ -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 (