diff --git a/CHANGELOG.md b/CHANGELOG.md index 14098054e..f5f6cd713 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index b2ebccf9b..ca7378749 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -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" diff --git a/schema.graphql b/schema.graphql index fa3f88d5e..0ec911388 100644 --- a/schema.graphql +++ b/schema.graphql @@ -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 } diff --git a/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx b/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx index 8e24ee24e..3f88d51d7 100644 --- a/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx +++ b/src/discounts/components/VoucherCreatePage/VoucherCreatePage.tsx @@ -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 = ({ const initialForm: FormData = { applyOncePerCustomer: false, applyOncePerOrder: false, + onlyForStaff: false, channelListings, code: "", discountType: DiscountTypeEnum.VALUE_FIXED, diff --git a/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx b/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx index 5f2fbc6fd..4f3f65ecf 100644 --- a/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx +++ b/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.tsx @@ -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 = ({ const initialForm: VoucherDetailsPageFormData = { applyOncePerCustomer: voucher?.applyOncePerCustomer || false, applyOncePerOrder: voucher?.applyOncePerOrder || false, + onlyForStaff: voucher?.onlyForStaff || false, channelListings, code: voucher?.code || "", discountType, diff --git a/src/discounts/components/VoucherLimits/VoucherLimits.tsx b/src/discounts/components/VoucherLimits/VoucherLimits.tsx index 1b19433cf..fd6afc9c8 100644 --- a/src/discounts/components/VoucherLimits/VoucherLimits.tsx +++ b/src/discounts/components/VoucherLimits/VoucherLimits.tsx @@ -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 ( - + @@ -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 = ({ )} + ); diff --git a/src/discounts/components/VoucherLimits/messages.ts b/src/discounts/components/VoucherLimits/messages.ts new file mode 100644 index 000000000..f58ccd274 --- /dev/null +++ b/src/discounts/components/VoucherLimits/messages.ts @@ -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" + } +}); diff --git a/src/discounts/fixtures.ts b/src/discounts/fixtures.ts index 82af48219..e49d93c6d 100644 --- a/src/discounts/fixtures.ts +++ b/src/discounts/fixtures.ts @@ -416,6 +416,7 @@ export const voucherDetails: VoucherDetails_voucher = { __typename: "Voucher", applyOncePerCustomer: false, applyOncePerOrder: false, + onlyForStaff: false, categories: { __typename: "CategoryCountableConnection", edges: [], diff --git a/src/discounts/types/VoucherCataloguesAdd.ts b/src/discounts/types/VoucherCataloguesAdd.ts index 2c3fc5c48..adc42177e 100644 --- a/src/discounts/types/VoucherCataloguesAdd.ts +++ b/src/discounts/types/VoucherCataloguesAdd.ts @@ -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; diff --git a/src/discounts/types/VoucherCataloguesRemove.ts b/src/discounts/types/VoucherCataloguesRemove.ts index 05b2a5b7e..7479dbabf 100644 --- a/src/discounts/types/VoucherCataloguesRemove.ts +++ b/src/discounts/types/VoucherCataloguesRemove.ts @@ -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; diff --git a/src/discounts/types/VoucherDetails.ts b/src/discounts/types/VoucherDetails.ts index c2020074a..86275d008 100644 --- a/src/discounts/types/VoucherDetails.ts +++ b/src/discounts/types/VoucherDetails.ts @@ -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; diff --git a/src/discounts/views/VoucherCreate/handlers.ts b/src/discounts/views/VoucherCreate/handlers.ts index b1c6086b7..9e0573838 100644 --- a/src/discounts/views/VoucherCreate/handlers.ts +++ b/src/discounts/views/VoucherCreate/handlers.ts @@ -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 diff --git a/src/discounts/views/VoucherDetails/handlers.ts b/src/discounts/views/VoucherDetails/handlers.ts index f64e05990..9244cafda 100644 --- a/src/discounts/views/VoucherDetails/handlers.ts +++ b/src/discounts/views/VoucherDetails/handlers.ts @@ -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 diff --git a/src/fragments/discounts.ts b/src/fragments/discounts.ts index 0ef48f482..491954fd4 100644 --- a/src/fragments/discounts.ts +++ b/src/fragments/discounts.ts @@ -126,6 +126,7 @@ export const voucherDetailsFragment = gql` used applyOncePerOrder applyOncePerCustomer + onlyForStaff products(after: $after, before: $before, first: $first, last: $last) { edges { node { diff --git a/src/fragments/types/VoucherDetailsFragment.ts b/src/fragments/types/VoucherDetailsFragment.ts index 2afdb3d15..3a09ccdf0 100644 --- a/src/fragments/types/VoucherDetailsFragment.ts +++ b/src/fragments/types/VoucherDetailsFragment.ts @@ -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; diff --git a/src/products/types/ProductMediaById.ts b/src/products/types/ProductMediaById.ts index 33639570c..ddc1136cb 100644 --- a/src/products/types/ProductMediaById.ts +++ b/src/products/types/ProductMediaById.ts @@ -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; } diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index ebb2c2533..c45aac27f 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -95798,6 +95798,45 @@ exports[`Storyshots Views / Discounts / Voucher create default 1`] = ` Limit to one use per customer +
+
+
+
+