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:
Riqwan Thamir
2024-08-21 16:38:18 +02:00
committed by GitHub
parent de7848f68d
commit a5707fd3bc
2 changed files with 202 additions and 39 deletions

View File

@@ -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"
}
}
}

View File

@@ -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>
)
}