saleor-dashboard/src/orders/components/OrderPayment/OrderPayment.tsx
Magdalena Markusik aaa0a9f309
Feature - Gift Cards (#1366)
* Add deletion to gift cards (#1298)

* Add gift cards section to menu and add empty list component

* Update messages

* Change styling of app wide page header to match design

* Add gift cards list table wip

* Update prop name for status chip component to make it more consistent with other components

* Replace old trash icon with new one

* Add Size type based on action dialog sizes to be used app wide

* Add delete icon button

* Add new sizes option to status chip component

* Add / update gift cards list components

* Add bulk actions type

* Work on gift cards list WIP

* Small refactor

* Fix styling of gift cards table

* Remove temp files

* Remove unnecessary type

* Add gift cards section to menu and add empty list component

* Update schema and types

* Add link to gift card update page to gift cards list and add route to gift cards index

* Extract order page title with status chip into a separate generic component and use it in order page title

* wip

* Update money component

* Add gift card details card balance section

* Refactor gift card details

* Add vertical spacer component

* Update schema and types

* Add gift card tag input component along with necessary queries

* Add gift card tag input to gift card update page

* Add gift card update details card expiry section WIP

* Add time period select field WIP

* Post rebase refactor

* Add time period select field to gift card update view

* Update schema, types and gift cards query

* Add getFullName util function and replace existing manual usages

* Add text with select field component

* Add gift card update info card and refactor

* Fixes after review

* Fix import

* Add displaying order link in gift card update

* Refactor

* Connect gift card list to api

* refactor

* Add gift card create dialog

* Fix gift card list styles, change location for gift card list query, minor refactor

* Fix menu structure data for gift cards

* Add channel currencies type to shop

* Refactor text with select field

* Add gift card expiry select component

* Add gift card error type and fragment

* Update global types

* Add default prop to getFormErrors function

* Move gift card details provider to providers dir

* Update global utils with mapSingleValueNodeToChoice function

* Update gift card tag input

* Move and refactor time period field

* Update schema

* move format money function to other money ulities

* Update gift card urls

* Add content or skeleton component

* Add gift card create util for extracting expiry settings input data

* Remove content or skeleton component and move displaying logic to existing skeleton

* Move displaying logic of gift card create dialog to list

* Refactor

* Add hooks for gift card bulk actions and gift card list to be used instead of context directly

* Fix types for text with select field + add parsing for number typed field

* Add initial currency to gift card create form

* Fix gift card create dialog closing animation

* Add gift card update info card

* Refactor gift card update details card

* Add gift card balance dialog

* Move gift card update form providers to providers dir

* Connect gift card update page to api, add necessary contexts etc.

* Refactor

* Refactor

* Add hooks to use instead of gift card contexts directly

* Fix types

* Fix text field target name missing in passed event in text with select field

* Add minimal value option to text with select field, add to gift card inputs

* Fix gift card update balance dialog not changing hasChanged prop after submit

* Refactor

* Add enable / disable section to gift card update

* Refactor

* Refactor

* Fix update balance dialog crashing the app when enetered wrong amount

* Fix gift card list table header styles

* Refactor

* Add metadata to gift card update

* Update messages ids

* Refactor

* Refactor

* Refactor

* Refactor

* Update schema and types, add gift card delete and bulk delete mutations

* Fix url change after gift card delete

* Refactor

* Update messages

* Change gift card list providers order

* Refactor/fix after merge

* Add gift card resend mutation and update types

* Add use dialog form reset hook and make update balance dialog use it, to fix it displaying form errors after modal close and open

* Add gift card resend code dialog

* Add button to open gift card resend code dialog

* Update messages

* Add gift card list bulk enable disable section

* Add refetching gift card list query after bulk activate / deactivate, refactor

* Refactor

* Refactor

* Update messages

* Update schema

* Change gift card update expiry settings

* Refactor

* Add gift card settings view (#1300)

* Add gift card settings view

* Refactor

* Create gift card sttings expiry select

* Update test snapshots

* Update schema

* Update gift card settings page title

* Refactor to match rest of the gift cards flow (#1308)

Co-authored-by: Magdalena Markusik <magdalena.markusik@mirumee.com>

* Refactor

* Refactor

* Set common error codes in string union

Co-authored-by: Magdalena Markusik <magdalena.markusik@mirumee.com>

* Add gift card kind to product type (#1307)

* Add gift card kind to product type

* Fix radio label alignment

* Update test snapshots

* Refactor

* Set default kind in product type create

* Change styling of activate / deactivate button in gift card update

* Add week option to time period select field

* Update messages

* Change labels and update messages

* Add auto fulfill non shippable gift cards to order settings

* Fix fixture

* Update messages

* Update snapshots

* Refactor

* Update types

* Add gift card used in order money amount in order payment section

* Remove unnecessary schema changes

* Change types

* Update fixtures and messages

* Refactor

* Add top card to gift card list (#1327)

* Add top card to gift card  list

* Update no gift card products notification messages

* Use alert instead of notification

* Update prodduct and product  type counts

* Return null if none of the conditions pass

* Update messages

* Fix unused product type deletion

* Update types

* Update imports

* Update messages

* Update test snapshots

* Change gift card dialog expiry settings

* Update form of create gift card dialog

* Add activation option to create gift card dialog

* Update event handling

* Update test snapshots

* Use date context provider for moment time

* Update types

* Refactor

* Update messages

* Update snapshots

* Add channel picker to gift card create modal

* Fix styling

* Add channel picker to gift card resend code dialog

* Update schema and types

* Refactor

* Update messages

* Refactor

* Update messages and snapshots

* Fix order gift card money amount (#1371)

* Update messages and snapshots

* Fix order gift card money in payment card when multiple gift cards used

* Fix missing order id check in gift card events in order gift card money used util

* Fix channel selection in gift card create dialog

* Fix order number not showing in gift card update view

* Add gift card settings to gift card create dialog (#1372)

* Fix gift cards number inputs to accept floats

* Fix order number showing as null in gift card update info card

* Fix channel slug adding in gift card create dialog

* Fix gift card list header top card links to display correctly

* Remove unused imports

Co-authored-by: Dawid Tarasiuk <tarasiukdawid@gmail.com>
2021-09-14 15:57:02 +02:00

366 lines
12 KiB
TypeScript

import { Button, Card, CardActions, CardContent } from "@material-ui/core";
import CardTitle from "@saleor/components/CardTitle";
import { Hr } from "@saleor/components/Hr";
import Money, { subtractMoney } from "@saleor/components/Money";
import Skeleton from "@saleor/components/Skeleton";
import StatusLabel from "@saleor/components/StatusLabel";
import { makeStyles } from "@saleor/macaw-ui";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import { maybe, transformPaymentStatus } from "../../../misc";
import {
OrderAction,
OrderDiscountType,
OrderStatus
} from "../../../types/globalTypes";
import { OrderDetails_order } from "../../types/OrderDetails";
import messages from "./messages";
import { extractOrderGiftCardUsedAmount } from "./utils";
const useStyles = makeStyles(
theme => ({
root: {
...theme.typography.body1,
lineHeight: 1.9,
width: "100%"
},
textRight: {
textAlign: "right"
},
totalRow: {
fontWeight: 600
}
}),
{ name: "OrderPayment" }
);
interface OrderPaymentProps {
order: OrderDetails_order;
onCapture: () => void;
onMarkAsPaid: () => void;
onRefund: () => void;
onVoid: () => void;
}
const OrderPayment: React.FC<OrderPaymentProps> = props => {
const { order, onCapture, onMarkAsPaid, onRefund, onVoid } = props;
const classes = useStyles(props);
const intl = useIntl();
const canCapture = maybe(() => order.actions, []).includes(
OrderAction.CAPTURE
);
const canVoid = maybe(() => order.actions, []).includes(OrderAction.VOID);
const canRefund = maybe(() => order.actions, []).includes(OrderAction.REFUND);
const canMarkAsPaid = maybe(() => order.actions, []).includes(
OrderAction.MARK_AS_PAID
);
const payment = transformPaymentStatus(
maybe(() => order.paymentStatus),
intl
);
const refundedAmount =
order?.totalCaptured &&
order?.total?.gross &&
subtractMoney(order.totalCaptured, order.total.gross);
const getDeliveryMethodName = order => {
if (
order?.shippingMethodName === undefined &&
order?.shippingPrice === undefined &&
order?.collectionPointName === undefined
) {
return <Skeleton />;
}
if (order.shippingMethodName === null) {
return order.collectionPointName == null ? (
<FormattedMessage {...messages.orderPaymentShippingDoesNotApply} />
) : (
<FormattedMessage
{...messages.orderPaymentClickAndCollectShippingMethod}
/>
);
}
return order.shippingMethodName;
};
const usedGiftCardAmount = extractOrderGiftCardUsedAmount(order);
return (
<Card>
<CardTitle
title={
maybe(() => order.paymentStatus) === undefined ? (
<Skeleton />
) : (
<StatusLabel label={payment.localized} status={payment.status} />
)
}
/>
<CardContent>
<table className={classes.root}>
<tbody>
<tr>
<td>
<FormattedMessage
defaultMessage="Subtotal"
description="order subtotal price"
/>
</td>
<td>
{maybe(() => order.lines) === undefined ? (
<Skeleton />
) : (
<FormattedMessage
defaultMessage="{quantity} items"
description="ordered products"
values={{
quantity: order.lines
.map(line => line.quantity)
.reduce((curr, prev) => prev + curr, 0)
}}
/>
)}
</td>
<td className={classes.textRight}>
{maybe(() => order.subtotal.gross) === undefined ? (
<Skeleton />
) : (
<Money money={order.subtotal.gross} />
)}
</td>
</tr>
<tr>
<td>
<FormattedMessage defaultMessage="Taxes" />
</td>
<td>
{maybe(() => order.total.tax) === undefined ? (
<Skeleton />
) : order.total.tax.amount > 0 ? (
intl.formatMessage({
defaultMessage: "VAT included",
description: "vat included in order price"
})
) : (
intl.formatMessage({
defaultMessage: "does not apply",
description: "vat not included in order price",
id: "orderPaymentVATDoesNotApply"
})
)}
</td>
<td className={classes.textRight}>
{maybe(() => order.total.tax) === undefined ? (
<Skeleton />
) : (
<Money money={order.total.tax} />
)}
</td>
</tr>
<tr>
<td>
<FormattedMessage
defaultMessage="Shipping"
description="order shipping method name"
/>
</td>
<td>{getDeliveryMethodName(order)}</td>
<td className={classes.textRight}>
{maybe(() => order.shippingPrice.gross) === undefined ? (
<Skeleton />
) : (
<Money money={order.shippingPrice.gross} />
)}
</td>
</tr>
{order?.discounts?.map(discount => (
<tr>
<td>
<FormattedMessage
defaultMessage="Discount"
description="order discount"
/>
</td>
<td>
{discount.type === OrderDiscountType.MANUAL ? (
<FormattedMessage
defaultMessage="Staff added"
description="staff added type order discount"
/>
) : (
<FormattedMessage
defaultMessage="Voucher"
description="voucher type order discount"
/>
)}
</td>
<td className={classes.textRight}>
-<Money money={discount.amount} />
</td>
</tr>
))}
<tr className={classes.totalRow}>
<td>
<FormattedMessage
defaultMessage="Total"
description="order total price"
/>
</td>
<td />
<td className={classes.textRight}>
{maybe(() => order.total.gross) === undefined ? (
<Skeleton />
) : (
<Money money={order.total.gross} />
)}
</td>
</tr>
</tbody>
</table>
</CardContent>
<Hr />
<CardContent>
<table className={classes.root}>
<tbody>
{!!usedGiftCardAmount && (
<tr>
<td>
<FormattedMessage
defaultMessage="Paid with Gift Card"
description="order payment"
/>
</td>
<td className={classes.textRight}>
<Money
money={{
amount: usedGiftCardAmount,
currency: order?.total?.gross?.currency
}}
/>
</td>
</tr>
)}
<tr>
<td>
<FormattedMessage
defaultMessage="Preauthorized amount"
description="order payment"
/>
</td>
<td className={classes.textRight}>
{maybe(() => order.totalAuthorized.amount) === undefined ? (
<Skeleton />
) : (
<Money money={order.totalAuthorized} />
)}
</td>
</tr>
<tr>
<td>
<FormattedMessage
defaultMessage="Captured amount"
description="order payment"
/>
</td>
<td className={classes.textRight}>
{maybe(() => order.totalCaptured.amount) === undefined ? (
<Skeleton />
) : (
<Money money={order.totalCaptured} />
)}
</td>
</tr>
<tr>
<td>
<FormattedMessage
defaultMessage="Refunded amount"
description="order payment"
/>
</td>
<td className={classes.textRight}>
{refundedAmount?.amount === undefined ? (
<Skeleton />
) : (
<Money money={refundedAmount} />
)}
</td>
</tr>
<tr className={classes.totalRow}>
<td>
<FormattedMessage
defaultMessage="Outstanding Balance"
description="order payment"
/>
</td>
<td className={classes.textRight}>
{maybe(
() => order.total.gross.amount && order.totalCaptured.amount
) === undefined ? (
<Skeleton />
) : (
<Money
money={subtractMoney(
order.totalCaptured,
order.total.gross
)}
/>
)}
</td>
</tr>
</tbody>
</table>
</CardContent>
{maybe(() => order.status) !== OrderStatus.CANCELED &&
(canCapture || canRefund || canVoid || canMarkAsPaid) && (
<>
<Hr />
<CardActions>
{canCapture && (
<Button color="primary" variant="text" onClick={onCapture}>
<FormattedMessage
defaultMessage="Capture"
description="capture payment, button"
/>
</Button>
)}
{canRefund && (
<Button
color="primary"
variant="text"
onClick={onRefund}
data-test-id="refund-button"
>
<FormattedMessage
defaultMessage="Refund"
description="button"
/>
</Button>
)}
{canVoid && (
<Button color="primary" variant="text" onClick={onVoid}>
<FormattedMessage
defaultMessage="Void"
description="void payment, button"
/>
</Button>
)}
{canMarkAsPaid && (
<Button color="primary" variant="text" onClick={onMarkAsPaid}>
<FormattedMessage
defaultMessage="Mark as paid"
description="order, button"
/>
</Button>
)}
</CardActions>
</>
)}
</Card>
);
};
OrderPayment.displayName = "OrderPayment";
export default OrderPayment;