Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dashboard): Load product variant edit page and fix product detail query key #10029

Merged
merged 14 commits into from
Nov 12, 2024
Merged
5 changes: 5 additions & 0 deletions .changeset/modern-walls-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@medusajs/dashboard": patch
---

fix(dashboard): Fix query key for product details and load product variant data correctly
11 changes: 8 additions & 3 deletions packages/admin/dashboard/src/hooks/api/products.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,14 @@ export const useDeleteProductOption = (
export const useProductVariant = (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add the same fix here you did for for product (include the query in query key).
If you open edit variant from product and then go to variant page it will break since pulling the variant from the same cache key.

productId: string,
variantId: string,
query?: Record<string, any>,
query?: HttpTypes.AdminProductVariantParams,
options?: Omit<
UseQueryOptions<any, FetchError, any, QueryKey>,
UseQueryOptions<
HttpTypes.AdminProductVariantResponse,
FetchError,
HttpTypes.AdminProductVariantResponse,
QueryKey
>,
"queryFn" | "queryKey"
>
) => {
Expand Down Expand Up @@ -238,7 +243,7 @@ export const useProduct = (
) => {
const { data, ...rest } = useQuery({
queryFn: () => sdk.admin.product.retrieve(id, query),
queryKey: productsQueryKeys.detail(id),
queryKey: productsQueryKeys.detail(id, query),
...options,
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ const ProductEditVariantSchema = z.object({

// TODO: Either pass option ID or make the backend handle options constraints differently to handle the lack of IDs
export const ProductEditVariantForm = ({
product,
variant,
product,
}: ProductEditVariantFormProps) => {
const { t } = useTranslation()
const { handleSuccess } = useRouteModal()
Expand All @@ -63,7 +63,6 @@ export const ProductEditVariantForm = ({
ean: variant.ean || "",
upc: variant.upc || "",
barcode: variant.barcode || "",
inventory_quantity: variant.inventory_quantity || "",
manage_inventory: variant.manage_inventory || false,
allow_backorder: variant.allow_backorder || false,
weight: variant.weight || "",
Expand All @@ -79,7 +78,7 @@ export const ProductEditVariantForm = ({
})

const { mutateAsync, isPending } = useUpdateProductVariant(
product.id,
variant.product_id!,
variant.id
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
import { LoaderFunctionArgs } from "react-router-dom"

import { productsQueryKeys } from "../../../hooks/api/products"
import { productVariantQueryKeys } from "../../../hooks/api"
import { sdk } from "../../../lib/client"
import { queryClient } from "../../../lib/query-client"

const queryKey = (id: string) => {
return [productsQueryKeys.detail(id)]
const queryFn = async (id: string, variantId: string) => {
return await sdk.admin.product.retrieveVariant(id, variantId)
}

const queryFn = async (id: string) => {
return await sdk.admin.product.retrieve(id)
}

const editProductVariantQuery = (id: string) => ({
queryKey: queryKey(id),
queryFn: async () => queryFn(id),
const editProductVariantQuery = (id: string, variantId: string) => ({
queryKey: productVariantQueryKeys.detail(variantId),
queryFn: async () => queryFn(id, variantId),
})

export const editProductVariantLoader = async ({
params,
request,
}: LoaderFunctionArgs) => {
const id = params.id
const query = editProductVariantQuery(id!)

const searchParams = new URL(request.url).searchParams
const searchVariantId = searchParams.get("variant_id")

const variantId = params.variant_id || searchVariantId

const query = editProductVariantQuery(id!, variantId || searchVariantId!)

return (
queryClient.getQueryData<ReturnType<typeof queryFn>>(query.queryKey) ??
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import { HttpTypes } from "@medusajs/types"
import { Heading } from "@medusajs/ui"
import { useTranslation } from "react-i18next"
import {
json,
useLoaderData,
useParams,
useSearchParams,
} from "react-router-dom"
import { useLoaderData, useParams, useSearchParams } from "react-router-dom"
import { RouteDrawer } from "../../../components/modals"
import { useProduct } from "../../../hooks/api/products"
import { useProduct, useProductVariant } from "../../../hooks/api/products"
import { ProductEditVariantForm } from "./components/product-edit-variant-form"
import { editProductVariantLoader } from "./loader"

Expand All @@ -22,41 +16,55 @@ export const ProductVariantEdit = () => {
const [URLSearchParms] = useSearchParams()
const searchVariantId = URLSearchParms.get("variant_id")

const { product, isPending, isFetching, isError, error } = useProduct(
const { variant, isPending, isError, error } = useProductVariant(
id!,
variant_id || searchVariantId!,
undefined,
{
initialData,
}
)

const variant = product?.variants.find(
(v: HttpTypes.AdminProductVariant) =>
v.id === (variant_id || searchVariantId)
const {
product,
isPending: isProductPending,
isError: isProductError,
error: productError,
} = useProduct(
variant?.product_id!,
{
fields: "-variants",
},
{
enabled: !!variant?.product_id,
}
)

if (!isPending && !isFetching && !variant) {
throw json({
status: 404,
message: `Variant with ID ${variant_id || searchVariantId} was not found.`,
})
}
const ready = !isPending && !!variant && !isProductPending && !!product

console.log(
variant_id,
searchVariantId,
variant,
variant?.product_id,
isPending,
isProductPending
)

if (isError) {
throw error
}

if (isProductError) {
throw productError
}

return (
<RouteDrawer>
<RouteDrawer.Header>
<Heading>{t("products.variant.edit.header")}</Heading>
</RouteDrawer.Header>
{variant && (
<ProductEditVariantForm
product={product}
variant={variant as unknown as HttpTypes.AdminProductVariant}
/>
)}
{ready && <ProductEditVariantForm variant={variant} product={product} />}
</RouteDrawer>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ export const PricingEdit = ({
}, [regions])

const variants = variantId
? product.variants.filter((v) => v.id === variantId)
? product.variants?.filter((v) => v.id === variantId)
: product.variants

const form = useForm<UpdateVariantPricesSchemaType>({
defaultValues: {
variants: variants.map((variant: any) => ({
variants: variants?.map((variant: any) => ({
title: variant.title,
prices: variant.prices.reduce((acc: any, price: any) => {
if (price.rules?.region_id) {
Expand Down Expand Up @@ -90,11 +90,11 @@ export const PricingEdit = ({
let existingId = undefined

if (regionId) {
existingId = variants[ind].prices.find(
existingId = variants?.[ind]?.prices?.find(
(p) => p.rules["region_id"] === regionId
)?.id
} else {
existingId = variants[ind].prices.find(
existingId = variants?.[ind]?.prices?.find(
(p) =>
p.currency_code === currencyCode &&
Object.keys(p.rules ?? {}).length === 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { PricingEdit } from "./pricing-edit"
export const ProductPrices = () => {
const { id, variant_id } = useParams()

const { product, isLoading, isError, error } = useProduct(id!)
const { product, isLoading, isError, error } = useProduct(id!, {
fields: "+variants,+variants.prices",
})

if (isError) {
throw error
Expand Down
Loading