feat(dashboard): add activities for order - claim, exchange, payment (#8702)
what: - add activities for order - claim, exchange, payment <img width="382" alt="Screenshot 2024-08-21 at 16 12 31" src="https://github.com/user-attachments/assets/56627d63-69b4-4b9c-b9db-c670fe49bfc9"> RESOLVES CC-344
This commit is contained in:
@@ -1039,7 +1039,8 @@
|
||||
"payment": {
|
||||
"awaiting": "Awaiting payment",
|
||||
"captured": "Payment captured",
|
||||
"canceled": "Payment canceled"
|
||||
"canceled": "Payment canceled",
|
||||
"refunded": "Payment refunded"
|
||||
},
|
||||
"fulfillment": {
|
||||
"created": "Items fulfilled",
|
||||
@@ -1057,6 +1058,16 @@
|
||||
"note": {
|
||||
"comment": "Comment",
|
||||
"byLine": "by {{author}}"
|
||||
},
|
||||
"claim": {
|
||||
"created": "Claim #{{claimId}} requested",
|
||||
"itemsInbound": "{{count}} item to return",
|
||||
"itemsOutbound": "{{count}} item to send"
|
||||
},
|
||||
"exchange": {
|
||||
"created": "Exchange #{{exchangeId}} requested",
|
||||
"itemsInbound": "{{count}} item to return",
|
||||
"itemsOutbound": "{{count}} item to send"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,21 @@ import { PropsWithChildren, ReactNode, useMemo, useState } from "react"
|
||||
import { Link } from "react-router-dom"
|
||||
|
||||
import { XMarkMini } from "@medusajs/icons"
|
||||
import { AdminFulfillment, AdminOrder, AdminReturn } from "@medusajs/types"
|
||||
import {
|
||||
AdminClaim,
|
||||
AdminExchange,
|
||||
AdminFulfillment,
|
||||
AdminOrder,
|
||||
AdminReturn,
|
||||
} from "@medusajs/types"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { useClaims } from "../../../../../hooks/api/claims"
|
||||
import { useExchanges } from "../../../../../hooks/api/exchanges"
|
||||
import { useReturns } from "../../../../../hooks/api/returns"
|
||||
import { useDate } from "../../../../../hooks/use-date"
|
||||
import { getStylizedAmount } from "../../../../../lib/money-amount-helpers"
|
||||
import { useReturns } from "../../../../../hooks/api/returns"
|
||||
import { getPaymentsFromOrder } from "../order-payment-section"
|
||||
|
||||
type OrderTimelineProps = {
|
||||
order: AdminOrder
|
||||
@@ -86,6 +95,18 @@ const useActivityItems = (order: AdminOrder) => {
|
||||
fields: "+received_at,*items",
|
||||
})
|
||||
|
||||
const { claims = [] } = useClaims({
|
||||
order_id: order.id,
|
||||
fields: "*additional_items",
|
||||
})
|
||||
|
||||
const { exchanges = [] } = useExchanges({
|
||||
order_id: order.id,
|
||||
fields: "*additional_items",
|
||||
})
|
||||
|
||||
const payments = getPaymentsFromOrder(order)
|
||||
|
||||
const notes = []
|
||||
const isLoading = false
|
||||
// const { notes, isLoading, isError, error } = useNotes(
|
||||
@@ -110,43 +131,60 @@ const useActivityItems = (order: AdminOrder) => {
|
||||
|
||||
const items: Activity[] = []
|
||||
|
||||
// for (const payment of order.payments) {
|
||||
// items.push({
|
||||
// title: t("orders.activity.events.payment.awaiting"),
|
||||
// timestamp: payment.created_at,
|
||||
// children: (
|
||||
// <Text size="small" className="text-ui-fg-subtle">
|
||||
// {getStylizedAmount(payment.amount, payment.currency_code)}
|
||||
// </Text>
|
||||
// ),
|
||||
// })
|
||||
//
|
||||
// if (payment.canceled_at) {
|
||||
// items.push({
|
||||
// title: t("orders.activity.events.payment.canceled"),
|
||||
// timestamp: payment.canceled_at,
|
||||
// children: (
|
||||
// <Text size="small" className="text-ui-fg-subtle">
|
||||
// {getStylizedAmount(payment.amount, payment.currency_code)}
|
||||
// </Text>
|
||||
// ),
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// if (payment.captured_at) {
|
||||
// items.push({
|
||||
// title: t("orders.activity.events.payment.captured"),
|
||||
// timestamp: payment.captured_at,
|
||||
// children: (
|
||||
// <Text size="small" className="text-ui-fg-subtle">
|
||||
// {getStylizedAmount(payment.amount, payment.currency_code)}
|
||||
// </Text>
|
||||
// ),
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
for (const payment of payments) {
|
||||
const amount = payment.amount as number
|
||||
|
||||
for (const fulfillment of order.fulfillments) {
|
||||
items.push({
|
||||
title: t("orders.activity.events.payment.awaiting"),
|
||||
timestamp: payment.created_at!,
|
||||
children: (
|
||||
<Text size="small" className="text-ui-fg-subtle">
|
||||
{getStylizedAmount(amount, payment.currency_code)}
|
||||
</Text>
|
||||
),
|
||||
})
|
||||
|
||||
if (payment.canceled_at) {
|
||||
items.push({
|
||||
title: t("orders.activity.events.payment.canceled"),
|
||||
timestamp: payment.canceled_at,
|
||||
children: (
|
||||
<Text size="small" className="text-ui-fg-subtle">
|
||||
{getStylizedAmount(amount, payment.currency_code)}
|
||||
</Text>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
if (payment.captured_at) {
|
||||
items.push({
|
||||
title: t("orders.activity.events.payment.captured"),
|
||||
timestamp: payment.captured_at,
|
||||
children: (
|
||||
<Text size="small" className="text-ui-fg-subtle">
|
||||
{getStylizedAmount(amount, payment.currency_code)}
|
||||
</Text>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
for (const refund of payment.refunds || []) {
|
||||
items.push({
|
||||
title: t("orders.activity.events.payment.refunded"),
|
||||
timestamp: refund.created_at,
|
||||
children: (
|
||||
<Text size="small" className="text-ui-fg-subtle">
|
||||
{getStylizedAmount(
|
||||
refund.amount as number,
|
||||
payment.currency_code
|
||||
)}
|
||||
</Text>
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for (const fulfillment of order.fulfillments || []) {
|
||||
items.push({
|
||||
title: t("orders.activity.events.fulfillment.created"),
|
||||
timestamp: fulfillment.created_at,
|
||||
@@ -171,7 +209,15 @@ const useActivityItems = (order: AdminOrder) => {
|
||||
}
|
||||
}
|
||||
|
||||
const returnMap = new Map<string, AdminReturn>()
|
||||
|
||||
for (const ret of returns) {
|
||||
returnMap.set(ret.id, ret)
|
||||
|
||||
if (ret.claim_id || ret.exchange_id) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Always display created action
|
||||
items.push({
|
||||
title: t("orders.activity.events.return.created", {
|
||||
@@ -192,6 +238,32 @@ const useActivityItems = (order: AdminOrder) => {
|
||||
}
|
||||
}
|
||||
|
||||
for (const claim of claims) {
|
||||
const claimReturn = returnMap.get(claim.return_id!)
|
||||
|
||||
items.push({
|
||||
title: t("orders.activity.events.claim.created", {
|
||||
claimId: claim.id.slice(-7),
|
||||
}),
|
||||
timestamp: claim.created_at,
|
||||
children: <ClaimBody claim={claim} claimReturn={claimReturn} />,
|
||||
})
|
||||
}
|
||||
|
||||
for (const exchange of exchanges) {
|
||||
const exchangeReturn = returnMap.get(exchange.return_id!)
|
||||
|
||||
items.push({
|
||||
title: t("orders.activity.events.exchange.created", {
|
||||
exchangeId: exchange.id.slice(-7),
|
||||
}),
|
||||
timestamp: exchange.created_at,
|
||||
children: (
|
||||
<ExchangeBody exchange={exchange} exchangeReturn={exchangeReturn} />
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
// for (const note of notes || []) {
|
||||
// items.push({
|
||||
// title: t("orders.activity.events.note.comment"),
|
||||
@@ -431,3 +503,83 @@ const ReturnBody = ({ orderReturn }: { orderReturn: AdminReturn }) => {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const ClaimBody = ({
|
||||
claim,
|
||||
claimReturn,
|
||||
}: {
|
||||
claim: AdminClaim
|
||||
claimReturn?: AdminReturn
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const outboundItems = (claim.additional_items || []).reduce(
|
||||
(acc, item) => (acc + item.quantity) as number,
|
||||
0
|
||||
)
|
||||
|
||||
const inboundItems = (claimReturn?.items || []).reduce(
|
||||
(acc, item) => acc + item.quantity,
|
||||
0
|
||||
)
|
||||
|
||||
return (
|
||||
<div>
|
||||
{outboundItems > 0 && (
|
||||
<Text size="small" className="text-ui-fg-subtle">
|
||||
{t("orders.activity.events.claim.itemsInbound", {
|
||||
count: outboundItems,
|
||||
})}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{inboundItems > 0 && (
|
||||
<Text size="small" className="text-ui-fg-subtle">
|
||||
{t("orders.activity.events.claim.itemsOutbound", {
|
||||
count: inboundItems,
|
||||
})}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const ExchangeBody = ({
|
||||
exchange,
|
||||
exchangeReturn,
|
||||
}: {
|
||||
exchange: AdminExchange
|
||||
exchangeReturn?: AdminReturn
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const outboundItems = (exchange.additional_items || []).reduce(
|
||||
(acc, item) => (acc + item.quantity) as number,
|
||||
0
|
||||
)
|
||||
|
||||
const inboundItems = (exchangeReturn?.items || []).reduce(
|
||||
(acc, item) => acc + item.quantity,
|
||||
0
|
||||
)
|
||||
|
||||
return (
|
||||
<div>
|
||||
{outboundItems > 0 && (
|
||||
<Text size="small" className="text-ui-fg-subtle">
|
||||
{t("orders.activity.events.exchange.itemsInbound", {
|
||||
count: outboundItems,
|
||||
})}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{inboundItems > 0 && (
|
||||
<Text size="small" className="text-ui-fg-subtle">
|
||||
{t("orders.activity.events.exchange.itemsOutbound", {
|
||||
count: inboundItems,
|
||||
})}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user