Support staff only voucher (#1174)

* Support staff only voucher

* Trigger CI

* Update messages

* Update changelog
This commit is contained in:
Dawid Tarasiuk 2021-06-21 11:02:17 +02:00 committed by GitHub
parent a0dce99b5d
commit 4056ac395b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 264 additions and 29 deletions

View file

@ -51,6 +51,7 @@ All notable, unreleased changes to this project will be documented in this file.
- Paginate attribute values in filters - #1152 by @orzechdev
- Fix attribute values input display - #1156 by @orzechdev
- Fix product type translations - #1163 by @orzechdev
- Support staff only voucher - #1174 by @orzechdev
# 2.11.1

View file

@ -3019,21 +3019,26 @@
"context": "voucher code, button",
"string": "Generate Code"
},
"src_dot_discounts_dot_components_dot_VoucherLimits_dot_2215544659": {
"string": "Limit number of times this discount can be used in total"
},
"src_dot_discounts_dot_components_dot_VoucherLimits_dot_3459612469": {
"src_dot_discounts_dot_components_dot_VoucherLimits_dot_applyOncePerCustomer": {
"context": "limit voucher",
"string": "Limit to one use per customer"
},
"src_dot_discounts_dot_components_dot_VoucherLimits_dot_3751756157": {
"src_dot_discounts_dot_components_dot_VoucherLimits_dot_hasUsageLimit": {
"context": "limit voucher",
"string": "Limit number of times this discount can be used in total"
},
"src_dot_discounts_dot_components_dot_VoucherLimits_dot_onlyForStaff": {
"context": "limit voucher",
"string": "Limit to staff only"
},
"src_dot_discounts_dot_components_dot_VoucherLimits_dot_usageLimit": {
"context": "limit voucher",
"string": "Limit of Uses"
},
"src_dot_discounts_dot_components_dot_VoucherLimits_dot_usageLimitsTitle": {
"context": "voucher usage limit, header",
"string": "Usage Limit"
},
"src_dot_discounts_dot_components_dot_VoucherLimits_dot_557552777": {
"context": "voucher",
"string": "Limit of Uses"
},
"src_dot_discounts_dot_components_dot_VoucherListPage_dot_1112241061": {
"context": "tab name",
"string": "All Vouchers"

View file

@ -1914,6 +1914,7 @@ type ExportError {
}
enum ExportErrorCode {
GRAPHQL_ERROR
INVALID
NOT_FOUND
REQUIRED
@ -4106,7 +4107,7 @@ type Product implements Node & ObjectWithMetadata {
taxType: TaxType
attributes: [SelectedAttribute!]!
channelListings: [ProductChannelListing!]
mediaById(id: ID): ProductMedia!
mediaById(id: ID): ProductMedia
imageById(id: ID): ProductImage @deprecated(reason: "Will be removed in Saleor 4.0. Use the `mediaById` field instead.")
variants: [ProductVariant]
media: [ProductMedia!]
@ -5757,6 +5758,7 @@ type Voucher implements Node {
endDate: DateTime
applyOncePerOrder: Boolean!
applyOncePerCustomer: Boolean!
onlyForStaff: Boolean!
discountValueType: DiscountValueTypeEnum!
minCheckoutItemsQuantity: Int
categories(before: String, after: String, first: Int, last: Int): CategoryCountableConnection
@ -5858,6 +5860,7 @@ input VoucherInput {
countries: [String]
applyOncePerOrder: Boolean
applyOncePerCustomer: Boolean
onlyForStaff: Boolean
usageLimit: Int
}

View file

@ -30,6 +30,7 @@ import VoucherValue from "../VoucherValue";
export interface FormData {
applyOncePerCustomer: boolean;
applyOncePerOrder: boolean;
onlyForStaff: boolean;
channelListings: ChannelVoucherData[];
code: string;
discountType: DiscountTypeEnum;
@ -76,6 +77,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
const initialForm: FormData = {
applyOncePerCustomer: false,
applyOncePerOrder: false,
onlyForStaff: false,
channelListings,
code: "",
discountType: DiscountTypeEnum.VALUE_FIXED,

View file

@ -58,6 +58,7 @@ export function voucherDetailsPageTab(tab: string): VoucherDetailsPageTab {
export interface VoucherDetailsPageFormData {
applyOncePerCustomer: boolean;
applyOncePerOrder: boolean;
onlyForStaff: boolean;
channelListings: ChannelVoucherData[];
code: string;
discountType: DiscountTypeEnum;
@ -170,6 +171,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
const initialForm: VoucherDetailsPageFormData = {
applyOncePerCustomer: voucher?.applyOncePerCustomer || false,
applyOncePerOrder: voucher?.applyOncePerOrder || false,
onlyForStaff: voucher?.onlyForStaff || false,
channelListings,
code: voucher?.code || "",
discountType,

View file

@ -8,6 +8,7 @@ import React from "react";
import { useIntl } from "react-intl";
import { VoucherDetailsPageFormData } from "../VoucherDetailsPage";
import messages from "./messages";
interface VoucherLimitsProps {
data: VoucherDetailsPageFormData;
@ -28,19 +29,11 @@ const VoucherLimits = ({
return (
<Card>
<CardTitle
title={intl.formatMessage({
defaultMessage: "Usage Limit",
description: "voucher usage limit, header"
})}
/>
<CardTitle title={intl.formatMessage(messages.usageLimitsTitle)} />
<CardContent>
<ControlledCheckbox
checked={data.hasUsageLimit}
label={intl.formatMessage({
defaultMessage:
"Limit number of times this discount can be used in total"
})}
label={intl.formatMessage(messages.hasUsageLimit)}
name={"hasUsageLimit" as keyof VoucherDetailsPageFormData}
onChange={onChange}
/>
@ -49,10 +42,7 @@ const VoucherLimits = ({
disabled={disabled}
error={!!formErrors.usageLimit}
helperText={getDiscountErrorMessage(formErrors.usageLimit, intl)}
label={intl.formatMessage({
defaultMessage: "Limit of Uses",
description: "voucher"
})}
label={intl.formatMessage(messages.usageLimit)}
name={"usageLimit" as keyof VoucherDetailsPageFormData}
value={data.usageLimit}
onChange={onChange}
@ -65,13 +55,16 @@ const VoucherLimits = ({
)}
<ControlledCheckbox
checked={data.applyOncePerCustomer}
label={intl.formatMessage({
defaultMessage: "Limit to one use per customer",
description: "limit voucher"
})}
label={intl.formatMessage(messages.applyOncePerCustomer)}
name={"applyOncePerCustomer" as keyof VoucherDetailsPageFormData}
onChange={onChange}
/>
<ControlledCheckbox
checked={data.onlyForStaff}
label={intl.formatMessage(messages.onlyForStaff)}
name={"onlyForStaff" as keyof VoucherDetailsPageFormData}
onChange={onChange}
/>
</CardContent>
</Card>
);

View file

@ -0,0 +1,24 @@
import { defineMessages } from "react-intl";
export default defineMessages({
usageLimitsTitle: {
defaultMessage: "Usage Limit",
description: "voucher usage limit, header"
},
hasUsageLimit: {
defaultMessage: "Limit number of times this discount can be used in total",
description: "limit voucher"
},
usageLimit: {
defaultMessage: "Limit of Uses",
description: "limit voucher"
},
applyOncePerCustomer: {
defaultMessage: "Limit to one use per customer",
description: "limit voucher"
},
onlyForStaff: {
defaultMessage: "Limit to staff only",
description: "limit voucher"
}
});

View file

@ -416,6 +416,7 @@ export const voucherDetails: VoucherDetails_voucher = {
__typename: "Voucher",
applyOncePerCustomer: false,
applyOncePerOrder: false,
onlyForStaff: false,
categories: {
__typename: "CategoryCountableConnection",
edges: [],

View file

@ -180,6 +180,7 @@ export interface VoucherCataloguesAdd_voucherCataloguesAdd_voucher {
used: number;
applyOncePerOrder: boolean;
applyOncePerCustomer: boolean;
onlyForStaff: boolean;
products: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_products | null;
collections: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_collections | null;
categories: VoucherCataloguesAdd_voucherCataloguesAdd_voucher_categories | null;

View file

@ -180,6 +180,7 @@ export interface VoucherCataloguesRemove_voucherCataloguesRemove_voucher {
used: number;
applyOncePerOrder: boolean;
applyOncePerCustomer: boolean;
onlyForStaff: boolean;
products: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_products | null;
collections: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_collections | null;
categories: VoucherCataloguesRemove_voucherCataloguesRemove_voucher_categories | null;

View file

@ -173,6 +173,7 @@ export interface VoucherDetails_voucher {
used: number;
applyOncePerOrder: boolean;
applyOncePerCustomer: boolean;
onlyForStaff: boolean;
products: VoucherDetails_voucher_products | null;
collections: VoucherDetails_voucher_collections | null;
categories: VoucherDetails_voucher_categories | null;

View file

@ -29,6 +29,7 @@ export function createHandler(
input: {
applyOncePerCustomer: formData.applyOncePerCustomer,
applyOncePerOrder: formData.applyOncePerOrder,
onlyForStaff: formData.onlyForStaff,
code: formData.code,
discountValueType:
formData.discountType === DiscountTypeEnum.VALUE_PERCENTAGE

View file

@ -35,6 +35,7 @@ export function createUpdateHandler(
input: {
applyOncePerCustomer: formData.applyOncePerCustomer,
applyOncePerOrder: formData.applyOncePerOrder,
onlyForStaff: formData.onlyForStaff,
discountValueType:
formData.discountType === DiscountTypeEnum.VALUE_PERCENTAGE
? DiscountValueTypeEnum.PERCENTAGE

View file

@ -126,6 +126,7 @@ export const voucherDetailsFragment = gql`
used
applyOncePerOrder
applyOncePerCustomer
onlyForStaff
products(after: $after, before: $before, first: $first, last: $last) {
edges {
node {

View file

@ -173,6 +173,7 @@ export interface VoucherDetailsFragment {
used: number;
applyOncePerOrder: boolean;
applyOncePerCustomer: boolean;
onlyForStaff: boolean;
products: VoucherDetailsFragment_products | null;
collections: VoucherDetailsFragment_collections | null;
categories: VoucherDetailsFragment_categories | null;

View file

@ -31,7 +31,7 @@ export interface ProductMediaById_product {
__typename: "Product";
id: string;
name: string;
mainImage: ProductMediaById_product_mainImage;
mainImage: ProductMediaById_product_mainImage | null;
media: ProductMediaById_product_media[] | null;
}

View file

@ -95798,6 +95798,45 @@ exports[`Storyshots Views / Discounts / Voucher create default 1`] = `
Limit to one use per customer
</span>
</label>
<label
class="MuiFormControlLabel-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
name="onlyForStaff"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
Limit to staff only
</span>
</label>
</div>
</div>
<div
@ -97225,6 +97264,45 @@ exports[`Storyshots Views / Discounts / Voucher create form errors 1`] = `
Limit to one use per customer
</span>
</label>
<label
class="MuiFormControlLabel-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
name="onlyForStaff"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
Limit to staff only
</span>
</label>
</div>
</div>
<div
@ -99285,6 +99363,45 @@ exports[`Storyshots Views / Discounts / Voucher details default 1`] = `
Limit to one use per customer
</span>
</label>
<label
class="MuiFormControlLabel-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
name="onlyForStaff"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
Limit to staff only
</span>
</label>
</div>
</div>
<div
@ -101495,6 +101612,45 @@ exports[`Storyshots Views / Discounts / Voucher details form errors 1`] = `
Limit to one use per customer
</span>
</label>
<label
class="MuiFormControlLabel-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
name="onlyForStaff"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
Limit to staff only
</span>
</label>
</div>
</div>
<div
@ -103268,6 +103424,45 @@ exports[`Storyshots Views / Discounts / Voucher details loading 1`] = `
Limit to one use per customer
</span>
</label>
<label
class="MuiFormControlLabel-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id"
data-indeterminate="false"
name="onlyForStaff"
type="checkbox"
/>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id"
focusable="false"
viewBox="0 0 24 24"
>
<rect
fill="none"
height="14"
stroke="currentColor"
width="14"
x="5"
y="5"
/>
</svg>
</span>
</span>
<span
class="MuiTypography-root-id MuiFormControlLabel-label-id MuiTypography-body1-id"
>
Limit to staff only
</span>
</label>
</div>
</div>
<div

View file

@ -440,6 +440,7 @@ export enum DiscountValueTypeEnum {
}
export enum ExportErrorCode {
GRAPHQL_ERROR = "GRAPHQL_ERROR",
INVALID = "INVALID",
NOT_FOUND = "NOT_FOUND",
REQUIRED = "REQUIRED",
@ -1978,6 +1979,7 @@ export interface VoucherInput {
countries?: (string | null)[] | null;
applyOncePerOrder?: boolean | null;
applyOncePerCustomer?: boolean | null;
onlyForStaff?: boolean | null;
usageLimit?: number | null;
}