feat(dashboard): summary shipping breakdown (#8779)
**What** - display a shipping costs breakdown in the order summary - allow to receive only non canceled returns - show how many items is actually received with return in the timeline **Question** - should we display the shipping total somewhere as well --- CLOSES CC-356
This commit is contained in:
+4
-2
@@ -242,7 +242,7 @@ const useActivityItems = (order: AdminOrder) => {
|
|||||||
returnId: ret.id.slice(-7),
|
returnId: ret.id.slice(-7),
|
||||||
}),
|
}),
|
||||||
timestamp: ret.received_at,
|
timestamp: ret.received_at,
|
||||||
children: <ReturnBody orderReturn={ret} />,
|
children: <ReturnBody orderReturn={ret} isReceived />,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,9 +498,11 @@ const FulfillmentCreatedBody = ({
|
|||||||
const ReturnBody = ({
|
const ReturnBody = ({
|
||||||
orderReturn,
|
orderReturn,
|
||||||
isCreated,
|
isCreated,
|
||||||
|
isReceived,
|
||||||
}: {
|
}: {
|
||||||
orderReturn: AdminReturn
|
orderReturn: AdminReturn
|
||||||
isCreated: boolean
|
isCreated: boolean
|
||||||
|
isReceived?: boolean
|
||||||
}) => {
|
}) => {
|
||||||
const prompt = usePrompt()
|
const prompt = usePrompt()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@@ -526,7 +528,7 @@ const ReturnBody = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const numberOfItems = orderReturn.items.reduce((acc, item) => {
|
const numberOfItems = orderReturn.items.reduce((acc, item) => {
|
||||||
return acc + item.quantity
|
return acc + (isReceived ? item.received_quantity : item.quantity) // TODO: revisit when we add dismissed quantity on ReturnItem
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
+27
-16
@@ -35,23 +35,23 @@ import {
|
|||||||
|
|
||||||
import { AdminPaymentCollection } from "../../../../../../../../core/types/dist/http/payment/admin/entities"
|
import { AdminPaymentCollection } from "../../../../../../../../core/types/dist/http/payment/admin/entities"
|
||||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||||
import { ButtonMenu } from "../../../../../components/common/button-menu/button-menu.tsx"
|
import { ButtonMenu } from "../../../../../components/common/button-menu/button-menu"
|
||||||
import { Thumbnail } from "../../../../../components/common/thumbnail"
|
import { Thumbnail } from "../../../../../components/common/thumbnail"
|
||||||
import { useClaims } from "../../../../../hooks/api/claims.tsx"
|
import { useClaims } from "../../../../../hooks/api/claims"
|
||||||
import { useExchanges } from "../../../../../hooks/api/exchanges.tsx"
|
import { useExchanges } from "../../../../../hooks/api/exchanges"
|
||||||
import { useOrderPreview } from "../../../../../hooks/api/orders.tsx"
|
import { useOrderPreview } from "../../../../../hooks/api/orders"
|
||||||
import { useMarkPaymentCollectionAsPaid } from "../../../../../hooks/api/payment-collections.tsx"
|
import { useMarkPaymentCollectionAsPaid } from "../../../../../hooks/api/payment-collections"
|
||||||
import { useReservationItems } from "../../../../../hooks/api/reservations"
|
import { useReservationItems } from "../../../../../hooks/api/reservations"
|
||||||
import { useReturns } from "../../../../../hooks/api/returns"
|
import { useReturns } from "../../../../../hooks/api/returns"
|
||||||
import { useDate } from "../../../../../hooks/use-date"
|
import { useDate } from "../../../../../hooks/use-date"
|
||||||
import { formatCurrency } from "../../../../../lib/format-currency.ts"
|
import { formatCurrency } from "../../../../../lib/format-currency"
|
||||||
import {
|
import {
|
||||||
getLocaleAmount,
|
getLocaleAmount,
|
||||||
getStylizedAmount,
|
getStylizedAmount,
|
||||||
} from "../../../../../lib/money-amount-helpers"
|
} from "../../../../../lib/money-amount-helpers"
|
||||||
import { getTotalCaptured } from "../../../../../lib/payment.ts"
|
import { getTotalCaptured } from "../../../../../lib/payment"
|
||||||
import { getReturnableQuantity } from "../../../../../lib/rma.ts"
|
import { getReturnableQuantity } from "../../../../../lib/rma"
|
||||||
import { CopyPaymentLink } from "../copy-payment-link/copy-payment-link.tsx"
|
import { CopyPaymentLink } from "../copy-payment-link/copy-payment-link"
|
||||||
|
|
||||||
type OrderSummarySectionProps = {
|
type OrderSummarySectionProps = {
|
||||||
order: AdminOrder
|
order: AdminOrder
|
||||||
@@ -77,7 +77,12 @@ export const OrderSummarySection = ({ order }: OrderSummarySectionProps) => {
|
|||||||
fields: "+received_at",
|
fields: "+received_at",
|
||||||
})
|
})
|
||||||
|
|
||||||
const showReturns = !!returns.length
|
const receivableReturns = useMemo(
|
||||||
|
() => returns.filter((r) => !r.canceled_at),
|
||||||
|
[returns]
|
||||||
|
)
|
||||||
|
|
||||||
|
const showReturns = !!receivableReturns.length
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show Allocation button only if there are unfulfilled items that don't have reservations
|
* Show Allocation button only if there are unfulfilled items that don't have reservations
|
||||||
@@ -170,11 +175,11 @@ export const OrderSummarySection = ({ order }: OrderSummarySectionProps) => {
|
|||||||
{(showAllocateButton || showReturns || showPayment || showRefund) && (
|
{(showAllocateButton || showReturns || showPayment || showRefund) && (
|
||||||
<div className="bg-ui-bg-subtle flex items-center justify-end gap-x-2 rounded-b-xl px-4 py-4">
|
<div className="bg-ui-bg-subtle flex items-center justify-end gap-x-2 rounded-b-xl px-4 py-4">
|
||||||
{showReturns &&
|
{showReturns &&
|
||||||
(returns.length === 1 ? (
|
(receivableReturns.length === 1 ? (
|
||||||
<Button
|
<Button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
navigate(
|
navigate(
|
||||||
`/orders/${order.id}/returns/${returns[0].id}/receive`
|
`/orders/${order.id}/returns/${receivableReturns[0].id}/receive`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
@@ -186,7 +191,7 @@ export const OrderSummarySection = ({ order }: OrderSummarySectionProps) => {
|
|||||||
<ButtonMenu
|
<ButtonMenu
|
||||||
groups={[
|
groups={[
|
||||||
{
|
{
|
||||||
actions: returns.map((r) => ({
|
actions: receivableReturns.map((r) => ({
|
||||||
label: t("orders.returns.receive.receive", {
|
label: t("orders.returns.receive.receive", {
|
||||||
label: `#${r.id.slice(-7)}`,
|
label: `#${r.id.slice(-7)}`,
|
||||||
}),
|
}),
|
||||||
@@ -529,11 +534,17 @@ const CostBreakdown = ({ order }: { order: AdminOrder }) => {
|
|||||||
: "-"
|
: "-"
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
{(order.shipping_methods || [])
|
||||||
|
.sort((m1, m2) =>
|
||||||
|
(m1.created_at as string).localeCompare(m2.created_at as string)
|
||||||
|
)
|
||||||
|
.map((sm, i) => (
|
||||||
<Cost
|
<Cost
|
||||||
label={t("fields.shipping")}
|
label={t("fields.shipping") + (i ? ` ${i + 1}` : "")}
|
||||||
secondaryValue={order.shipping_methods.map((sm) => sm.name).join(", ")}
|
secondaryValue={sm.name}
|
||||||
value={getLocaleAmount(order.shipping_total, order.currency_code)}
|
value={getLocaleAmount(sm.total, order.currency_code)}
|
||||||
/>
|
/>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user