Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/little-pandas-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

Overcharged status pill has been added to order lists and details view. This means you can now see if an order has been overcharged.
8 changes: 8 additions & 0 deletions locale/defaultMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,10 @@
"4T/RzC": {
"string": "Make sure to save token, you won’t be able to see it again."
},
"4VLj3S": {
"context": "overcharged order status",
"string": "Overcharged"
},
"4VOIum": {
"context": "product availability",
"string": "Enabling this checkbox will remove product from search and category pages. It will be available on collection pages."
Expand Down Expand Up @@ -2084,6 +2088,10 @@
"BWpuKl": {
"string": "Update"
},
"BXKn/d": {
"context": "charge status",
"string": "Overcharged"
},
"BXkF8Z": {
"context": "header",
"string": "Activity"
Expand Down
72 changes: 21 additions & 51 deletions src/customers/components/CustomerOrders/CustomerOrders.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,32 @@
// @ts-strict-ignore
import { DashboardCard } from "@dashboard/components/Card";
import { DateTime } from "@dashboard/components/Date";
import Money from "@dashboard/components/Money";
import { Pill } from "@dashboard/components/Pill";
import ResponsiveTable from "@dashboard/components/ResponsiveTable";
import TableRowLink from "@dashboard/components/TableRowLink";
import { CustomerDetailsQuery } from "@dashboard/graphql";
import { OrderPaymentStatusPill } from "@dashboard/orders/components/OrderPaymentSummaryCard/components/OrderPaymentStatusPill";
import { orderUrl } from "@dashboard/orders/urls";
import { RelayToFlat } from "@dashboard/types";
import { TableBody, TableCell, TableHead } from "@material-ui/core";
import { makeStyles } from "@saleor/macaw-ui";
import { Button, Skeleton } from "@saleor/macaw-ui-next";
import { Button, Skeleton, sprinkles } from "@saleor/macaw-ui-next";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import { Link } from "react-router-dom";

import { maybe, renderCollection, transformPaymentStatus } from "../../../misc";
import { renderCollection } from "../../../misc";

const useStyles = makeStyles(
{
link: {
cursor: "pointer",
},
textRight: {
textAlign: "right",
},
},
{ name: "CustomerOrders" },
);
const textRightStyle = sprinkles({
textAlign: "right",
});

export interface CustomerOrdersProps {
orders: RelayToFlat<CustomerDetailsQuery["user"]["orders"]>;
orders: RelayToFlat<NonNullable<NonNullable<CustomerDetailsQuery["user"]>["orders"]>>;
viewAllHref: string;
}

const CustomerOrders: React.FC<CustomerOrdersProps> = props => {
const { orders, viewAllHref } = props;
const classes = useStyles(props);
const intl = useIntl();
const orderList = orders
? orders.map(order => ({
...order,
paymentStatus: transformPaymentStatus(order.paymentStatus, intl),
}))
: undefined;

return (
<DashboardCard>
Expand Down Expand Up @@ -83,7 +66,7 @@ const CustomerOrders: React.FC<CustomerOrdersProps> = props => {
<TableCell>
<FormattedMessage id="pURrk1" defaultMessage="Status" description="order status" />
</TableCell>
<TableCell className={classes.textRight}>
<TableCell className={textRightStyle}>
<FormattedMessage
id="taX/V3"
defaultMessage="Total"
Expand All @@ -94,42 +77,29 @@ const CustomerOrders: React.FC<CustomerOrdersProps> = props => {
</TableHead>
<TableBody>
{renderCollection(
orderList,
orders,
order => (
<TableRowLink
hover={!!order}
className={order ? classes.link : undefined}
className={
order
? sprinkles({
cursor: "pointer",
})
: undefined
}
href={order && orderUrl(order.id)}
key={order ? order.id : "skeleton"}
>
<TableCell>{order?.number ? "#" + order.number : <Skeleton />}</TableCell>
<TableCell>
{maybe(() => order.number) ? "#" + order.number : <Skeleton />}
{order?.created ? <DateTime date={order.created} plain /> : <Skeleton />}
</TableCell>
<TableCell>
{maybe(() => order.created) ? (
<DateTime date={order.created} plain />
) : (
<Skeleton />
)}
{order ? <OrderPaymentStatusPill order={order} /> : <Skeleton />}
</TableCell>
<TableCell>
{maybe(() => order.paymentStatus.status) !== undefined ? (
order.paymentStatus.status === null ? null : (
<Pill
color={order.paymentStatus.status}
label={order.paymentStatus.localized}
/>
)
) : (
<Skeleton />
)}
</TableCell>
<TableCell className={classes.textRight} align="right">
{maybe(() => order.total.gross) ? (
<Money money={order.total.gross} />
) : (
<Skeleton />
)}
<TableCell className={textRightStyle} align="right">
{order?.total.gross ? <Money money={order.total.gross} /> : <Skeleton />}
</TableCell>
</TableRowLink>
),
Expand Down
2 changes: 2 additions & 0 deletions src/customers/fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
CustomerAddressesQuery,
CustomerDetailsQuery,
OrderChargeStatusEnum,
PaymentChargeStatusEnum,
} from "@dashboard/graphql";

Expand Down Expand Up @@ -1060,6 +1061,7 @@ export const customer: CustomerDetailsQuery["user"] & CustomerAddressesQuery["us
id: "T3JkZXI6MTk=",
number: "8234",
paymentStatus: PaymentChargeStatusEnum.FULLY_CHARGED,
chargeStatus: OrderChargeStatusEnum.FULL,
total: {
__typename: "TaxedMoney",
gross: {
Expand Down
5 changes: 3 additions & 2 deletions src/customers/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const customerDetails = gql`
privateMetadata @include(if: $PERMISSION_MANAGE_STAFF) {
...MetadataItem
}
orders(last: 5) @include(if: $PERMISSION_MANAGE_ORDERS) {
orders(first: 5) @include(if: $PERMISSION_MANAGE_ORDERS) {
edges {
node {
id
Expand All @@ -63,10 +63,11 @@ export const customerDetails = gql`
amount
}
}
chargeStatus
}
}
}
lastPlacedOrder: orders(last: 1) @include(if: $PERMISSION_MANAGE_ORDERS) {
lastPlacedOrder: orders(first: 1) @include(if: $PERMISSION_MANAGE_ORDERS) {
edges {
node {
id
Expand Down
3 changes: 1 addition & 2 deletions src/fragments/orders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,6 @@ export const orderDiscount = gql`
export const fragmentOrderDetails = gql`
fragment OrderDetails on Order {
id
# TODO: remove me
token
...Metadata
billingAddress {
...Address
Expand Down Expand Up @@ -428,6 +426,7 @@ export const fragmentOrderDetails = gql`
}
}
isPaid
chargeStatus
}
`;

Expand Down
8 changes: 5 additions & 3 deletions src/graphql/hooks.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1967,7 +1967,6 @@ export const InvoiceFragmentDoc = gql`
export const OrderDetailsFragmentDoc = gql`
fragment OrderDetails on Order {
id
token
...Metadata
billingAddress {
...Address
Expand Down Expand Up @@ -2123,6 +2122,7 @@ export const OrderDetailsFragmentDoc = gql`
}
}
isPaid
chargeStatus
}
${MetadataFragmentDoc}
${AddressFragmentDoc}
Expand Down Expand Up @@ -7844,7 +7844,7 @@ export const CustomerDetailsDocument = gql`
privateMetadata @include(if: $PERMISSION_MANAGE_STAFF) {
...MetadataItem
}
orders(last: 5) @include(if: $PERMISSION_MANAGE_ORDERS) {
orders(first: 5) @include(if: $PERMISSION_MANAGE_ORDERS) {
edges {
node {
id
Expand All @@ -7857,10 +7857,11 @@ export const CustomerDetailsDocument = gql`
amount
}
}
chargeStatus
}
}
}
lastPlacedOrder: orders(last: 1) @include(if: $PERMISSION_MANAGE_ORDERS) {
lastPlacedOrder: orders(first: 1) @include(if: $PERMISSION_MANAGE_ORDERS) {
edges {
node {
id
Expand Down Expand Up @@ -12279,6 +12280,7 @@ export const OrderListDocument = gql`
}
}
userEmail
chargeStatus
}
}
pageInfo {
Expand Down
58 changes: 29 additions & 29 deletions src/graphql/types.generated.ts

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions src/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
AddressInput,
CountryCode,
DateRangeInput,
OrderChargeStatusEnum,
OrderStatus,
OrderStatusFilter,
PaymentChargeStatusEnum,
Expand Down Expand Up @@ -125,6 +126,25 @@
};
};

export const transformChargedStatus = (status: OrderChargeStatusEnum, intl: IntlShape) => {
switch (status) {
case OrderChargeStatusEnum.OVERCHARGED:
return {
localized: intl.formatMessage({
defaultMessage: "Overcharged",
id: "4VLj3S",
description: "overcharged order status",
}),
status: StatusType.WARNING,
};
default:
return {

Check warning on line 141 in src/misc.ts

View check run for this annotation

Codecov / codecov/patch

src/misc.ts#L140-L141

Added lines #L140 - L141 were not covered by tests
localized: status,
status: StatusType.ERROR,
};
}
};

export const transformOrderStatus = (
status: string,
intl: IntlShape,
Expand Down
41 changes: 39 additions & 2 deletions src/orders/components/OrderListDatagrid/datagrid.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { PillCell } from "@dashboard/components/Datagrid/customCells/PillCell";
import { GetCellContentOpts } from "@dashboard/components/Datagrid/Datagrid";
import { AvailableColumn } from "@dashboard/components/Datagrid/types";
import { OrderListQuery, OrderStatus, PaymentChargeStatusEnum } from "@dashboard/graphql";
import {
OrderChargeStatusEnum,
OrderListQuery,
OrderStatus,
PaymentChargeStatusEnum,
} from "@dashboard/graphql";
import { RelayToFlat } from "@dashboard/types";
import { TextCell } from "@glideapps/glide-data-grid";
import { intlMock } from "@test/intl";
import { renderHook } from "@testing-library/react-hooks";

import { getCustomerCellContent, useGetCellContent } from "./datagrid";
import { getCustomerCellContent, getPaymentCellContent, useGetCellContent } from "./datagrid";

jest.mock("react-intl", () => ({
useIntl: jest.fn(() => ({
Expand Down Expand Up @@ -205,3 +212,33 @@ describe("useGetCellContent", () => {
expect((getCellContent([0, 1], contentOpts) as TextCell).data).toBe("");
});
});

type RowDataType = RelayToFlat<NonNullable<OrderListQuery["orders"]>>[number];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: I meant to keep this in one place types.ts and use everywhere


describe("getPaymentCellContent", () => {
it("should return Fully Paid when payment status is PAID", () => {
// Arrange
const data = {
paymentStatus: "PAID" as PaymentChargeStatusEnum,
} as RowDataType;

// Act
const result = getPaymentCellContent(intlMock, "defaultLight", data);

// Assert
expect((result.data as PillCell["data"]).value).toEqual("PAID");
});

it("should return Overcharged when charge status is OVERCHARGED", () => {
// Arrange
const data = {
chargeStatus: "OVERCHARGED" as OrderChargeStatusEnum,
} as RowDataType;

// Act
const result = getPaymentCellContent(intlMock, "defaultLight", data);

// Assert
expect((result.data as PillCell["data"]).value).toEqual("Overcharged");
});
});
22 changes: 20 additions & 2 deletions src/orders/components/OrderListDatagrid/datagrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ import {
} from "@dashboard/components/Datagrid/customCells/cells";
import { GetCellContentOpts } from "@dashboard/components/Datagrid/Datagrid";
import { AvailableColumn } from "@dashboard/components/Datagrid/types";
import { OrderListQuery } from "@dashboard/graphql";
import { getStatusColor, transformOrderStatus, transformPaymentStatus } from "@dashboard/misc";
import { OrderChargeStatusEnum, OrderListQuery } from "@dashboard/graphql";
import {
getStatusColor,
transformChargedStatus,
transformOrderStatus,
transformPaymentStatus,
} from "@dashboard/misc";
import { OrderListUrlSortField } from "@dashboard/orders/urls";
import { RelayToFlat, Sort } from "@dashboard/types";
import { getColumnSortDirectionIcon } from "@dashboard/utils/columns/getColumnSortDirectionIcon";
Expand Down Expand Up @@ -142,11 +147,24 @@ export function getStatusCellContent(
return readonlyTextCell("-");
}

const higherPriorityChargeStatuses = [OrderChargeStatusEnum.OVERCHARGED];

export function getPaymentCellContent(
intl: IntlShape,
currentTheme: DefaultTheme,
rowData: RelayToFlat<OrderListQuery["orders"]>[number],
) {
if (higherPriorityChargeStatuses.includes(rowData.chargeStatus)) {
const { localized, status } = transformChargedStatus(rowData.chargeStatus, intl);

const color = getStatusColor({
status,
currentTheme,
});

return pillCell(localized, color, COMMON_CELL_PROPS);
}

const paymentStatus = transformPaymentStatus(rowData.paymentStatus, intl);

if (paymentStatus) {
Expand Down
Loading
Loading