fix(dashboard): create refund form broken when no payment id defined (#13631)

* fix(dashboard): create refund form broken when no payment id defined

* Create funny-donuts-destroy.md
This commit is contained in:
William Bouchard
2025-09-30 13:17:43 -04:00
committed by GitHub
parent b9d6f73320
commit d30806533c
2 changed files with 97 additions and 13 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/dashboard": patch
---
fix(dashboard): create refund form broken when no payment id defined

View File

@@ -1,7 +1,14 @@
import { zodResolver } from "@hookform/resolvers/zod"
import { HttpTypes } from "@medusajs/types"
import { Button, CurrencyInput, Select, Textarea, toast } from "@medusajs/ui"
import { useMemo, useState } from "react"
import {
Button,
CurrencyInput,
Label,
Select,
Textarea,
toast,
} from "@medusajs/ui"
import { useEffect, useMemo, useState } from "react"
import { formatValue } from "react-currency-input-field"
import { useForm } from "react-hook-form"
import { useTranslation } from "react-i18next"
@@ -16,6 +23,7 @@ import { formatCurrency } from "../../../../../lib/format-currency"
import { getLocaleAmount } from "../../../../../lib/money-amount-helpers"
import { getPaymentsFromOrder } from "../../../../../lib/orders"
import { useDocumentDirection } from "../../../../../hooks/use-document-direction"
import { formatProvider } from "../../../../../lib/format-provider.ts"
type CreateRefundFormProps = {
order: HttpTypes.AdminOrder
@@ -36,11 +44,12 @@ export const CreateRefundForm = ({ order }: CreateRefundFormProps) => {
const { refund_reasons } = useRefundReasons()
const [searchParams] = useSearchParams()
const hasPaymentIdInSearchParams = !!searchParams.get("paymentId")
const [paymentId, setPaymentId] = useState<string | undefined>(
searchParams.get("paymentId") || undefined
)
const payments = getPaymentsFromOrder(order)
const payment = payments.find((p) => p.id === paymentId)!
const payment = payments.find((p) => p.id === paymentId)
const paymentAmount = payment?.amount || 0
const currency = useMemo(
@@ -59,6 +68,23 @@ export const CreateRefundForm = ({ order }: CreateRefundFormProps) => {
resolver: zodResolver(CreateRefundSchema),
})
useEffect(() => {
const pendingDifference = order.summary.pending_difference as number
const paymentAmount = (payment?.amount || 0) as number
const pendingAmount =
pendingDifference < 0
? Math.min(Math.abs(pendingDifference), paymentAmount)
: paymentAmount
const normalizedAmount =
pendingAmount < 0 ? pendingAmount * -1 : pendingAmount
form.setValue("amount", {
value: normalizedAmount.toFixed(currency.decimal_digits),
float: normalizedAmount,
})
}, [payment?.id || ""])
const { mutateAsync, isPending } = useRefundPayment(order.id, payment?.id!)
const handleSubmit = form.handleSubmit(async (data) => {
@@ -96,16 +122,69 @@ export const CreateRefundForm = ({ order }: CreateRefundFormProps) => {
>
<RouteDrawer.Body className="flex-1 overflow-auto">
<div className="flex flex-col gap-y-4">
<div className="flex items-center">
<span>
{getLocaleAmount(
payment.amount as number,
payment.currency_code
)}
</span>
<span> - </span>
<span>(#{payment.id.substring(23)})</span>
</div>
{!hasPaymentIdInSearchParams && (
<Select
dir={direction}
value={paymentId}
onValueChange={(value) => {
setPaymentId(value)
}}
>
<Label className="txt-compact-small mb-[-6px] font-sans font-medium">
{t("orders.payment.selectPaymentToRefund")}
</Label>
<Select.Trigger>
<Select.Value
placeholder={t("orders.payment.selectPaymentToRefund")}
/>
</Select.Trigger>
<Select.Content>
{payments.map((payment) => {
const totalRefunded =
payment.refunds?.reduce(
(acc, next) => next.amount + acc,
0
) || 0
return (
<Select.Item
value={payment!.id}
key={payment.id}
disabled={
!!payment.canceled_at ||
totalRefunded >= payment.amount
}
className="flex items-center justify-center"
>
<span>
{getLocaleAmount(
payment.amount as number,
payment.currency_code
)}
{" - "}
</span>
<span>{formatProvider(payment.provider_id)}</span>
<span> - (#{payment.id.substring(23)})</span>
</Select.Item>
)
})}
</Select.Content>
</Select>
)}
{hasPaymentIdInSearchParams && (
<div className="flex items-center">
<span>
{getLocaleAmount(
payment!.amount as number,
payment!.currency_code
)}
</span>
<span> - </span>
<span>(#{payment!.id.substring(23)})</span>
</div>
)}
<Form.Field
control={form.control}