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:
5
.changeset/cozy-candles-work.md
Normal file
5
.changeset/cozy-candles-work.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@medusajs/dashboard": patch
|
||||
---
|
||||
|
||||
feat(dashboard): show promo tooltip on edit flows
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user