fix(dashboard): Product create price columns race condition (#8943)

This commit is contained in:
Kasper Fabricius Kristensen
2024-09-02 18:56:05 +02:00
committed by GitHub
parent 479e712c17
commit d88e6474e9
3 changed files with 95 additions and 68 deletions

View File

@@ -1,5 +1,5 @@
import { zodResolver } from "@hookform/resolvers/zod"
import { HttpTypes, SalesChannelDTO } from "@medusajs/types"
import { HttpTypes } from "@medusajs/types"
import { Button, ProgressStatus, ProgressTabs, toast } from "@medusajs/ui"
import { useEffect, useMemo, useState } from "react"
import { useForm, useWatch } from "react-hook-form"
@@ -9,7 +9,6 @@ import {
useRouteModal,
} from "../../../../../components/modals"
import { useCreateProduct } from "../../../../../hooks/api/products"
import { useRegions } from "../../../../../hooks/api/regions"
import { sdk } from "../../../../../lib/client"
import { isFetchError } from "../../../../../lib/is-fetch-error"
import {
@@ -34,12 +33,18 @@ type TabState = Record<Tab, ProgressStatus>
const SAVE_DRAFT_BUTTON = "save-draft-button"
let LAST_VISITED_TAB: Tab | null = null
type ProductCreateFormProps = { defaultChannel?: SalesChannelDTO }
type ProductCreateFormProps = {
defaultChannel?: HttpTypes.AdminSalesChannel
regions: HttpTypes.AdminRegion[]
store: HttpTypes.AdminStore
pricePreferences: HttpTypes.AdminPricePreference[]
}
export const ProductCreateForm = ({
defaultChannel,
regions,
store,
pricePreferences,
}: ProductCreateFormProps) => {
const [tab, setTab] = useState<Tab>(Tab.DETAILS)
const [tabState, setTabState] = useState<TabState>({
@@ -63,17 +68,19 @@ export const ProductCreateForm = ({
})
const { mutateAsync, isPending } = useCreateProduct()
const { regions } = useRegions({ limit: 9999 })
const regionsCurrencyMap = useMemo(() => {
if (!regions?.length) {
return {}
}
return regions.reduce((acc, reg) => {
acc[reg.id] = reg.currency_code
return acc
}, {} as Record<string, string>)
return regions.reduce(
(acc, reg) => {
acc[reg.id] = reg.currency_code
return acc
},
{} as Record<string, string>
)
}, [regions])
/**
@@ -197,8 +204,6 @@ export const ProductCreateForm = ({
}
setTabState({ ...currentState })
LAST_VISITED_TAB = tab
}, [tab])
return (
@@ -284,7 +289,12 @@ export const ProductCreateForm = ({
className="size-full overflow-y-auto"
value={Tab.VARIANTS}
>
<ProductCreateVariantsForm form={form} />
<ProductCreateVariantsForm
form={form}
store={store}
regions={regions}
pricePreferences={pricePreferences}
/>
</ProgressTabs.Content>
{showInventoryTab && (
<ProgressTabs.Content

View File

@@ -9,9 +9,6 @@ import {
DataGrid,
} from "../../../../../components/data-grid"
import { useRouteModal } from "../../../../../components/modals"
import { usePricePreferences } from "../../../../../hooks/api/price-preferences"
import { useRegions } from "../../../../../hooks/api/regions"
import { useStore } from "../../../../../hooks/api/store"
import {
ProductCreateOptionSchema,
ProductCreateVariantSchema,
@@ -20,32 +17,17 @@ import { ProductCreateSchemaType } from "../../types"
type ProductCreateVariantsFormProps = {
form: UseFormReturn<ProductCreateSchemaType>
regions: HttpTypes.AdminRegion[]
store: HttpTypes.AdminStore
pricePreferences: HttpTypes.AdminPricePreference[]
}
export const ProductCreateVariantsForm = ({
form,
regions,
store,
pricePreferences,
}: ProductCreateVariantsFormProps) => {
const {
regions,
isPending: isRegionsPending,
isError: isRegionError,
error: regionError,
} = useRegions({ limit: 9999 })
const {
store,
isPending: isStorePending,
isError: isStoreError,
error: storeError,
} = useStore()
const {
price_preferences,
isPending: isPricePreferencesPending,
isError: isPricePreferencesError,
error: pricePreferencesError,
} = usePricePreferences({})
const { setCloseOnEscape } = useRouteModal()
const currencyCodes = useMemo(
@@ -72,7 +54,7 @@ export const ProductCreateVariantsForm = ({
options,
currencies: currencyCodes,
regions,
pricePreferences: price_preferences,
pricePreferences,
})
const variantData = useMemo(
@@ -80,30 +62,9 @@ export const ProductCreateVariantsForm = ({
[variants]
)
const isPending =
isRegionsPending ||
isStorePending ||
isPricePreferencesPending ||
!store ||
!regions ||
!price_preferences
if (isRegionError) {
throw regionError
}
if (isStoreError) {
throw storeError
}
if (isPricePreferencesError) {
throw pricePreferencesError
}
return (
<div className="flex size-full flex-col divide-y overflow-hidden">
<DataGrid
isLoading={isPending}
columns={columns}
data={variantData}
state={form}

View File

@@ -1,25 +1,81 @@
import { RouteFocusModal } from "../../../components/modals"
import { useRegions } from "../../../hooks/api"
import { usePricePreferences } from "../../../hooks/api/price-preferences"
import { useSalesChannel } from "../../../hooks/api/sales-channels"
import { useStore } from "../../../hooks/api/store"
import { ProductCreateForm } from "./components/product-create-form/product-create-form"
export const ProductCreate = () => {
const { store } = useStore({
const {
store,
isPending: isStorePending,
isError: isStoreError,
error: storeError,
} = useStore({
fields: "default_sales_channel",
})
const { sales_channel, isPending } = useSalesChannel(
store?.default_sales_channel_id,
{
enabled: !!store,
}
)
const {
sales_channel,
isPending: isSalesChannelPending,
isError: isSalesChannelError,
error: salesChannelError,
} = useSalesChannel(store?.default_sales_channel_id!, {
enabled: !!store?.default_sales_channel_id,
})
const canDisplayForm = store && !isPending
const {
regions,
isPending: isRegionsPending,
isError: isRegionsError,
error: regionsError,
} = useRegions({ limit: 9999 })
const {
price_preferences,
isPending: isPricePreferencesPending,
isError: isPricePreferencesError,
error: pricePreferencesError,
} = usePricePreferences({
limit: 9999,
})
const ready =
!!store &&
!isStorePending &&
!!regions &&
!isRegionsPending &&
!!sales_channel &&
!isSalesChannelPending &&
!!price_preferences &&
!isPricePreferencesPending
if (isStoreError) {
throw storeError
}
if (isRegionsError) {
throw regionsError
}
if (isSalesChannelError) {
throw salesChannelError
}
if (isPricePreferencesError) {
throw pricePreferencesError
}
return (
<RouteFocusModal>
{canDisplayForm && <ProductCreateForm defaultChannel={sales_channel} />}
{ready && (
<ProductCreateForm
defaultChannel={sales_channel}
store={store}
pricePreferences={price_preferences}
regions={regions}
/>
)}
</RouteFocusModal>
)
}