feat(dashboard): show promo tooltip on the edit flows (#14121)

## Summary

**What** — What changes are introduced in this PR?

Display a tootlipt on line items when creating OrderEdit/Exchange to show which promotions are applied on the items.

---

## Checklist

Please ensure the following before requesting a review:

- [x] I have added a **changeset** for this PR
    - Every non-breaking change should be marked as a **patch**
    - To add a changeset, run `yarn changeset` and follow the prompts
- [ ] The changes are covered by relevant **tests**
- [x] I have verified the code works as intended locally
- [ ] I have linked the related issue(s) if applicable

<img width="786" height="910" alt="Screenshot 2025-11-25 at 14 11 22" src="https://github.com/user-attachments/assets/644bea00-b8ab-4a70-9a43-7c912ac21208" />

<img width="775" height="792" alt="Screenshot 2025-11-25 at 14 23 26" src="https://github.com/user-attachments/assets/ed935dad-9c2b-4ebd-8b9f-00d929add1ff" />
This commit is contained in:
Frane Polić
2025-11-25 20:37:45 +01:00
committed by GitHub
parent 1cfc88ee55
commit 1e761345be
4 changed files with 85 additions and 11 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/dashboard": patch
---
feat(dashboard): show promo tooltip on edit flows

View File

@@ -1,6 +1,11 @@
import { ArrowUturnLeft, DocumentSeries, XCircle } from "@medusajs/icons"
import {
ArrowUturnLeft,
DocumentSeries,
ReceiptPercent,
XCircle,
} from "@medusajs/icons"
import { AdminOrderLineItem } from "@medusajs/types"
import { Badge, Input, Text, toast } from "@medusajs/ui"
import { Badge, Input, Text, toast, Tooltip } from "@medusajs/ui"
import { useTranslation } from "react-i18next"
import { ActionMenu } from "../../../../../components/common/action-menu"
@@ -45,6 +50,10 @@ function OrderEditItem({ item, currencyCode, orderId }: OrderEditItemProps) {
return !!updateAction && item.quantity === item.detail.fulfilled_quantity
}, [item])
const appliedPromoCodes = useMemo(() => {
return (item.adjustments || []).map((adjustment) => adjustment.code)
}, [item])
/**
* HANDLERS
*/
@@ -166,7 +175,7 @@ function OrderEditItem({ item, currencyCode, orderId }: OrderEditItemProps) {
)}
</div>
<div className="flex flex-1 justify-between">
<div className="flex flex-1 items-center justify-between">
<div className="flex flex-grow items-center gap-2">
<Input
className="bg-ui-bg-base txt-small w-[67px] rounded-lg [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
@@ -186,6 +195,22 @@ function OrderEditItem({ item, currencyCode, orderId }: OrderEditItemProps) {
<Text className="txt-small text-ui-fg-subtle">
{t("fields.qty")}
</Text>
{appliedPromoCodes.length > 0 && (
<div className="flex flex-shrink pt-[2px]">
<Tooltip
content={
<span className="text-pretty">
{appliedPromoCodes.map((code) => (
<div key={code}>{code}</div>
))}
</span>
}
>
<ReceiptPercent className="text-ui-fg-subtle font-normal" />
</Tooltip>
</div>
)}
</div>
<div className="text-ui-fg-subtle txt-small mr-2 flex flex-shrink-0">

View File

@@ -1,6 +1,12 @@
import { ChatBubble, DocumentText, XCircle, XMark } from "@medusajs/icons"
import {
ChatBubble,
DocumentText,
ReceiptPercent,
XCircle,
XMark,
} from "@medusajs/icons"
import { AdminOrderLineItem, HttpTypes } from "@medusajs/types"
import { IconButton, Input, Text } from "@medusajs/ui"
import { IconButton, Input, Text, Tooltip } from "@medusajs/ui"
import { UseFormReturn } from "react-hook-form"
import { useTranslation } from "react-i18next"
@@ -39,13 +45,17 @@ function ExchangeInboundItem({
const showReturnReason = typeof formItem.reason_id === "string"
const showNote = typeof formItem.note === "string"
const appliedPromoCodes = (previewItem.adjustments || []).map(
(adjustment) => adjustment.code
)
return (
<div className="bg-ui-bg-subtle shadow-elevation-card-rest my-2 rounded-xl ">
<div className="flex flex-col items-center gap-x-2 gap-y-2 p-3 text-sm md:flex-row">
<div className="flex flex-col items-center gap-x-3 gap-y-2 p-3 text-sm md:flex-row">
<div className="flex flex-1 items-center gap-x-3">
<Thumbnail src={item.thumbnail} />
<div className="flex flex-col">
<div className="flex flex-grow flex-col">
<div>
<Text className="txt-small" as="span" weight="plus">
{item.title}{" "}
@@ -57,6 +67,21 @@ function ExchangeInboundItem({
{item.product_title}
</Text>
</div>
{appliedPromoCodes.length > 0 && (
<div className="flex flex-shrink">
<Tooltip
content={
<span className="text-pretty">
{appliedPromoCodes.map((code) => (
<div key={code}>{code}</div>
))}
</span>
}
>
<ReceiptPercent className="text-ui-fg-subtle" />
</Tooltip>
</div>
)}
</div>
<div className="flex flex-1 justify-between">

View File

@@ -1,6 +1,6 @@
import { XCircle } from "@medusajs/icons"
import { ReceiptPercent, XCircle } from "@medusajs/icons"
import { AdminOrderLineItem, HttpTypes } from "@medusajs/types"
import { Input, Text } from "@medusajs/ui"
import { Input, Text, Tooltip } from "@medusajs/ui"
import { UseFormReturn } from "react-hook-form"
import { useTranslation } from "react-i18next"
@@ -32,13 +32,17 @@ function ExchangeOutboundItem({
}: ExchangeOutboundItemProps) {
const { t } = useTranslation()
const appliedPromoCodes = (previewItem.adjustments || []).map(
(adjustment) => adjustment.code
)
return (
<div className="bg-ui-bg-subtle shadow-elevation-card-rest my-2 rounded-xl ">
<div className="flex flex-col items-center gap-x-2 gap-y-2 p-3 text-sm md:flex-row">
<div className="flex flex-col items-center gap-x-3 gap-y-2 p-3 text-sm md:flex-row">
<div className="flex flex-1 items-center gap-x-3">
<Thumbnail src={previewItem.thumbnail} />
<div className="flex flex-col">
<div className="flex flex-grow flex-col">
<div>
<Text className="txt-small" as="span" weight="plus">
{previewItem.title}{" "}
@@ -52,6 +56,21 @@ function ExchangeOutboundItem({
{previewItem.subtitle}
</Text>
</div>
{appliedPromoCodes.length > 0 && (
<div className="flex flex-shrink">
<Tooltip
content={
<span className="text-pretty">
{appliedPromoCodes.map((code) => (
<div key={code}>{code}</div>
))}
</span>
}
>
<ReceiptPercent className="text-ui-fg-subtle" />
</Tooltip>
</div>
)}
</div>
<div className="flex flex-1 justify-between">