Add gift card expired status (#1412)
* Add gift card expiry status to gift card details provider WIP * Add gift card expiry handling in gift card update page header * Add gift card expiry handling to gift card update details tag section & refactor * Add gift card expiry handling to gift card update details expiry date section * Add gift card expiry handling to gift card update metadata fields, add disabled prop to metadata cards * Add comment * Add gift card expiry handling to gift card list & refactor * Change back some parts because of change of requirements * Extract messages * Remove comments, fix wrong expiry label being displayed in gift card list
This commit is contained in:
parent
ffe44be733
commit
705df796d2
23 changed files with 229 additions and 152 deletions
|
@ -3546,10 +3546,18 @@
|
||||||
"context": "GiftCardUpdateDetailsCard set balance button label",
|
"context": "GiftCardUpdateDetailsCard set balance button label",
|
||||||
"string": "set balance"
|
"string": "set balance"
|
||||||
},
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateDetailsCard_dot_tagInputLabel": {
|
||||||
|
"context": "GiftCardTagInput tag label",
|
||||||
|
"string": "Card Tag"
|
||||||
|
},
|
||||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateDetailsCard_dot_title": {
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateDetailsCard_dot_title": {
|
||||||
"context": "GiftCardUpdateDetailsCard title",
|
"context": "GiftCardUpdateDetailsCard title",
|
||||||
"string": "Details"
|
"string": "Details"
|
||||||
},
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateExpirySelect_dot_expiredOnLabel": {
|
||||||
|
"context": "GiftCarUpdateDetailsExpirySection expired on label",
|
||||||
|
"string": "Expired on {date}"
|
||||||
|
},
|
||||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateExpirySelect_dot_expiryDateCheckboxLabel": {
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateExpirySelect_dot_expiryDateCheckboxLabel": {
|
||||||
"context": "GiftCarUpdateDetailsExpirySection expiry date checkbox label",
|
"context": "GiftCarUpdateDetailsExpirySection expiry date checkbox label",
|
||||||
"string": "Gift card expires"
|
"string": "Gift card expires"
|
||||||
|
@ -3590,6 +3598,14 @@
|
||||||
"context": "GiftCardUpdateInfoCard used by label",
|
"context": "GiftCardUpdateInfoCard used by label",
|
||||||
"string": "Used by"
|
"string": "Used by"
|
||||||
},
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_disabledStatusLabel": {
|
||||||
|
"context": "giftCardUpdatePageHeader disabled status label",
|
||||||
|
"string": "Disabled"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_expiredStatusLabel": {
|
||||||
|
"context": "giftCardUpdatePageHeader expired status label",
|
||||||
|
"string": "Expired"
|
||||||
|
},
|
||||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_resendButtonLabel": {
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_resendButtonLabel": {
|
||||||
"context": "giftCardUpdatePageHeader resendButtonLabel",
|
"context": "giftCardUpdatePageHeader resendButtonLabel",
|
||||||
"string": "Resend code"
|
"string": "Resend code"
|
||||||
|
@ -3654,10 +3670,6 @@
|
||||||
"context": "GiftCardsListHeader menu item settings",
|
"context": "GiftCardsListHeader menu item settings",
|
||||||
"string": "Export card codes"
|
"string": "Export card codes"
|
||||||
},
|
},
|
||||||
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardDisabledLabel": {
|
|
||||||
"context": "GiftCardsListTable disabled label",
|
|
||||||
"string": "Disabled"
|
|
||||||
},
|
|
||||||
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardProduct": {
|
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardProduct": {
|
||||||
"context": "GiftCardsListHeader alert",
|
"context": "GiftCardsListHeader alert",
|
||||||
"string": "gift card product"
|
"string": "gift card product"
|
||||||
|
@ -3754,10 +3766,6 @@
|
||||||
"context": "checkbox label",
|
"context": "checkbox label",
|
||||||
"string": "Set gift card expiration period"
|
"string": "Set gift card expiration period"
|
||||||
},
|
},
|
||||||
"src_dot_giftCards_dot_components_dot_GiftCardTagInput_dot_label": {
|
|
||||||
"context": "GiftCardTagInput tag label",
|
|
||||||
"string": "Card Tag"
|
|
||||||
},
|
|
||||||
"src_dot_giftCards_dot_components_dot_GiftCardTagInput_dot_placeholder": {
|
"src_dot_giftCards_dot_components_dot_GiftCardTagInput_dot_placeholder": {
|
||||||
"context": "GiftCardTagInput tag placeholder",
|
"context": "GiftCardTagInput tag placeholder",
|
||||||
"string": "Tag"
|
"string": "Tag"
|
||||||
|
|
|
@ -120,6 +120,7 @@ const MetadataCard: React.FC<MetadataCardProps> = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Typography color="textSecondary">
|
<Typography color="textSecondary">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Use the button below to add new metadata field"
|
defaultMessage="Use the button below to add new metadata field"
|
||||||
|
|
|
@ -33,7 +33,7 @@ const GiftCardUpdateDetailsBalanceSection: React.FC = () => {
|
||||||
<HorizontalSpacer />
|
<HorizontalSpacer />
|
||||||
/
|
/
|
||||||
<HorizontalSpacer />
|
<HorizontalSpacer />
|
||||||
<Money money={initialBalance} />
|
<Money className={classes.balanceTotal} money={initialBalance} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
import { Button, Card, CardContent, Divider } from "@material-ui/core";
|
import {
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
Divider,
|
||||||
|
Typography
|
||||||
|
} from "@material-ui/core";
|
||||||
|
import VerticalSpacer from "@saleor/apps/components/VerticalSpacer";
|
||||||
import CardSpacer from "@saleor/components/CardSpacer";
|
import CardSpacer from "@saleor/components/CardSpacer";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import Skeleton from "@saleor/components/Skeleton";
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
|
@ -16,9 +23,8 @@ import { giftCardUpdateDetailsCardMessages as messages } from "./messages";
|
||||||
const GiftCardUpdateDetailsCard: React.FC = () => {
|
const GiftCardUpdateDetailsCard: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const { loading } = useGiftCardDetails();
|
const { loading, giftCard } = useGiftCardDetails();
|
||||||
const { openSetBalanceDialog } = useGiftCardUpdateDialogs();
|
const { openSetBalanceDialog } = useGiftCardUpdateDialogs();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
change,
|
change,
|
||||||
data: { tag },
|
data: { tag },
|
||||||
|
@ -30,13 +36,16 @@ const GiftCardUpdateDetailsCard: React.FC = () => {
|
||||||
<CardTitle
|
<CardTitle
|
||||||
title={intl.formatMessage(messages.title)}
|
title={intl.formatMessage(messages.title)}
|
||||||
toolbar={
|
toolbar={
|
||||||
<Button
|
!loading &&
|
||||||
data-test-id="set-balance-button"
|
!giftCard?.isExpired && (
|
||||||
color="primary"
|
<Button
|
||||||
onClick={openSetBalanceDialog}
|
data-test-id="set-balance-button"
|
||||||
>
|
color="primary"
|
||||||
{intl.formatMessage(messages.setBalanceButtonLabel)}
|
onClick={openSetBalanceDialog}
|
||||||
</Button>
|
>
|
||||||
|
{intl.formatMessage(messages.setBalanceButtonLabel)}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
@ -47,10 +56,13 @@ const GiftCardUpdateDetailsCard: React.FC = () => {
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
<Divider />
|
<Divider />
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
<Typography>
|
||||||
|
{intl.formatMessage(messages.tagInputLabel)}
|
||||||
|
</Typography>
|
||||||
|
<VerticalSpacer />
|
||||||
<GiftCardTagInput
|
<GiftCardTagInput
|
||||||
error={formErrors?.tag}
|
error={formErrors?.tag}
|
||||||
name="tag"
|
name="tag"
|
||||||
withTopLabel
|
|
||||||
value={tag}
|
value={tag}
|
||||||
change={change}
|
change={change}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -12,5 +12,9 @@ export const giftCardUpdateDetailsCardMessages = defineMessages({
|
||||||
cardBalanceLabel: {
|
cardBalanceLabel: {
|
||||||
defaultMessage: "Card Balance",
|
defaultMessage: "Card Balance",
|
||||||
description: "GiftCardUpdateDetailsCard card balance label"
|
description: "GiftCardUpdateDetailsCard card balance label"
|
||||||
|
},
|
||||||
|
tagInputLabel: {
|
||||||
|
defaultMessage: "Card Tag",
|
||||||
|
description: "GiftCardTagInput tag label"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,6 +22,9 @@ export const useGiftCardDetailsBalanceStyles = makeStyles(
|
||||||
height: 28,
|
height: 28,
|
||||||
borderRadius: 14,
|
borderRadius: 14,
|
||||||
backgroundColor: theme.palette.primary.light
|
backgroundColor: theme.palette.primary.light
|
||||||
|
},
|
||||||
|
balanceTotal: {
|
||||||
|
color: theme.palette.text.secondary
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
{ name: "GiftCardUpdateDetailsBalanceSection" }
|
{ name: "GiftCardUpdateDetailsBalanceSection" }
|
||||||
|
|
|
@ -8,5 +8,9 @@ export const giftCardExpirySelectMessages = defineMessages({
|
||||||
expiryDateLabel: {
|
expiryDateLabel: {
|
||||||
defaultMessage: "Expiration date",
|
defaultMessage: "Expiration date",
|
||||||
description: "GiftCarUpdateDetailsExpirySection expiry date label"
|
description: "GiftCarUpdateDetailsExpirySection expiry date label"
|
||||||
|
},
|
||||||
|
expiredOnLabel: {
|
||||||
|
defaultMessage: "Expired on {date}",
|
||||||
|
description: "GiftCarUpdateDetailsExpirySection expired on label"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,10 +16,9 @@ import React from "react";
|
||||||
import { MessageDescriptor, useIntl } from "react-intl";
|
import { MessageDescriptor, useIntl } from "react-intl";
|
||||||
|
|
||||||
import useGiftCardDetails from "../providers/GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
import useGiftCardDetails from "../providers/GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||||
|
import { PLACEHOLDER } from "../types";
|
||||||
import { giftCardUpdateInfoCardMessages as messages } from "./messages";
|
import { giftCardUpdateInfoCardMessages as messages } from "./messages";
|
||||||
|
|
||||||
const PLACEHOLDER = "-";
|
|
||||||
|
|
||||||
const GiftCardUpdateInfoCardContent: React.FC = () => {
|
const GiftCardUpdateInfoCardContent: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const localizeDate = useDateLocalize();
|
const localizeDate = useDateLocalize();
|
||||||
|
|
|
@ -20,9 +20,13 @@ const GiftCardEnableDisableSection: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
giftCard: { id, isActive }
|
giftCard: { id, isActive, isExpired }
|
||||||
} = useGiftCardDetails();
|
} = useGiftCardDetails();
|
||||||
|
|
||||||
|
if (isExpired) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const onActivateCompleted = (data: GiftCardActivate) => {
|
const onActivateCompleted = (data: GiftCardActivate) => {
|
||||||
const errors = data?.giftCardActivate?.errors;
|
const errors = data?.giftCardActivate?.errors;
|
||||||
|
|
||||||
|
|
|
@ -25,42 +25,53 @@ const GiftCardUpdatePageHeader: React.FC = () => {
|
||||||
|
|
||||||
const { openResendCodeDialog } = useGiftCardUpdateDialogs();
|
const { openResendCodeDialog } = useGiftCardUpdateDialogs();
|
||||||
|
|
||||||
const { displayCode, isActive } = giftCard;
|
const { displayCode, isActive, isExpired } = giftCard;
|
||||||
|
|
||||||
const title = intl.formatMessage(tableMessages.codeEndingWithLabel, {
|
const title = intl.formatMessage(tableMessages.codeEndingWithLabel, {
|
||||||
displayCode
|
displayCode
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getPageTitle = () => {
|
||||||
|
if (isExpired) {
|
||||||
|
return (
|
||||||
|
<PageTitleWithStatusChip
|
||||||
|
title={title}
|
||||||
|
statusLabel={intl.formatMessage(messages.expiredStatusLabel)}
|
||||||
|
statusType={StatusType.NEUTRAL}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isActive) {
|
||||||
|
return (
|
||||||
|
<PageTitleWithStatusChip
|
||||||
|
title={title}
|
||||||
|
statusLabel={intl.formatMessage(messages.disabledStatusLabel)}
|
||||||
|
statusType={StatusType.ERROR}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return title;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Backlink onClick={navigateBack}>
|
<Backlink onClick={navigateBack}>
|
||||||
{intl.formatMessage(sectionNames.giftCards)}
|
{intl.formatMessage(sectionNames.giftCards)}
|
||||||
</Backlink>
|
</Backlink>
|
||||||
<PageHeader
|
<PageHeader inline title={getPageTitle()}>
|
||||||
inline
|
|
||||||
title={
|
|
||||||
isActive ? (
|
|
||||||
title
|
|
||||||
) : (
|
|
||||||
<PageTitleWithStatusChip
|
|
||||||
title={title}
|
|
||||||
statusLabel={intl.formatMessage(
|
|
||||||
tableMessages.giftCardDisabledLabel
|
|
||||||
)}
|
|
||||||
statusType={StatusType.ERROR}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<GiftCardEnableDisableSection />
|
<GiftCardEnableDisableSection />
|
||||||
<HorizontalSpacer />
|
<HorizontalSpacer />
|
||||||
<Button
|
{!isExpired && (
|
||||||
color="primary"
|
<Button
|
||||||
variant="contained"
|
color="primary"
|
||||||
onClick={openResendCodeDialog}
|
variant="contained"
|
||||||
>
|
onClick={openResendCodeDialog}
|
||||||
{intl.formatMessage(messages.resendButtonLabel)}
|
>
|
||||||
</Button>
|
{intl.formatMessage(messages.resendButtonLabel)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,5 +15,13 @@ export const giftCardUpdatePageHeaderMessages = defineMessages({
|
||||||
resendButtonLabel: {
|
resendButtonLabel: {
|
||||||
defaultMessage: "Resend code",
|
defaultMessage: "Resend code",
|
||||||
description: "giftCardUpdatePageHeader resendButtonLabel"
|
description: "giftCardUpdatePageHeader resendButtonLabel"
|
||||||
|
},
|
||||||
|
expiredStatusLabel: {
|
||||||
|
defaultMessage: "Expired",
|
||||||
|
description: "giftCardUpdatePageHeader expired status label"
|
||||||
|
},
|
||||||
|
disabledStatusLabel: {
|
||||||
|
defaultMessage: "Disabled",
|
||||||
|
description: "giftCardUpdatePageHeader disabled status label"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,6 +2,8 @@ import React, { createContext } from "react";
|
||||||
|
|
||||||
import { useGiftCardDetailsQuery } from "../../queries";
|
import { useGiftCardDetailsQuery } from "../../queries";
|
||||||
import { GiftCardDetails_giftCard } from "../../types/GiftCardDetails";
|
import { GiftCardDetails_giftCard } from "../../types/GiftCardDetails";
|
||||||
|
import { ExtendedGiftCard } from "./types";
|
||||||
|
import { getExtendedGiftCard } from "./utils";
|
||||||
|
|
||||||
interface GiftCardDetailsProviderProps {
|
interface GiftCardDetailsProviderProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
@ -9,7 +11,7 @@ interface GiftCardDetailsProviderProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GiftCardDetailsConsumerProps {
|
export interface GiftCardDetailsConsumerProps {
|
||||||
giftCard: GiftCardDetails_giftCard;
|
giftCard: ExtendedGiftCard<GiftCardDetails_giftCard> | undefined;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +29,7 @@ const GiftCardDetailsProvider: React.FC<GiftCardDetailsProviderProps> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const providerValues: GiftCardDetailsConsumerProps = {
|
const providerValues: GiftCardDetailsConsumerProps = {
|
||||||
giftCard: data?.giftCard,
|
giftCard: getExtendedGiftCard(data?.giftCard),
|
||||||
loading
|
loading
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
export type ExtendedGiftCard<T extends GiftCardBase> = T & {
|
||||||
|
isExpired: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface GiftCardBase {
|
||||||
|
expiryDate: string | undefined;
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
|
import { ExtendedGiftCard, GiftCardBase } from "./types";
|
||||||
|
|
||||||
|
export function isGiftCardExpired<T extends GiftCardBase>(
|
||||||
|
giftCard: T
|
||||||
|
): boolean {
|
||||||
|
if (!giftCard?.expiryDate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return moment(giftCard?.expiryDate).isBefore(moment());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getExtendedGiftCard<T extends GiftCardBase>(
|
||||||
|
giftCard?: T
|
||||||
|
): ExtendedGiftCard<T> {
|
||||||
|
if (!giftCard) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...giftCard,
|
||||||
|
isExpired: isGiftCardExpired(giftCard)
|
||||||
|
};
|
||||||
|
}
|
|
@ -9,3 +9,5 @@ export enum GiftCardUpdatePageActionParamsEnum {
|
||||||
export type GiftCardUpdatePageUrlQueryParams = Dialog<
|
export type GiftCardUpdatePageUrlQueryParams = Dialog<
|
||||||
GiftCardUpdatePageActionParamsEnum
|
GiftCardUpdatePageActionParamsEnum
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export const PLACEHOLDER = "-";
|
||||||
|
|
|
@ -14,6 +14,7 @@ import Skeleton from "@saleor/components/Skeleton";
|
||||||
import StatusChip from "@saleor/components/StatusChip";
|
import StatusChip from "@saleor/components/StatusChip";
|
||||||
import { StatusType } from "@saleor/components/StatusChip/types";
|
import { StatusType } from "@saleor/components/StatusChip/types";
|
||||||
import { customerUrl } from "@saleor/customers/urls";
|
import { customerUrl } from "@saleor/customers/urls";
|
||||||
|
import { PLACEHOLDER } from "@saleor/giftCards/GiftCardUpdate/types";
|
||||||
import { giftCardUrl } from "@saleor/giftCards/urls";
|
import { giftCardUrl } from "@saleor/giftCards/urls";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import { renderCollection } from "@saleor/misc";
|
import { renderCollection } from "@saleor/misc";
|
||||||
|
@ -21,6 +22,7 @@ import { productUrl } from "@saleor/products/urls";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { giftCardUpdatePageHeaderMessages as giftCardStatusChipMessages } from "../../GiftCardUpdate/GiftCardUpdatePageHeader/messages";
|
||||||
import { giftCardsListTableMessages as messages } from "../messages";
|
import { giftCardsListTableMessages as messages } from "../messages";
|
||||||
import useGiftCardListDialogs from "../providers/GiftCardListDialogsProvider/hooks/useGiftCardListDialogs";
|
import useGiftCardListDialogs from "../providers/GiftCardListDialogsProvider/hooks/useGiftCardListDialogs";
|
||||||
import useGiftCardList from "../providers/GiftCardListProvider/hooks/useGiftCardList";
|
import useGiftCardList from "../providers/GiftCardListProvider/hooks/useGiftCardList";
|
||||||
|
@ -29,8 +31,6 @@ import { useTableStyles as useStyles } from "../styles";
|
||||||
import GiftCardsListTableFooter from "./GiftCardsListTableFooter";
|
import GiftCardsListTableFooter from "./GiftCardsListTableFooter";
|
||||||
import GiftCardsListTableHeader from "./GiftCardsListTableHeader";
|
import GiftCardsListTableHeader from "./GiftCardsListTableHeader";
|
||||||
|
|
||||||
const PLACEHOLDER = "-";
|
|
||||||
|
|
||||||
const GiftCardsListTable: React.FC = () => {
|
const GiftCardsListTable: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const classes = useStyles({});
|
const classes = useStyles({});
|
||||||
|
@ -43,6 +43,38 @@ const GiftCardsListTable: React.FC = () => {
|
||||||
const redirectToGiftCardUpdate = (id: string) => () =>
|
const redirectToGiftCardUpdate = (id: string) => () =>
|
||||||
navigate(giftCardUrl(id));
|
navigate(giftCardUrl(id));
|
||||||
|
|
||||||
|
const selectGiftCardStatusChip = ({
|
||||||
|
isActive,
|
||||||
|
isExpired
|
||||||
|
}: {
|
||||||
|
isActive: boolean;
|
||||||
|
isExpired: boolean;
|
||||||
|
}) => {
|
||||||
|
if (isExpired) {
|
||||||
|
return (
|
||||||
|
<StatusChip
|
||||||
|
size="md"
|
||||||
|
status={StatusType.NEUTRAL}
|
||||||
|
label={intl.formatMessage(
|
||||||
|
giftCardStatusChipMessages.expiredStatusLabel
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isActive) {
|
||||||
|
return (
|
||||||
|
<StatusChip
|
||||||
|
size="md"
|
||||||
|
status={StatusType.ERROR}
|
||||||
|
label={intl.formatMessage(
|
||||||
|
giftCardStatusChipMessages.disabledStatusLabel
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<ResponsiveTable>
|
<ResponsiveTable>
|
||||||
|
@ -59,7 +91,8 @@ const GiftCardsListTable: React.FC = () => {
|
||||||
tag,
|
tag,
|
||||||
isActive,
|
isActive,
|
||||||
product,
|
product,
|
||||||
currentBalance
|
currentBalance,
|
||||||
|
isExpired
|
||||||
}) => (
|
}) => (
|
||||||
<TableRow
|
<TableRow
|
||||||
onClick={redirectToGiftCardUpdate(id)}
|
onClick={redirectToGiftCardUpdate(id)}
|
||||||
|
@ -80,18 +113,10 @@ const GiftCardsListTable: React.FC = () => {
|
||||||
displayCode
|
displayCode
|
||||||
})}
|
})}
|
||||||
</Typography>
|
</Typography>
|
||||||
{!isActive && (
|
<>
|
||||||
<>
|
<HorizontalSpacer spacing={2} />
|
||||||
<HorizontalSpacer spacing={2} />
|
{selectGiftCardStatusChip({ isActive, isExpired })}
|
||||||
<StatusChip
|
</>
|
||||||
size="md"
|
|
||||||
status={StatusType.ERROR}
|
|
||||||
label={intl.formatMessage(
|
|
||||||
messages.giftCardDisabledLabel
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
|
|
|
@ -75,10 +75,6 @@ export const giftCardsListTableMessages = defineMessages({
|
||||||
defaultMessage: "Code ending with {displayCode}",
|
defaultMessage: "Code ending with {displayCode}",
|
||||||
description: "GiftCardsListTable code ending with label"
|
description: "GiftCardsListTable code ending with label"
|
||||||
},
|
},
|
||||||
giftCardDisabledLabel: {
|
|
||||||
defaultMessage: "Disabled",
|
|
||||||
description: "GiftCardsListTable disabled label"
|
|
||||||
},
|
|
||||||
noGiftCardsFound: {
|
noGiftCardsFound: {
|
||||||
defaultMessage: "No gift cards found",
|
defaultMessage: "No gift cards found",
|
||||||
description: "GiftCardsListTable no cards found title"
|
description: "GiftCardsListTable no cards found title"
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { ExtendedGiftCard } from "@saleor/giftCards/GiftCardUpdate/providers/GiftCardDetailsProvider/types";
|
||||||
|
import { getExtendedGiftCard } from "@saleor/giftCards/GiftCardUpdate/providers/GiftCardDetailsProvider/utils";
|
||||||
import useBulkActions, {
|
import useBulkActions, {
|
||||||
UseBulkActionsProps
|
UseBulkActionsProps
|
||||||
} from "@saleor/hooks/useBulkActions";
|
} from "@saleor/hooks/useBulkActions";
|
||||||
|
@ -28,7 +30,7 @@ interface GiftCardsListProviderProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GiftCardListDataProps {
|
export interface GiftCardListDataProps {
|
||||||
giftCards: GiftCardList_giftCards_edges_node[];
|
giftCards: Array<ExtendedGiftCard<GiftCardList_giftCards_edges_node>>;
|
||||||
pageInfo: PageInfo;
|
pageInfo: PageInfo;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
params: GiftCardListUrlQueryParams;
|
params: GiftCardListUrlQueryParams;
|
||||||
|
@ -73,8 +75,11 @@ export const GiftCardsListProvider: React.FC<GiftCardsListProviderProps> = ({
|
||||||
variables: queryVariables
|
variables: queryVariables
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const giftCards =
|
||||||
|
mapEdgesToItems(data?.giftCards)?.map(getExtendedGiftCard) || [];
|
||||||
|
|
||||||
const providerValues: GiftCardsListConsumerProps = {
|
const providerValues: GiftCardsListConsumerProps = {
|
||||||
giftCards: mapEdgesToItems(data?.giftCards) || [],
|
giftCards,
|
||||||
loading,
|
loading,
|
||||||
isSelected,
|
isSelected,
|
||||||
listElements,
|
listElements,
|
||||||
|
|
|
@ -3,19 +3,32 @@ import { fragmentMoney } from "@saleor/fragments/products";
|
||||||
import makeQuery from "@saleor/hooks/makeQuery";
|
import makeQuery from "@saleor/hooks/makeQuery";
|
||||||
import gql from "graphql-tag";
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
import { giftCardDataFragment } from "../GiftCardUpdate/queries";
|
|
||||||
import { GiftCardList, GiftCardListVariables } from "./types/GiftCardList";
|
import { GiftCardList, GiftCardListVariables } from "./types/GiftCardList";
|
||||||
import { GiftCardProductsCount } from "./types/GiftCardProductsCount";
|
import { GiftCardProductsCount } from "./types/GiftCardProductsCount";
|
||||||
|
|
||||||
export const giftCardList = gql`
|
export const giftCardList = gql`
|
||||||
${fragmentUserBase}
|
${fragmentUserBase}
|
||||||
${fragmentMoney}
|
${fragmentMoney}
|
||||||
${giftCardDataFragment}
|
|
||||||
query GiftCardList($first: Int, $after: String, $last: Int, $before: String) {
|
query GiftCardList($first: Int, $after: String, $last: Int, $before: String) {
|
||||||
giftCards(first: $first, after: $after, before: $before, last: $last) {
|
giftCards(first: $first, after: $after, before: $before, last: $last) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
...GiftCardData
|
id
|
||||||
|
usedByEmail
|
||||||
|
displayCode
|
||||||
|
isActive
|
||||||
|
expiryDate
|
||||||
|
product {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
tag
|
||||||
|
usedBy {
|
||||||
|
...UserBase
|
||||||
|
}
|
||||||
|
currentBalance {
|
||||||
|
...Money
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pageInfo {
|
pageInfo {
|
||||||
|
@ -27,6 +40,7 @@ export const giftCardList = gql`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const useGiftCardListQuery = makeQuery<
|
export const useGiftCardListQuery = makeQuery<
|
||||||
GiftCardList,
|
GiftCardList,
|
||||||
GiftCardListVariables
|
GiftCardListVariables
|
||||||
|
@ -42,6 +56,7 @@ export const giftCardProductsCount = gql`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const useGiftCardProductsCountQuery = makeQuery<
|
export const useGiftCardProductsCountQuery = makeQuery<
|
||||||
GiftCardProductsCount,
|
GiftCardProductsCount,
|
||||||
never
|
never
|
||||||
|
|
|
@ -7,25 +7,6 @@
|
||||||
// GraphQL query operation: GiftCardList
|
// GraphQL query operation: GiftCardList
|
||||||
// ====================================================
|
// ====================================================
|
||||||
|
|
||||||
export interface GiftCardList_giftCards_edges_node_metadata {
|
|
||||||
__typename: "MetadataItem";
|
|
||||||
key: string;
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GiftCardList_giftCards_edges_node_privateMetadata {
|
|
||||||
__typename: "MetadataItem";
|
|
||||||
key: string;
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GiftCardList_giftCards_edges_node_createdBy {
|
|
||||||
__typename: "User";
|
|
||||||
id: string;
|
|
||||||
firstName: string;
|
|
||||||
lastName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GiftCardList_giftCards_edges_node_product {
|
export interface GiftCardList_giftCards_edges_node_product {
|
||||||
__typename: "Product";
|
__typename: "Product";
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -39,18 +20,6 @@ export interface GiftCardList_giftCards_edges_node_usedBy {
|
||||||
lastName: string;
|
lastName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GiftCardList_giftCards_edges_node_app {
|
|
||||||
__typename: "App";
|
|
||||||
id: string;
|
|
||||||
name: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GiftCardList_giftCards_edges_node_initialBalance {
|
|
||||||
__typename: "Money";
|
|
||||||
amount: number;
|
|
||||||
currency: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GiftCardList_giftCards_edges_node_currentBalance {
|
export interface GiftCardList_giftCards_edges_node_currentBalance {
|
||||||
__typename: "Money";
|
__typename: "Money";
|
||||||
amount: number;
|
amount: number;
|
||||||
|
@ -59,24 +28,15 @@ export interface GiftCardList_giftCards_edges_node_currentBalance {
|
||||||
|
|
||||||
export interface GiftCardList_giftCards_edges_node {
|
export interface GiftCardList_giftCards_edges_node {
|
||||||
__typename: "GiftCard";
|
__typename: "GiftCard";
|
||||||
metadata: (GiftCardList_giftCards_edges_node_metadata | null)[];
|
|
||||||
privateMetadata: (GiftCardList_giftCards_edges_node_privateMetadata | null)[];
|
|
||||||
displayCode: string;
|
|
||||||
boughtInChannel: string | null;
|
|
||||||
createdBy: GiftCardList_giftCards_edges_node_createdBy | null;
|
|
||||||
product: GiftCardList_giftCards_edges_node_product | null;
|
|
||||||
usedBy: GiftCardList_giftCards_edges_node_usedBy | null;
|
|
||||||
usedByEmail: string | null;
|
|
||||||
createdByEmail: string | null;
|
|
||||||
app: GiftCardList_giftCards_edges_node_app | null;
|
|
||||||
created: any;
|
|
||||||
expiryDate: any | null;
|
|
||||||
lastUsedOn: any | null;
|
|
||||||
isActive: boolean;
|
|
||||||
initialBalance: GiftCardList_giftCards_edges_node_initialBalance | null;
|
|
||||||
currentBalance: GiftCardList_giftCards_edges_node_currentBalance | null;
|
|
||||||
id: string;
|
id: string;
|
||||||
|
usedByEmail: string | null;
|
||||||
|
displayCode: string;
|
||||||
|
isActive: boolean;
|
||||||
|
expiryDate: any | null;
|
||||||
|
product: GiftCardList_giftCards_edges_node_product | null;
|
||||||
tag: string | null;
|
tag: string | null;
|
||||||
|
usedBy: GiftCardList_giftCards_edges_node_usedBy | null;
|
||||||
|
currentBalance: GiftCardList_giftCards_edges_node_currentBalance | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GiftCardList_giftCards_edges {
|
export interface GiftCardList_giftCards_edges {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { Typography } from "@material-ui/core";
|
|
||||||
import VerticalSpacer from "@saleor/apps/components/VerticalSpacer";
|
|
||||||
import SingleAutocompleteSelectField, {
|
import SingleAutocompleteSelectField, {
|
||||||
SingleAutocompleteSelectFieldProps
|
SingleAutocompleteSelectFieldProps
|
||||||
} from "@saleor/components/SingleAutocompleteSelectField";
|
} from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
|
@ -24,12 +22,10 @@ interface GiftCardTagInputProps
|
||||||
extends Pick<SingleAutocompleteSelectFieldProps, "name"> {
|
extends Pick<SingleAutocompleteSelectFieldProps, "name"> {
|
||||||
change: FormChange;
|
change: FormChange;
|
||||||
value: string;
|
value: string;
|
||||||
withTopLabel?: boolean;
|
|
||||||
error: GiftCardError;
|
error: GiftCardError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GiftCardTagInput: React.FC<GiftCardTagInputProps> = ({
|
const GiftCardTagInput: React.FC<GiftCardTagInputProps> = ({
|
||||||
withTopLabel = false,
|
|
||||||
change,
|
change,
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
|
@ -47,30 +43,22 @@ const GiftCardTagInput: React.FC<GiftCardTagInputProps> = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<SingleAutocompleteSelectField
|
||||||
{withTopLabel && (
|
error={!!error}
|
||||||
<>
|
helperText={getGiftCardErrorMessage(error, intl)}
|
||||||
<Typography>{intl.formatMessage(messages.label)}</Typography>
|
allowCustomValues
|
||||||
<VerticalSpacer />
|
name={name || "giftCardTag"}
|
||||||
</>
|
label={`${intl.formatMessage(messages.placeholder)} *${intl.formatMessage(
|
||||||
)}
|
commonMessages.optionalField
|
||||||
<SingleAutocompleteSelectField
|
)}`}
|
||||||
error={!!error}
|
data-test-id="gift-card-tag-select-field"
|
||||||
helperText={getGiftCardErrorMessage(error, intl)}
|
value={value}
|
||||||
allowCustomValues
|
displayValue={value}
|
||||||
name={name || "giftCardTag"}
|
choices={choices}
|
||||||
label={`${intl.formatMessage(
|
fetchChoices={search}
|
||||||
messages.placeholder
|
onChange={change}
|
||||||
)} *${intl.formatMessage(commonMessages.optionalField)}`}
|
onFetchMore={loadMore}
|
||||||
data-test-id="gift-card-tag-select-field"
|
/>
|
||||||
value={value}
|
|
||||||
displayValue={value}
|
|
||||||
choices={choices}
|
|
||||||
fetchChoices={search}
|
|
||||||
onChange={change}
|
|
||||||
onFetchMore={loadMore}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import { defineMessages } from "react-intl";
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
export const giftCardTagInputMessages = defineMessages({
|
export const giftCardTagInputMessages = defineMessages({
|
||||||
label: {
|
|
||||||
defaultMessage: "Card Tag",
|
|
||||||
description: "GiftCardTagInput tag label"
|
|
||||||
},
|
|
||||||
placeholder: {
|
placeholder: {
|
||||||
defaultMessage: "Tag",
|
defaultMessage: "Tag",
|
||||||
description: "GiftCardTagInput tag placeholder"
|
description: "GiftCardTagInput tag placeholder"
|
||||||
|
|
|
@ -44,6 +44,7 @@ export function mapNodeToChoice<
|
||||||
T extends ExtendedNode | Node,
|
T extends ExtendedNode | Node,
|
||||||
K extends ChoiceValue
|
K extends ChoiceValue
|
||||||
>(nodes: T[], getterFn: (node: T) => K): Array<SingleAutocompleteChoiceType<K>>;
|
>(nodes: T[], getterFn: (node: T) => K): Array<SingleAutocompleteChoiceType<K>>;
|
||||||
|
|
||||||
export function mapNodeToChoice<T extends ExtendedNode>(
|
export function mapNodeToChoice<T extends ExtendedNode>(
|
||||||
nodes: T[],
|
nodes: T[],
|
||||||
getterFn?: (node: T) => any
|
getterFn?: (node: T) => any
|
||||||
|
|
Loading…
Reference in a new issue