fix(dashboard): handle large resource count in tax rule override edit form (#13297)

* fix(dashboard): handle larege resource count in tax rule override edit form

* fix: typo

* fix: rm log
This commit is contained in:
Frane Polić
2025-08-26 10:45:27 +02:00
committed by GitHub
parent ff98055592
commit 87a61baf8f
4 changed files with 99 additions and 27 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/dashboard": patch
---
fix(dashboard): handle large resource count in tax rule override edit form
@@ -1,17 +1,30 @@
import { XMarkMini } from "@medusajs/icons" import { XMarkMini } from "@medusajs/icons"
import { IconButton, Text } from "@medusajs/ui" import { IconButton, Text } from "@medusajs/ui"
import { useProduct } from "../../../../../hooks/api"
type TargetItemProps = { type TargetItemProps = {
index: number index: number
onRemove: (index: number) => void onRemove: (index: number) => void
label: string label: string
value: string
} }
export const TargetItem = ({ index, label, onRemove }: TargetItemProps) => { export const TargetItem = ({
index,
label,
onRemove,
value,
}: TargetItemProps) => {
const { product } = useProduct(
value,
{ fields: "id,title" },
{ enabled: !label }
)
return ( return (
<div className="bg-ui-bg-field-component shadow-borders-base flex items-center justify-between gap-2 rounded-md px-2 py-0.5"> <div className="bg-ui-bg-field-component shadow-borders-base flex items-center justify-between gap-2 rounded-md px-2 py-0.5">
<Text size="small" leading="compact"> <Text size="small" leading="compact">
{label} {label || product?.title}
</Text> </Text>
<IconButton <IconButton
size="small" size="small"
@@ -38,6 +38,8 @@ import {
import { createTaxRulePayload } from "../../../common/utils" import { createTaxRulePayload } from "../../../common/utils"
import { InitialRuleValues } from "../../types" import { InitialRuleValues } from "../../types"
export const DISPLAY_OVERRIDE_ITEMS_LIMIT = 10
type TaxRegionTaxOverrideEditFormProps = { type TaxRegionTaxOverrideEditFormProps = {
taxRate: HttpTypes.AdminTaxRate taxRate: HttpTypes.AdminTaxRate
initialValues: InitialRuleValues initialValues: InitialRuleValues
@@ -272,7 +274,7 @@ export const TaxRegionTaxOverrideEditForm = ({
} }
const getFieldHandler = (type: TaxRateRuleReferenceType) => { const getFieldHandler = (type: TaxRateRuleReferenceType) => {
const { fields, remove, append } = getControls(type) const { fields, remove, prepend } = getControls(type)
const modalId = getStackedModalId(type) const modalId = getStackedModalId(type)
return (references: TaxRateRuleReference[]) => { return (references: TaxRateRuleReference[]) => {
@@ -296,7 +298,7 @@ export const TaxRegionTaxOverrideEditForm = ({
} }
} }
append(fieldsToAdd) prepend(fieldsToAdd) // to display newer items first
setIsOpen(modalId, false) setIsOpen(modalId, false)
} }
} }
@@ -588,17 +590,33 @@ export const TaxRegionTaxOverrideEditForm = ({
<div className="flex flex-col gap-y-1.5"> <div className="flex flex-col gap-y-1.5">
<Divider variant="dashed" /> <Divider variant="dashed" />
<div className="flex flex-col gap-y-1.5 px-1.5"> <div className="flex flex-col gap-y-1.5 px-1.5">
{fields.map((field, index) => { {fields
return ( .slice(0, DISPLAY_OVERRIDE_ITEMS_LIMIT)
<TargetItem .map((field, index) => {
key={field.id} return (
index={index} <TargetItem
label={field.label} key={field.id}
onRemove={remove} index={index}
/> label={field.label}
) value={field.value}
})} onRemove={remove}
/>
)
})}
</div> </div>
{fields.length >
DISPLAY_OVERRIDE_ITEMS_LIMIT && (
<div className="flex flex-col gap-y-1.5 px-1.5">
{/* <Divider variant="dashed" /> */}
<div className="text-ui-fg-muted txt-small flex flex-col gap-y-1.5 px-1.5">
{t("general.plusCountMore", {
count:
fields.length -
DISPLAY_OVERRIDE_ITEMS_LIMIT,
})}
</div>
</div>
)}
</div> </div>
) : null} ) : null}
</div> </div>
@@ -7,9 +7,13 @@ import { RouteDrawer } from "../../../components/modals"
import { useProductTypes } from "../../../hooks/api/product-types" import { useProductTypes } from "../../../hooks/api/product-types"
import { useProducts } from "../../../hooks/api/products" import { useProducts } from "../../../hooks/api/products"
import { TaxRateRuleReferenceType } from "../common/constants" import { TaxRateRuleReferenceType } from "../common/constants"
import { TaxRegionTaxOverrideEditForm } from "./components/tax-region-tax-override-edit-form" import {
DISPLAY_OVERRIDE_ITEMS_LIMIT,
TaxRegionTaxOverrideEditForm,
} from "./components/tax-region-tax-override-edit-form"
import { InitialRuleValues } from "./types" import { InitialRuleValues } from "./types"
import { useShippingOptions, useTaxRate } from "../../../hooks/api" import { useShippingOptions, useTaxRate } from "../../../hooks/api"
import { TaxRateRuleReference } from "../common/schemas"
export const TaxRegionTaxOverrideEdit = () => { export const TaxRegionTaxOverrideEdit = () => {
const { t } = useTranslation() const { t } = useTranslation()
@@ -49,7 +53,7 @@ export const TaxRegionTaxOverrideEdit = () => {
const useDefaultRulesValues = ( const useDefaultRulesValues = (
taxRate?: HttpTypes.AdminTaxRate taxRate?: HttpTypes.AdminTaxRate
): { initialValues?: InitialRuleValues; isPending: boolean } => { ): { initialValues: InitialRuleValues; isPending: boolean } => {
const rules = taxRate?.rules || [] const rules = taxRate?.rules || []
const idsByReferenceType: { const idsByReferenceType: {
@@ -63,10 +67,12 @@ const useDefaultRulesValues = (
// [TaxRateRuleReferenceType.CUSTOMER_GROUP]: [], // [TaxRateRuleReferenceType.CUSTOMER_GROUP]: [],
} }
rules.forEach((rule) => { rules
const reference = rule.reference as TaxRateRuleReferenceType .sort((a, b) => a.created_at.localeCompare(b.created_at)) // preffer newer rules for display
idsByReferenceType[reference]?.push(rule.reference_id) .forEach((rule) => {
}) const reference = rule.reference as TaxRateRuleReferenceType
idsByReferenceType[reference]?.push(rule.reference_id)
})
const queries = [ const queries = [
{ {
@@ -137,8 +143,21 @@ const useDefaultRulesValues = (
const queryResults = queries.map(({ ids, hook }) => { const queryResults = queries.map(({ ids, hook }) => {
const enabled = ids.length > 0 const enabled = ids.length > 0
return { return {
result: hook({ id: ids, limit: ids.length }, { enabled }), result: hook(
{
/**
* Limit fetch to 10 resources for display
*/
id:
ids.length > DISPLAY_OVERRIDE_ITEMS_LIMIT
? ids.slice(0, DISPLAY_OVERRIDE_ITEMS_LIMIT)
: ids,
limit: DISPLAY_OVERRIDE_ITEMS_LIMIT,
},
{ enabled }
),
enabled, enabled,
} }
}) })
@@ -162,12 +181,29 @@ const useDefaultRulesValues = (
}) })
const initialRulesValues: InitialRuleValues = queries.reduce( const initialRulesValues: InitialRuleValues = queries.reduce(
(acc, { key, getResult }, index) => ({ (acc, { key, getResult }, index) => {
...acc, let initialValues: TaxRateRuleReference[] = []
[key]: queryResults[index].enabled
? getResult(queryResults[index].result) if (queryResults[index].enabled) {
: [], const fetchedEntityList = getResult(queryResults[index].result)
}),
const entityIdMap = new Map(
fetchedEntityList.map((entity) => [entity.value, entity])
)
const initialIds = idsByReferenceType[key]
initialValues = initialIds.map((id) => ({
value: id,
label: entityIdMap.get(id)?.label || "",
}))
}
return {
...acc,
[key]: initialValues,
}
},
{} as InitialRuleValues {} as InitialRuleValues
) )