fix(dashboard): Prevent fulfillment provider modal from re-rendering before form submission is complete (#10547)

Resolves CMRC-782
This commit is contained in:
Kasper Fabricius Kristensen
2024-12-11 13:10:58 +00:00
committed by GitHub
parent 2ac6fd82d9
commit dc5e73af4d
4 changed files with 35 additions and 19 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/dashboard": patch
---
fix(dashboard): Prevent fulfillment provider modal from rerendering before form submission is complete
@@ -185,8 +185,8 @@ export const useUpdateStockLocationFulfillmentProviders = (
> >
) => { ) => {
return useMutation({ return useMutation({
mutationFn: (payload) => mutationFn: async (payload) =>
sdk.admin.stockLocation.updateFulfillmentProviders(id, payload), await sdk.admin.stockLocation.updateFulfillmentProviders(id, payload),
onSuccess: async (data, variables, context) => { onSuccess: async (data, variables, context) => {
await queryClient.invalidateQueries({ await queryClient.invalidateQueries({
queryKey: stockLocationsQueryKeys.details(), queryKey: stockLocationsQueryKeys.details(),
@@ -1,8 +1,12 @@
import { HttpTypes } from "@medusajs/types" import { HttpTypes } from "@medusajs/types"
import { Button, Checkbox, toast } from "@medusajs/ui" import { Button, Checkbox, toast } from "@medusajs/ui"
import { keepPreviousData } from "@tanstack/react-query" import { keepPreviousData } from "@tanstack/react-query"
import { RowSelectionState, createColumnHelper } from "@tanstack/react-table" import {
import { useEffect, useMemo, useState } from "react" RowSelectionState,
Updater,
createColumnHelper,
} from "@tanstack/react-table"
import { useMemo, useState } from "react"
import { useTranslation } from "react-i18next" import { useTranslation } from "react-i18next"
import * as zod from "zod" import * as zod from "zod"
@@ -13,6 +17,7 @@ import {
useRouteModal, useRouteModal,
} from "../../../../../components/modals" } from "../../../../../components/modals"
import { DataTable } from "../../../../../components/table/data-table" import { DataTable } from "../../../../../components/table/data-table"
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
import { useFulfillmentProviders } from "../../../../../hooks/api/fulfillment-providers" import { useFulfillmentProviders } from "../../../../../hooks/api/fulfillment-providers"
import { useUpdateStockLocationFulfillmentProviders } from "../../../../../hooks/api/stock-locations" import { useUpdateStockLocationFulfillmentProviders } from "../../../../../hooks/api/stock-locations"
import { useFulfillmentProviderTableColumns } from "../../../../../hooks/table/columns/use-fulfillment-provider-table-columns" import { useFulfillmentProviderTableColumns } from "../../../../../hooks/table/columns/use-fulfillment-provider-table-columns"
@@ -55,13 +60,16 @@ export const LocationEditFulfillmentProvidersForm = ({
const [rowSelection, setRowSelection] = const [rowSelection, setRowSelection] =
useState<RowSelectionState>(initialState) useState<RowSelectionState>(initialState)
useEffect(() => { const handleRowSelectionChange = (updater: Updater<RowSelectionState>) => {
const ids = Object.keys(rowSelection) const ids = typeof updater === "function" ? updater(rowSelection) : updater
setValue("fulfillment_providers", ids, {
setValue("fulfillment_providers", Object.keys(ids), {
shouldDirty: true, shouldDirty: true,
shouldTouch: true, shouldTouch: true,
}) })
}, [rowSelection, setValue])
setRowSelection(ids)
}
const { searchParams, raw } = useFulfillmentProvidersTableQuery({ const { searchParams, raw } = useFulfillmentProvidersTableQuery({
pageSize: PAGE_SIZE, pageSize: PAGE_SIZE,
@@ -84,7 +92,7 @@ export const LocationEditFulfillmentProvidersForm = ({
enableRowSelection: true, enableRowSelection: true,
rowSelection: { rowSelection: {
state: rowSelection, state: rowSelection,
updater: setRowSelection, updater: handleRowSelectionChange,
}, },
getRowId: (row) => row.id, getRowId: (row) => row.id,
pageSize: PAGE_SIZE, pageSize: PAGE_SIZE,
@@ -104,9 +112,9 @@ export const LocationEditFulfillmentProvidersForm = ({
remove: originalIds?.filter((i) => !arr.includes(i)), remove: originalIds?.filter((i) => !arr.includes(i)),
}, },
{ {
onSuccess: () => { onSuccess: ({ stock_location }) => {
toast.success(t("stockLocations.fulfillmentProviders.successToast")) toast.success(t("stockLocations.fulfillmentProviders.successToast"))
handleSuccess(`/settings/locations/${location.id}`) handleSuccess(`/settings/locations/${stock_location.id}`)
}, },
onError: (e) => { onError: (e) => {
toast.error(e.message) toast.error(e.message)
@@ -121,8 +129,9 @@ export const LocationEditFulfillmentProvidersForm = ({
return ( return (
<RouteFocusModal.Form form={form}> <RouteFocusModal.Form form={form}>
<div className="flex h-full flex-col overflow-hidden"> <KeyboundForm onSubmit={handleSubmit} className="flex size-full flex-col">
<RouteFocusModal.Body> <RouteFocusModal.Header />
<RouteFocusModal.Body className="flex flex-1 flex-col overflow-auto">
<DataTable <DataTable
table={table} table={table}
columns={columns} columns={columns}
@@ -141,17 +150,17 @@ export const LocationEditFulfillmentProvidersForm = ({
<RouteFocusModal.Footer> <RouteFocusModal.Footer>
<div className="flex items-center justify-end gap-x-2"> <div className="flex items-center justify-end gap-x-2">
<RouteFocusModal.Close asChild> <RouteFocusModal.Close asChild>
<Button size="small" variant="secondary"> <Button size="small" variant="secondary" type="button">
{t("actions.cancel")} {t("actions.cancel")}
</Button> </Button>
</RouteFocusModal.Close> </RouteFocusModal.Close>
<Button size="small" isLoading={isMutating} onClick={handleSubmit}> <Button size="small" isLoading={isMutating} type="submit">
{t("actions.save")} {t("actions.save")}
</Button> </Button>
</div> </div>
</RouteFocusModal.Footer> </RouteFocusModal.Footer>
</div> </KeyboundForm>
</RouteFocusModal.Form> </RouteFocusModal.Form>
) )
} }
@@ -6,10 +6,12 @@ import { LocationEditFulfillmentProvidersForm } from "./components/edit-fulfillm
export const LocationFulfillmentProviders = () => { export const LocationFulfillmentProviders = () => {
const { location_id } = useParams() const { location_id } = useParams()
const { stock_location, isPending, isFetching, isError, error } = const { stock_location, isPending, isError, error } = useStockLocation(
useStockLocation(location_id!, { fields: "id,*fulfillment_providers" }) location_id!,
{ fields: "id,*fulfillment_providers" }
)
const ready = !isPending && !isFetching && !!stock_location const ready = !isPending && !!stock_location
if (isError) { if (isError) {
throw error throw error