feat(dashboard): Rework route modals (#6459)
**What** - Reworks how RouteModals are setup. **Why** - With the current implementation it was possible to create a race-condition in the logic that handled displaying a prompt if the user tried to close a modal, while a child form was dirty. The race condition would cause a new prompt to spawn each time the user clicked the screen, making it impossible to dismiss the prompt. This only occurred in a few specific cases. **How** - Creates two new components: RouteFocusModal and RouteDrawer. The component shares logic for handling their own open/closed state, and now accept a form prop, that allows the modals to keep track of whether their child form is dirty. This change ensures that race conditions cannot occur, and that the prompt always only renders once when needed.
This commit is contained in:
committed by
GitHub
parent
add861d205
commit
72a17d6cd7
@@ -0,0 +1,56 @@
|
||||
import { Country } from "@medusajs/medusa"
|
||||
import { Tooltip } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { PlaceholderCell } from "../../common/placeholder-cell"
|
||||
|
||||
type CountriesCellProps = {
|
||||
countries?: Country[] | null
|
||||
}
|
||||
|
||||
export const CountriesCell = ({ countries }: CountriesCellProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
if (!countries || countries.length === 0) {
|
||||
return <PlaceholderCell />
|
||||
}
|
||||
|
||||
const displayValue = countries
|
||||
.slice(0, 2)
|
||||
.map((c) => c.display_name)
|
||||
.join(", ")
|
||||
|
||||
const additionalCountries = countries.slice(2).map((c) => c.display_name)
|
||||
|
||||
return (
|
||||
<div className="flex size-full items-center gap-x-1">
|
||||
<span>{displayValue}</span>
|
||||
{additionalCountries.length > 0 && (
|
||||
<Tooltip
|
||||
content={
|
||||
<ul>
|
||||
{additionalCountries.map((c) => (
|
||||
<li key={c}>{c}</li>
|
||||
))}
|
||||
</ul>
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{t("general.plusCountMore", {
|
||||
count: additionalCountries.length,
|
||||
})}
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const CountriesHeader = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex size-full items-center">
|
||||
<span>{t("fields.countries")}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./countries-cell"
|
||||
@@ -0,0 +1,58 @@
|
||||
import { FulfillmentProvider } from "@medusajs/medusa"
|
||||
import { Tooltip } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { PlaceholderCell } from "../../common/placeholder-cell"
|
||||
|
||||
type FulfillmentProvidersCellProps = {
|
||||
fulfillmentProviders?: FulfillmentProvider[] | null
|
||||
}
|
||||
|
||||
export const FulfillmentProvidersCell = ({
|
||||
fulfillmentProviders,
|
||||
}: FulfillmentProvidersCellProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
if (!fulfillmentProviders || fulfillmentProviders.length === 0) {
|
||||
return <PlaceholderCell />
|
||||
}
|
||||
|
||||
const displayValue = fulfillmentProviders
|
||||
.slice(0, 2)
|
||||
.map((p) => p.id)
|
||||
.join(", ")
|
||||
|
||||
const additionalProviders = fulfillmentProviders.slice(2).map((c) => c.id)
|
||||
|
||||
return (
|
||||
<div className="flex size-full items-center gap-x-1">
|
||||
<span>{displayValue}</span>
|
||||
{additionalProviders.length > 0 && (
|
||||
<Tooltip
|
||||
content={
|
||||
<ul>
|
||||
{additionalProviders.map((c) => (
|
||||
<li key={c}>{c}</li>
|
||||
))}
|
||||
</ul>
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{t("general.plusCountMore", {
|
||||
count: additionalProviders.length,
|
||||
})}
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const FulfillmentProvidersHeader = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex size-full items-center">
|
||||
<span>{t("fields.fulfillmentProviders")}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./fulfillment-providers-cell"
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./payment-providers-cell"
|
||||
@@ -0,0 +1,58 @@
|
||||
import { PaymentProvider } from "@medusajs/medusa"
|
||||
import { Tooltip } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { PlaceholderCell } from "../../common/placeholder-cell"
|
||||
|
||||
type PaymentProvidersCellProps = {
|
||||
paymentProviders?: PaymentProvider[] | null
|
||||
}
|
||||
|
||||
export const PaymentProvidersCell = ({
|
||||
paymentProviders,
|
||||
}: PaymentProvidersCellProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
if (!paymentProviders || paymentProviders.length === 0) {
|
||||
return <PlaceholderCell />
|
||||
}
|
||||
|
||||
const displayValue = paymentProviders
|
||||
.slice(0, 2)
|
||||
.map((p) => p.id)
|
||||
.join(", ")
|
||||
|
||||
const additionalProviders = paymentProviders.slice(2).map((c) => c.id)
|
||||
|
||||
return (
|
||||
<div className="flex size-full items-center gap-x-1">
|
||||
<span>{displayValue}</span>
|
||||
{additionalProviders.length > 0 && (
|
||||
<Tooltip
|
||||
content={
|
||||
<ul>
|
||||
{additionalProviders.map((c) => (
|
||||
<li key={c}>{c}</li>
|
||||
))}
|
||||
</ul>
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{t("general.plusCountMore", {
|
||||
count: additionalProviders.length,
|
||||
})}
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const PaymentProvidersHeader = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex size-full items-center">
|
||||
<span>{t("fields.paymentProviders")}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./region-cell"
|
||||
@@ -0,0 +1,23 @@
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
type RegionCellProps = {
|
||||
name: string
|
||||
}
|
||||
|
||||
export const RegionCell = ({ name }: RegionCellProps) => {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center overflow-hidden">
|
||||
<span className="truncate">{name}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const RegionHeader = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full items-center">
|
||||
<span className="truncate">{t("fields.name")}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user