fix(dashboard): Product create price columns race condition (#8943)
This commit is contained in:
committed by
GitHub
parent
479e712c17
commit
d88e6474e9
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user