saleor-dashboard/src/orders/components/OrderHistory/ExtendedTimelineEvent.tsx

278 lines
7.2 KiB
TypeScript

import Money from "@dashboard/components/Money";
import { TimelineEvent } from "@dashboard/components/Timeline";
import { OrderEventFragment, OrderEventsEnum } from "@dashboard/graphql";
import { Typography } from "@material-ui/core";
import { makeStyles } from "@saleor/macaw-ui";
import camelCase from "lodash/camelCase";
import React from "react";
import { defineMessages, useIntl } from "react-intl";
import ExtendedDiscountTimelineEvent from "./ExtendedDiscountTimelineEvent";
import Label from "./Label";
import {
getEmployeeNameLink,
getOrderNumberLink,
hasOrderLineDiscountWithNoPreviousValue,
isTimelineEventOfDiscountType,
} from "./utils";
const useStyles = makeStyles(
theme => ({
eventSubtitle: {
marginBottom: theme.spacing(0.5),
marginTop: theme.spacing(1),
},
header: {
fontWeight: 500,
marginBottom: theme.spacing(1),
},
linesTableCell: {
paddingRight: theme.spacing(3),
},
root: { marginTop: theme.spacing(4) },
topSpacer: {
marginTop: theme.spacing(3),
},
user: {
marginBottom: theme.spacing(1),
},
}),
{ name: "OrderHistory" },
);
export const productTitles = defineMessages({
draftCreatedFromReplace: {
id: "a1uffz",
defaultMessage: "Products replaced",
description: "draft created from replace products list title",
},
fulfillmentRefunded: {
id: "sHON47",
defaultMessage: "Products refunded",
description: "refunded products list title",
},
fulfillmentReplaced: {
id: "nki0o/",
defaultMessage: "Products replaced",
description: "replaced products list title",
},
fulfillmentReturned: {
id: "L5io1l",
defaultMessage: "Products returned",
description: "returned products list title",
},
});
export const titles = defineMessages({
draftCreatedFromReplace: {
id: "5R4VMl",
defaultMessage: "Draft was reissued from order ",
description: "draft created from replace event title",
},
fulfillmentRefunded: {
id: "VDwkEZ",
defaultMessage: "Products were refunded by ",
description: "refunded event title",
},
fulfillmentReplaced: {
id: "1GTU/3",
defaultMessage: "Products were replaced by ",
description: "replaced event title",
},
fulfillmentReturned: {
id: "nayZY0",
defaultMessage: "Products were returned by",
description: "returned event title",
},
orderDiscountAdded: {
id: "Zptsep",
defaultMessage: "Order was discounted by",
description: "order was discounted event title",
},
orderDiscountAutomaticallyUpdated: {
id: "AQSmqG",
defaultMessage: "Order discount was updated automatically updated",
description: "order discount was updated automatically event title",
},
orderDiscountUpdated: {
id: "/KWNJW",
defaultMessage: "Order discount was updated by",
description: "order discount was updated event title",
},
orderLineDiscountAdded: {
id: "9TAzb5",
defaultMessage: "{productName} discount was added by ",
description: "order line discount added title",
},
orderLineDiscountUpdated: {
id: "NgCb99",
defaultMessage: "{productName} discount was updated by ",
description: "order line discount updated title",
},
orderMarkedAsPaid: {
id: "/0JckE",
defaultMessage: "Order was marked as paid by",
description: "order marked as paid event title",
},
});
export const messages = defineMessages({
by: {
id: "xrPv2K",
defaultMessage: "by",
description: "by preposition",
},
refundedAmount: {
id: "nngeI3",
defaultMessage: "Refunded amount",
description: "amount title",
},
refundedShipment: {
id: "Krzyo+",
defaultMessage: "Shipment was refunded",
description: "shipment refund title",
},
transactionReference: {
id: "XWGZLL",
defaultMessage: "Transaction reference",
description: "transaction reference subtitle",
},
});
interface ExtendedTimelineEventProps {
event: OrderEventFragment;
orderCurrency: string;
hasPlainDate?: boolean;
}
const ExtendedTimelineEvent: React.FC<ExtendedTimelineEventProps> = ({
event,
orderCurrency,
hasPlainDate,
}) => {
const {
id,
date,
type,
lines,
amount,
transactionReference,
shippingCostsIncluded,
} = event;
const classes = useStyles({});
const intl = useIntl();
const eventTypeInCamelCase = camelCase(type);
const getEventTitleMessageInCamelCase = () => {
if (hasOrderLineDiscountWithNoPreviousValue(event)) {
return titles.orderLineDiscountAdded;
}
return titles[eventTypeInCamelCase];
};
const getTitleProps = () => {
if (type === OrderEventsEnum.ORDER_LINE_DISCOUNT_UPDATED) {
return { productName: lines[0]?.itemName };
}
return {};
};
const titleElements = {
by: { text: intl.formatMessage(messages.by) },
employeeName: getEmployeeNameLink(event),
orderNumber: getOrderNumberLink(event),
title: {
text: intl.formatMessage(
getEventTitleMessageInCamelCase(),
getTitleProps(),
),
},
};
const selectTitleElements = () => {
const { title, by, employeeName, orderNumber } = titleElements;
switch (type) {
case OrderEventsEnum.DRAFT_CREATED_FROM_REPLACE: {
return [title, orderNumber, by, employeeName];
}
case OrderEventsEnum.ORDER_DISCOUNT_AUTOMATICALLY_UPDATED: {
return [title];
}
default: {
return [title, employeeName];
}
}
};
if (isTimelineEventOfDiscountType(type)) {
return (
<ExtendedDiscountTimelineEvent
event={event}
titleElements={selectTitleElements()}
/>
);
}
return (
<TimelineEvent
date={date}
titleElements={selectTitleElements()}
key={id}
hasPlainDate={hasPlainDate}
>
{lines && (
<>
<Label
text={intl.formatMessage(productTitles[eventTypeInCamelCase])}
/>
<table>
<tbody>
{lines.map(({ orderLine, quantity, itemName }, i) => (
<tr key={`${itemName}-${i}`}>
<td className={classes.linesTableCell}>
{orderLine?.productName || itemName}
</td>
<td className={classes.linesTableCell}>
<Label text={orderLine?.variantName} />
</td>
<td className={classes.linesTableCell}>
<Label text={`qty: ${quantity}`} />
</td>
</tr>
))}
</tbody>
</table>
{(amount || amount === 0) && (
<>
<Label text={intl.formatMessage(messages.refundedAmount)} />
<Money
money={{
amount,
currency: orderCurrency,
}}
/>
</>
)}
{shippingCostsIncluded && (
<Typography>
{intl.formatMessage(messages.refundedShipment)}
</Typography>
)}
</>
)}
{!!transactionReference && (
<>
<Label text={intl.formatMessage(messages.transactionReference)} />
<Typography>{transactionReference}</Typography>
</>
)}
</TimelineEvent>
);
};
export default ExtendedTimelineEvent;