Gift cards post mvp (#1632)
* Add gift bulk create (#1490) * Add gift card bulk create dialog WIP * Update schema, add gift card bulk create mutation and types * Add gift card bulk create modal and mutation * Fix types and update messages * Refactor gift card bulk create * Add closing gift card bulk create dialog after success * Change gift card list closeDialog prop name to onClose * Review fixes * Review fixes * Add error message to invalid expiryDate (#1518) * Add error message to invalid expiryDate * Add default messages * Replace filter with some * Add gift card export (#1499) * wip * Add exporting gift cards * Update messages * Fix types * Review fixes * Review fixes * Refactor passing messages to export settings component * Refactor * Update messages * Gift card customer page (#1520) * Add gift cards card to customer page (#1456) * WIP * WIP * Extract activate/deactivate logic to a hook * add optional side action * Add query for customer's gift cards * Add component for giftcard status chip * Graphql run types * Add gift card card to customer page * Fix status chip header * Revert style change * Unify status chip logic * Fix naming scheme * Add currentOpts to act/deactivate gift cards hook * Add queries to refetch prop * Simplify gift card list component * Fix order status chip * Extract messages to separate file * Remove unused lines of code * Tests and messages * Fix card list rendering * Type fix * Code review fixes * Review changes * Scripts * Change variable name * Fix formatted message * Check if giftcards exist before rendering collection * Add loading button to CardMenu component (#1476) * WIP * WIP * Add gift card card to customer page * Fix status chip header * Fix naming scheme * Add currentOpts to act/deactivate gift cards hook * Remove unused lines of code * Revert style change * Tests and messages * Fix card list rendering * Type fix * Code review fixes * Review changes * Scripts * Add loading animation to card menu buttons * Added default messages * Change conditional prop checking to filtering * Issue gift card in customer page (#1468) * WIP * WIP * Replace typed query with make query * Add customer details context to customer page * Add context to customer gift cards * Disable customer select when initial customer is present * Pass initial customer to create gift card form * Fixes after cherry-pick * Code cleanup * Remove getInitialData function * Remove unused package * Remove new line * Post-rebase fixes * Code cleanup & extract messages * Remove unused code * Create customer details hook * Minor fixes * Update default messages * Update gift card types * Type fixes * Change directory of useCustomerDetails hook * CR Fixes * Update tests * Make PageTitleWithStatusChip use ExtendedPageHeader * Update tests * Update hook name * Post-rebase fixes * Eslint fix * Fix scrollbar appearing in menu issue (#1539) * Change displayCode to last4CodeChars (#1573) * Add filtered redirect to gift card page from customer details (#1556) * Limit number of channel list items (#1607) * Add max height to single select field menu items container * Add storybook case * Update stories tests * Fix gift card product changing to preorder on save issue (#1583) * Variant preorder fix * Global threshold input should be optional * update snapshot * Add displaying logic gift cards list toolbar (#1617) * add displaying logic for gift card toolbar * Logic fix * Handle bulk export after creation (#1544) * Add gift bulk create (#1490) * Add gift card bulk create dialog WIP * Update schema, add gift card bulk create mutation and types * Add gift card bulk create modal and mutation * Fix types and update messages * Refactor gift card bulk create * Add closing gift card bulk create dialog after success * Change gift card list closeDialog prop name to onClose * Review fixes * Review fixes * Add gift card export (#1499) * wip * Add exporting gift cards * Update messages * Fix types * Review fixes * Review fixes * Refactor passing messages to export settings component * Refactor * Update messages * Handle export after bulk gift card creation * Add default messages * Create an util function to get correct input for export * Update component's name * Change modal's title * Update messages Co-authored-by: Magdalena Markusik <magdalena@markusik.com> * Gift Card List item number change doesn't refetch fix (#1643) * Fix number of rows change not refetching list * Add pagination reset * Update descriptions for gift card messages to be more descriptive (#1648) * Gift card history timeline (#1597) * Update queries and mutations * Allow title to be a react node * Show user name if it exists in data object * Update types * Refresh queries on note add * Add gift card history * type fix * Update messages * Fix timeline note * Add event fragment to form update result * Update types * Fix typo * Update messages * Disable input if gift card is expired * Remove unused imports * CR Fixes * Change messages location * Change message to include user in order * Allow adding notes to expired gift cards * Fix disabled input showing dropdown issue (#1636) * On click is disabled when component is disabled * update tests * Order filtering for gift cards in Order List View (#1628) * Add gift card order filter * Add gift card filter card in orders view * Bump macaw version * Update messages * Update tests * Code review changes * update messages * Change info card message to use only one message * Fix order gift card filter * Gift card filter in product list view (#1621) * Add GiftCard or Normal filter in Product List View * Fix tests * Fix type check * Don't filter if query param is not in enum * Update messages * Update tests * Code cleanup * Add default messages * Pass intl rather than initialise it in util * Post-rebase fixes * Change product type details messages (#1642) * Update product type gift card options messages * update tests * Add sorting to gift card list (#1569) * Update queries and types for sorting * Add optional handleError method to makeQuery * Add sorting to gift card list * Sorting hook uses useGiftCardList hook * Convert to boolean * Add default sorting field * format fix * Add expiry error handling for issuing gift cards (#1634) * Add expiry error handling for issuing gift cards * Add expiry error message to gift card bulk issue * Update Gift Card tag queries to utilise multiple tags (#1685) * Change displayCode to last4CodeChars (#1573) * Update types * WIP * Update gift card forms to utilise multiple tags * Code cleanup * Update gift card event types * Fixes * Change column with no click handler behaviour * Remove an ability to sort by tags * Remove unused code * Update tests * Update timeline events * Update messages * change array reduce to join * Add Y scroll to dialog content * Bulk create Y scroll fix * Endless loading fix (#1732) * Order filtering for gift cards in Order List View (#1628) * Add gift card order filter * Add gift card filter card in orders view * Bump macaw version * Update messages * Update tests * Code review changes * update messages * Change info card message to use only one message * Fix order gift card filter * Wip * Extract dialog component outside of gift card create * Update component's name * Extract dialog component outside of export component to provider * Update tests * Various gift card bugs fixes (#1749) * Change currency to options field * Fix hover and font size * Fix gift card list width * Fix bulk delete dialog * Allow balance to be sorted only when currency is filtered * Sorting by balance after removing currency filter defualts to usedBy * Fix trash icon * Add filter dependency * Fix single deletion with bulk * Update tests * Refactor Links used in Gift Cards * Fix export dialog (#1791) Co-authored-by: Magdalena Markusik <magdalena@markusik.com>
This commit is contained in:
parent
53a391eebc
commit
8f9c1ba19e
172 changed files with 7497 additions and 2105 deletions
|
@ -131,6 +131,9 @@
|
|||
{
|
||||
"name": "GiftCardEvent"
|
||||
},
|
||||
{
|
||||
"name": "GiftCardTag"
|
||||
},
|
||||
{
|
||||
"name": "Group"
|
||||
},
|
||||
|
|
|
@ -1966,6 +1966,10 @@
|
|||
"context": "unassign multiple attributes from item",
|
||||
"string": "{counter,plural,one{Are you sure you want to unassign this attribute from {itemTypeName}?} other{Are you sure you want to unassign {attributeQuantity} attributes from {itemTypeName}?}}"
|
||||
},
|
||||
"src_dot_components_dot_CardMenu_dot_cardMenuItemLoading": {
|
||||
"context": "menu item loading",
|
||||
"string": "working..."
|
||||
},
|
||||
"src_dot_components_dot_ChannelsAvailabilityCard_dot_3326160357": {
|
||||
"context": "section header",
|
||||
"string": "Availability"
|
||||
|
@ -3509,215 +3513,336 @@
|
|||
"context": "gift cards section name",
|
||||
"string": "Gift Cards"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardBulkCreateDialog_dot_createdSuccessAlertDescription": {
|
||||
"context": "bulk issue gift cards success alert description",
|
||||
"string": "Requested {cardsAmount} were successfully issued"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardBulkCreateDialog_dot_createdSuccessAlertTitle": {
|
||||
"context": "bulk issue gift cards success alert title",
|
||||
"string": "Gift Cards Issued"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardBulkCreateDialog_dot_title": {
|
||||
"context": "bulk issue gift cards dialog title",
|
||||
"string": "Bulk Issue Gift Cards"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_GiftCardCreateExpirySelect_dot_expiryDateLabel": {
|
||||
"context": "GiftCarUpdateDetailsExpirySection expiry date label",
|
||||
"context": "expiry date label",
|
||||
"string": "Exact date"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_GiftCardCreateExpirySelect_dot_expiryOnLabel": {
|
||||
"context": "GiftCarUpdateDetailsExpirySection expiry on label",
|
||||
"context": "expires on label",
|
||||
"string": "Will expire on:"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_GiftCardCreateExpirySelect_dot_expiryPeriodLabel": {
|
||||
"context": "GiftCarUpdateDetailsExpirySection expiry period label",
|
||||
"context": "expires in label",
|
||||
"string": "Expires in"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_GiftCardCreateExpirySelect_dot_expirySelectedLabel": {
|
||||
"context": "GiftCarUpdateDetailsExpirySection expiry selected label",
|
||||
"context": "set expiry date selected label",
|
||||
"string": "Set gift card expiry date"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_amountLabel": {
|
||||
"context": "GiftCardCreateDialog amount label",
|
||||
"context": "money amount input label",
|
||||
"string": "Enter amount"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_bulkCreateExplanation": {
|
||||
"context": "gift card bulk create modal bottom explanation",
|
||||
"string": "After creation Saleor will create a list of gift card codes that you will be able to download. "
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_bulkCreateIssuedAccept": {
|
||||
"context": "gift card bulk create success dialog accept button",
|
||||
"string": "Ok"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_bulkCreateIssuedExplanation": {
|
||||
"context": "gift card bulk create success dialog content",
|
||||
"string": "We have issued all of your requested gift cards. You can download the list of new gift cards using the button below."
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_bulkCreateIssuedExportToEmail": {
|
||||
"context": "gift card bulk create success dialog export button",
|
||||
"string": "Export To Email"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_bulkCreateIssuedTitle": {
|
||||
"context": "gift card bulk create success dialog title",
|
||||
"string": "Bulk Issue Gift Cards"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_copiedToClipboardTitle": {
|
||||
"context": "GiftCardCreateDialog copied to clipboard title",
|
||||
"context": "copied to clipboard alert title",
|
||||
"string": "Copied to clipboard"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_copyCodeLabel": {
|
||||
"context": "GiftCardCreateDialog copy code label",
|
||||
"context": "copy code button label",
|
||||
"string": "Copy code"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_createdGiftCardLabel": {
|
||||
"context": "GiftCardCreateDialog created gift card label",
|
||||
"context": "created gift card code label",
|
||||
"string": "This is the code of a created gift card:"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_createdSuccessAlertTitle": {
|
||||
"context": "GiftCardCreateDialog createdSuccessAlertTitle",
|
||||
"context": "successfully created gift card alert title",
|
||||
"string": "Successfully created gift card"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_customerLabel": {
|
||||
"context": "GiftCardCreateDialog customer label",
|
||||
"context": "customer input label",
|
||||
"string": "Customer"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_giftCardsAmountLabel": {
|
||||
"context": "issued cards amount label",
|
||||
"string": "Cards Issued"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_issueButtonLabel": {
|
||||
"context": "GiftCardCreateDialog issue button label",
|
||||
"context": "issue gift card button label",
|
||||
"string": "Issue"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_noteLabel": {
|
||||
"context": "GiftCardCreateDialog note label",
|
||||
"context": "note input label",
|
||||
"string": "Note"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_noteSubtitle": {
|
||||
"context": "GiftCardCreateDialog note subtitle",
|
||||
"context": "note input subtitle",
|
||||
"string": "Why was this gift card issued. This note will not be shown to the customer. Note will be stored in gift card history"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_requiresActivationCaption": {
|
||||
"context": "GiftCarUpdateDetailsExpirySection requires activation caption",
|
||||
"context": "requires activation checkbox caption",
|
||||
"string": "All issued cards require activation by staff before use."
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_requiresActivationLabel": {
|
||||
"context": "GiftCarUpdateDetailsExpirySection requires activation label",
|
||||
"context": "requires activation checkbox label",
|
||||
"string": "Requires activation"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_title": {
|
||||
"context": "GiftCardCreateDialog title",
|
||||
"context": "issue gift card dialog title",
|
||||
"string": "Issue gift card"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardExportDialogContent_dot_2086397658": {
|
||||
"context": "export all items to csv file",
|
||||
"string": "All gift cards ({number})"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardExportDialogContent_dot_701638571": {
|
||||
"context": "export selected items to csv file",
|
||||
"string": "Selected giftCards ({number})"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardExportDialogContent_dot_confirmButtonLabel": {
|
||||
"context": "gift card export dialog confirm button label",
|
||||
"string": "Export codes"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardExportDialogContent_dot_exportNote": {
|
||||
"context": "note on export gift cards",
|
||||
"string": "Note: Only active and not used gift cards will be expored"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardExportDialogContent_dot_exportTypeLabel": {
|
||||
"context": "gift card export type label",
|
||||
"string": "gift cards"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardExportDialogContent_dot_successAlertDescription": {
|
||||
"context": "gift card export success alert description",
|
||||
"string": "We are currently exporting your gift card codes. As soon as your file is available it will be sent to your email address"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardExportDialogContent_dot_successAlertTitle": {
|
||||
"context": "gift card export csv success alert title",
|
||||
"string": "Exporting CSV"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardExportDialogContent_dot_title": {
|
||||
"context": "gift card export dialog title",
|
||||
"string": "Export Gift Card Codes"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardSettings_dot_GiftCardExpirySettingsCard_dot_expiryDateSectionDescription": {
|
||||
"context": "expiry date selection info message",
|
||||
"string": "You can set gift cards to expire after a certain time after their purchase. Remember that in some countries, gift cards expiry is prohibited by law."
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardSettings_dot_GiftCardExpirySettingsCard_dot_expiryDateTitle": {
|
||||
"context": "section header",
|
||||
"context": "expiry date section header",
|
||||
"string": "Expiry date"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardSettings_dot_title": {
|
||||
"context": "header",
|
||||
"context": "gift card settings header",
|
||||
"string": "Gift Cards Settings"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_giftCardActivated": {
|
||||
"context": "gift card history message",
|
||||
"string": "Gift card was activated by {activatedBy}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_giftCardBalanceReset": {
|
||||
"context": "gift card history message",
|
||||
"string": "Gift card balance was reset by {resetBy}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_giftCardBought": {
|
||||
"context": "gift card history message",
|
||||
"string": "Gift card was bought in order {orderNumber}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_giftCardDeactivated": {
|
||||
"context": "gift card history message",
|
||||
"string": "Gift card was deactivated by {deactivatedBy}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_giftCardExpiryDateUpdate": {
|
||||
"context": "gift card history message",
|
||||
"string": "Gift card expiry date was updated by {expiryUpdatedBy}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_giftCardIssued": {
|
||||
"context": "dsc",
|
||||
"string": "Gift card was issued by {issuedBy}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_giftCardResent": {
|
||||
"context": "gift card history message",
|
||||
"string": "Gift card was resent"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_giftCardSentToCustomer": {
|
||||
"context": "gift card history message",
|
||||
"string": "Gift card was sent to customer"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_giftCardTagsUpdated": {
|
||||
"context": "gift card history message",
|
||||
"string": "Gift card tags were updated"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_giftCardUsedInOrder": {
|
||||
"context": "gift card history message",
|
||||
"string": "Gift card was used as a payment method on order {orderLink} <buyer>by</buyer>"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_historyHeaderTitle": {
|
||||
"context": "section header title",
|
||||
"string": "Gift Card Timeline"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_noteAddError": {
|
||||
"context": "notifier message",
|
||||
"string": "There was an error adding a note"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardHistory_dot_noteAddedSuccessfully": {
|
||||
"context": "notifier message",
|
||||
"string": "Note was added sucessfully"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardResendCodeDialog_dot_consentCheckboxLabel": {
|
||||
"context": "GiftCardResendCodeDialog consentCheckboxLabel",
|
||||
"context": "consent to send gift card to different address checkbox label",
|
||||
"string": "Yes, I want to send gift card to different address"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardResendCodeDialog_dot_description": {
|
||||
"context": "GiftCardResendCodeDialog description",
|
||||
"context": "resend code to customer description",
|
||||
"string": "Gift Card Code will be resent to email provided during checkout. You can provide a different email address if you want to:"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardResendCodeDialog_dot_emailInputPlaceholder": {
|
||||
"context": "GiftCardResendCodeDialog emailInputPlaceholder",
|
||||
"context": "provided email input placeholder",
|
||||
"string": "Provided email address"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardResendCodeDialog_dot_sendToChannelSelectLabel": {
|
||||
"context": "ChannelPickerSelectField sendToChannelLabel",
|
||||
"context": "send to channel select label",
|
||||
"string": "Send to channel"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardResendCodeDialog_dot_submitButtonLabel": {
|
||||
"context": "GiftCardResendCodeDialog submitButtonLabel",
|
||||
"context": "resend button label",
|
||||
"string": "Resend"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardResendCodeDialog_dot_successResendAlertText": {
|
||||
"context": "GiftCardResendCodeDialog successResendAlertText",
|
||||
"context": "resent code success message",
|
||||
"string": "Successfully resent code to customer!"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardResendCodeDialog_dot_title": {
|
||||
"context": "GiftCardResendCodeDialog title",
|
||||
"context": "resend code to customer title",
|
||||
"string": "Resend code to customer"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateBalanceDialog_dot_changeButtonLabel": {
|
||||
"context": "GiftCardUpdateDetailsCard set balance dialog change button label",
|
||||
"context": "change button label",
|
||||
"string": "Change"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateBalanceDialog_dot_subtitle": {
|
||||
"context": "GiftCardUpdateDetailsCard set balance dialog subtitle",
|
||||
"context": "set balance dialog subtitle",
|
||||
"string": "What would you like to set cards balance to. When you change the balance both values will be changed"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateBalanceDialog_dot_title": {
|
||||
"context": "GiftCardUpdateDetailsCard set balance button label",
|
||||
"context": "set balance dialog title label",
|
||||
"string": "Set balance"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateBalanceDialog_dot_updatedSuccessAlertTitle": {
|
||||
"context": "GiftCardUpdateDetailsCard update success alert title",
|
||||
"context": "card update success alert title",
|
||||
"string": "Successfully updated card balance"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateDetailsCard_dot_cardBalanceLabel": {
|
||||
"context": "GiftCardUpdateDetailsCard card balance label",
|
||||
"context": "card balance label",
|
||||
"string": "Card Balance"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateDetailsCard_dot_setBalanceButtonLabel": {
|
||||
"context": "GiftCardUpdateDetailsCard set balance button label",
|
||||
"context": "set balance button label",
|
||||
"string": "set balance"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateDetailsCard_dot_tagInputLabel": {
|
||||
"context": "GiftCardTagInput tag label",
|
||||
"context": "tag label",
|
||||
"string": "Card Tag"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateDetailsCard_dot_title": {
|
||||
"context": "GiftCardUpdateDetailsCard title",
|
||||
"context": "details title",
|
||||
"string": "Details"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateExpirySelect_dot_expiredOnLabel": {
|
||||
"context": "GiftCarUpdateDetailsExpirySection expired on label",
|
||||
"context": "expired on label",
|
||||
"string": "Expired on {date}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateExpirySelect_dot_expiryDateCheckboxLabel": {
|
||||
"context": "GiftCarUpdateDetailsExpirySection expiry date checkbox label",
|
||||
"context": "expiry date checkbox label",
|
||||
"string": "Gift card expires"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateExpirySelect_dot_expiryDateLabel": {
|
||||
"context": "GiftCarUpdateDetailsExpirySection expiry date label",
|
||||
"context": "expiration date label",
|
||||
"string": "Expiration date"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_boughtByLabel": {
|
||||
"context": "GiftCardUpdateInfoCard bought by label",
|
||||
"context": "bought by label",
|
||||
"string": "Bought by"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_creationLabel": {
|
||||
"context": "GiftCardUpdateInfoCard creation label",
|
||||
"context": "creation label",
|
||||
"string": "Creation"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_issuedByAppLabel": {
|
||||
"context": "GiftCardUpdateInfoCard issued by app label",
|
||||
"context": "issued by app label",
|
||||
"string": "Issued by app"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_issuedByLabel": {
|
||||
"context": "GiftCardUpdateInfoCard issued by label",
|
||||
"context": "issued by label",
|
||||
"string": "Issued by"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_orderNumberLabel": {
|
||||
"context": "GiftCardUpdateInfoCard order number label",
|
||||
"context": "order number label",
|
||||
"string": "Order number"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_productLabel": {
|
||||
"context": "GiftCardUpdateInfoCard product label",
|
||||
"context": "product label",
|
||||
"string": "Product bought to get gift card"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_title": {
|
||||
"context": "GiftCardUpdateInfoCard title",
|
||||
"context": "info card title",
|
||||
"string": "Card information"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_usedByLabel": {
|
||||
"context": "GiftCardUpdateInfoCard used by label",
|
||||
"context": "used by label",
|
||||
"string": "Used by"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_disabledStatusLabel": {
|
||||
"context": "giftCardUpdatePageHeader disabled status label",
|
||||
"context": "disabled status label",
|
||||
"string": "Disabled"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_expiredStatusLabel": {
|
||||
"context": "giftCardUpdatePageHeader expired status label",
|
||||
"context": "expired status label",
|
||||
"string": "Expired"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_resendButtonLabel": {
|
||||
"context": "giftCardUpdatePageHeader resendButtonLabel",
|
||||
"context": "resend code label",
|
||||
"string": "Resend code"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_successfullyDisabledTitle": {
|
||||
"context": "GiftCardEnableDisableSection disable success",
|
||||
"context": "success gift card disable message",
|
||||
"string": "Successfully disabled gift card"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_successfullyEnabledTitle": {
|
||||
"context": "GiftCardEnableDisableSection enable success",
|
||||
"context": "success gift card enable message",
|
||||
"string": "Successfully enabled gift card"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_notFound": {
|
||||
"context": "giftCardErrorMessages not found",
|
||||
"context": "gift card not found message",
|
||||
"string": "Couldn't find gift card"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardUpdate_dot_title": {
|
||||
"context": "GiftCardUpdateDetailsCard title",
|
||||
"context": "title",
|
||||
"string": "Details"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardListSearchAndFilters_dot_balanceAmount": {
|
||||
"context": "Filter balance amount error",
|
||||
"context": "balance amound missing error message",
|
||||
"string": "Balance amount is missing"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardListSearchAndFilters_dot_balanceAmountLabel": {
|
||||
|
@ -3725,7 +3850,7 @@
|
|||
"string": "Amount"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardListSearchAndFilters_dot_balanceCurrency": {
|
||||
"context": "Filter balance currency error",
|
||||
"context": "balance curreny missing error message",
|
||||
"string": "Balance currency is missing"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardListSearchAndFilters_dot_currencyLabel": {
|
||||
|
@ -3737,7 +3862,7 @@
|
|||
"string": "Current balance"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardListSearchAndFilters_dot_defaultTabLabel": {
|
||||
"context": "gift card default tab label",
|
||||
"context": "all gift cards label",
|
||||
"string": "All Gift Cards"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardListSearchAndFilters_dot_disabledOptionLabel": {
|
||||
|
@ -3757,7 +3882,7 @@
|
|||
"string": "Product"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardListSearchAndFilters_dot_searchPlaceholder": {
|
||||
"context": "gift card search placeholder",
|
||||
"context": "search gift card placeholder",
|
||||
"string": "Search Gift Cards, e.g {exampleGiftCardCode}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardListSearchAndFilters_dot_statusLabel": {
|
||||
|
@ -3772,136 +3897,172 @@
|
|||
"context": "used by filter label",
|
||||
"string": "Used by"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardsListOrderInfoCard_dot_giftCardOrderInfoMessage": {
|
||||
"context": "alert card message",
|
||||
"string": "Gift cards will appear after their order is fullfilled. <link>View Orders with Gift Cards</link>"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardsListTable_dot_GiftCardsListTableHeader_dot_deleteLabel": {
|
||||
"context": "bulk delete label",
|
||||
"string": "Delete"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardsListTable_dot_GiftCardsListTableHeader_dot_disableLabel": {
|
||||
"context": "GiftCardEnableDisableSection enable label",
|
||||
"context": "bulk disable label",
|
||||
"string": "Deactivate"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardsListTable_dot_GiftCardsListTableHeader_dot_enableLabel": {
|
||||
"context": "GiftCardEnableDisableSection enable label",
|
||||
"context": "bulk activate label",
|
||||
"string": "Activate"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardsListTable_dot_GiftCardsListTableHeader_dot_errorActivateAlertText": {
|
||||
"context": "GiftCardEnableDisableSection error activate alert text",
|
||||
"context": "error with activatation alert message",
|
||||
"string": "Error activating gift {count,plural,one{card} other{cards}}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardsListTable_dot_GiftCardsListTableHeader_dot_errorDeactivateAlertText": {
|
||||
"context": "GiftCardEnableDisableSection error activate alert text",
|
||||
"context": "error with deactivatation alert message",
|
||||
"string": "Errors deactivating gift {count,plural,one{card} other{cards}}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardsListTable_dot_GiftCardsListTableHeader_dot_successActivateAlertText": {
|
||||
"context": "GiftCardEnableDisableSection success activate alert text",
|
||||
"context": "success activate alert message",
|
||||
"string": "Successfully activated gift {count,plural,one{card} other{cards}}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_GiftCardsListTable_dot_GiftCardsListTableHeader_dot_successDeactivateAlertText": {
|
||||
"context": "GiftCardEnableDisableSection success activate alert text",
|
||||
"context": "success deactivate alert message",
|
||||
"string": "Successfully deactivated gift {count,plural,one{card} other{cards}}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_bulkIssue": {
|
||||
"context": "GiftCardsListHeader menu item settings",
|
||||
"context": "bulk issue menu item",
|
||||
"string": "Bulk Issue"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_codeEndingWithLabel": {
|
||||
"context": "GiftCardsListTable code ending with label",
|
||||
"string": "Code ending with {displayCode}"
|
||||
"context": "code ending with label",
|
||||
"string": "Code ending with {last4CodeChars}"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_createGiftCardProduct": {
|
||||
"context": "GiftCardsListHeader alert",
|
||||
"context": "create gift card product alert message",
|
||||
"string": "Create a gift card product"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_createGiftCardProductType": {
|
||||
"context": "GiftCardsListHeader alert",
|
||||
"context": "create gift card product type alert message",
|
||||
"string": "Create a gift card product type"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_exportCodes": {
|
||||
"context": "GiftCardsListHeader menu item settings",
|
||||
"context": "export card codes menu item",
|
||||
"string": "Export card codes"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardInvalidExpiryDateContent": {
|
||||
"context": "invalid date in expirydate field content",
|
||||
"string": "Gift Card with past expiration date cannot be created"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardInvalidExpiryDateHeader": {
|
||||
"context": "invalid date in expirydate field header",
|
||||
"string": "Incorrect date entered"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardProduct": {
|
||||
"context": "GiftCardsListHeader alert",
|
||||
"context": "gift card product message",
|
||||
"string": "gift card product"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardsTableColumnBalanceTitle": {
|
||||
"context": "GiftCardsListTable column title balance",
|
||||
"context": "column title balance",
|
||||
"string": "Balance"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardsTableColumnCustomerTitle": {
|
||||
"context": "GiftCardsListTable column title customer",
|
||||
"context": "column title used by/customer",
|
||||
"string": "Used by"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardsTableColumnGiftCardTitle": {
|
||||
"context": "GiftCardsListTable column title gift card",
|
||||
"context": "column title gift card",
|
||||
"string": "Gift Card"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardsTableColumnProductTitle": {
|
||||
"context": "GiftCardsListTable column title product",
|
||||
"context": "column title product",
|
||||
"string": "Product"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardsTableColumnTagTitle": {
|
||||
"context": "GiftCardsListTable column title tag",
|
||||
"context": "column title tag",
|
||||
"string": "Tag"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_issueButtonLabel": {
|
||||
"context": "GiftCardsListHeader issue button label",
|
||||
"context": "issue card button label",
|
||||
"string": "Issue card"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_noGiftCardsAlertTitle": {
|
||||
"context": "GiftCardsListHeader alert",
|
||||
"context": "no card defuned alert message",
|
||||
"string": "You haven’t defined a gift card product!"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_noGiftCardsFound": {
|
||||
"context": "GiftCardsListTable no cards found title",
|
||||
"context": "no cards found title message",
|
||||
"string": "No gift cards found"
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_noGiftCardsProductTypes": {
|
||||
"context": "GiftCardsListHeader alert",
|
||||
"context": "no gift card product types alert message",
|
||||
"string": "{createGiftCardProductType} to start selling gift cards in your store."
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_noGiftCardsProducts": {
|
||||
"context": "GiftCardsListHeader alert",
|
||||
"context": "no gift card products alert message",
|
||||
"string": "{createGiftCardProduct} to start selling gift cards in your store."
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_noGiftCardsProductsAndProductTypes": {
|
||||
"context": "GiftCardsListHeader alert",
|
||||
"context": "no gift card products and types alert message",
|
||||
"string": "{createGiftCardProductType} and {giftCardProduct} to start selling gift cards in your store."
|
||||
},
|
||||
"src_dot_giftCards_dot_GiftCardsList_dot_settings": {
|
||||
"context": "GiftCardsListHeader menu item settings",
|
||||
"context": "settings menu item",
|
||||
"string": "Settings"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardCustomerCard_dot_customerGiftCardsAbsentSubtitle": {
|
||||
"context": "customer gift cards card no cards subtitle",
|
||||
"string": "There are no gift cards assigned to this customer"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardCustomerCard_dot_customerGiftCardsCardTitle": {
|
||||
"context": "customer gift cards card title",
|
||||
"string": "Gift Cards"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardCustomerCard_dot_customerGiftCardsIssueNewCardButton": {
|
||||
"context": "customer gift cards card issue button",
|
||||
"string": "Issue new card"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardCustomerCard_dot_customerGiftCardsPresentSubtitle": {
|
||||
"context": "customer gift cards card subtitle",
|
||||
"string": "Only five newest gift cards are shown here"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardCustomerCard_dot_customerGiftCardsViewAllButton": {
|
||||
"context": "customer gift cards card view all button",
|
||||
"string": "View All"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardDeleteDialog_dot_consentLabel": {
|
||||
"context": "GiftCardDeleteDialog consent label",
|
||||
"context": "consent removal of gift cards with balance button label",
|
||||
"string": "{selectedItemsCount,plural,one{I am aware that I am removing a gift card with balance} other{I am aware that I am removing gift cards with balance}}"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardDeleteDialog_dot_defaultDescription": {
|
||||
"context": "GiftCardDeleteDialog default description",
|
||||
"context": "default gift card delete description",
|
||||
"string": "{selectedItemsCount,plural,one{Are you sure you want to delete this gift card?} other{Are you sure you want to delete {selectedItemsCount} giftCards?}}"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardDeleteDialog_dot_deleteSuccessAlertText": {
|
||||
"context": "GiftCardDeleteDialog success alert text",
|
||||
"context": "gift card removed success alert message",
|
||||
"string": "{selectedItemsCount,plural,one{Successfully deleted gift card} other{Successfully deleted gift cards}}"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardDeleteDialog_dot_title": {
|
||||
"context": "GiftCardDeleteDialog single title",
|
||||
"context": "single gift card title",
|
||||
"string": "{selectedItemsCount,plural,one{Delete Gift Card} other{Delete Gift Cards}}"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardDeleteDialog_dot_withBalanceDescription": {
|
||||
"context": "GiftCardDeleteDialog with balance description",
|
||||
"context": "delete gift cards with balance description",
|
||||
"string": "{selectedItemsCount,plural,one{The gift card you are about to delete has available balance. By deleting this card you may remove balance available to your customer.} other{You are about to delete gift cards with available balance. Are you sure you want to do that?}}"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardSendToCustomer_dot_channelSelectLabel": {
|
||||
"context": "GiftCardCreateDialog channel select label",
|
||||
"context": "channel select label",
|
||||
"string": "Channel"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardSendToCustomer_dot_customerChannelSubtitle": {
|
||||
"context": "GiftCardCreateDialog customer channel subtitle",
|
||||
"context": "selected customer channel subtitle",
|
||||
"string": "Customer will be sent the gift card code via this channels email address"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardSendToCustomer_dot_customerSubtitle": {
|
||||
"context": "GiftCardCreateDialog customer subtitle",
|
||||
"context": "selected customer gift card is sent to subtitle",
|
||||
"string": "Selected customer will be sent the generated gift card code. Someone else can redeem the gift card code. Gift card will be assigned to account which redeemed the code."
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardSendToCustomer_dot_sendToCustomerSelectedLabel": {
|
||||
"context": "GiftCardSendToCustomer send to customer selected label",
|
||||
"context": "send to customer selected label",
|
||||
"string": "Send gift card to customer"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardSettingsExpirySelect_dot_setExpirationPeriodDescription": {
|
||||
|
@ -3913,23 +4074,23 @@
|
|||
"string": "Set gift card expiration period"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_GiftCardTagInput_dot_placeholder": {
|
||||
"context": "GiftCardTagInput tag placeholder",
|
||||
"context": "input placeholder tag",
|
||||
"string": "Tag"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_TimePeriodField_dot_dayLabel": {
|
||||
"context": "TimePeriodTextWithSelectField day label",
|
||||
"context": "days after label",
|
||||
"string": "days after issue"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_TimePeriodField_dot_monthLabel": {
|
||||
"context": "TimePeriodTextWithSelectField month label",
|
||||
"context": "months after label",
|
||||
"string": "months after issue"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_TimePeriodField_dot_weekLabel": {
|
||||
"context": "TimePeriodTextWithSelectField day label",
|
||||
"context": "weeks after label",
|
||||
"string": "weeks after issue"
|
||||
},
|
||||
"src_dot_giftCards_dot_components_dot_TimePeriodField_dot_yearLabel": {
|
||||
"context": "TimePeriodTextWithSelectField year label",
|
||||
"context": "years after label",
|
||||
"string": "years after issue"
|
||||
},
|
||||
"src_dot_home": {
|
||||
|
@ -4659,6 +4820,18 @@
|
|||
"context": "order",
|
||||
"string": "Customer"
|
||||
},
|
||||
"src_dot_orders_dot_components_dot_OrderListPage_dot_giftCard": {
|
||||
"context": "order",
|
||||
"string": "Gift Card"
|
||||
},
|
||||
"src_dot_orders_dot_components_dot_OrderListPage_dot_giftCardOrdered": {
|
||||
"context": "order",
|
||||
"string": "Gift Card ordered"
|
||||
},
|
||||
"src_dot_orders_dot_components_dot_OrderListPage_dot_giftCardPaid": {
|
||||
"context": "order",
|
||||
"string": "Paid with Gift Card"
|
||||
},
|
||||
"src_dot_orders_dot_components_dot_OrderListPage_dot_placed": {
|
||||
"context": "order",
|
||||
"string": "Created"
|
||||
|
@ -5790,19 +5963,15 @@
|
|||
},
|
||||
"src_dot_productTypes_dot_components_dot_ProductTypeDetails_dot_optionGiftCardDescription": {
|
||||
"context": "option description",
|
||||
"string": "This product type can be used to create voucher/gift card type products that user will be able to pay with during checkout process"
|
||||
"string": "This product will act as a payment method"
|
||||
},
|
||||
"src_dot_productTypes_dot_components_dot_ProductTypeDetails_dot_optionGiftCardTitle": {
|
||||
"context": "option",
|
||||
"string": "Products of this type can be used as gift card/voucher"
|
||||
},
|
||||
"src_dot_productTypes_dot_components_dot_ProductTypeDetails_dot_optionNormalDescription": {
|
||||
"context": "option description",
|
||||
"string": "This product type can be used to create shipping passes for your customers"
|
||||
"string": "Gift card product type"
|
||||
},
|
||||
"src_dot_productTypes_dot_components_dot_ProductTypeDetails_dot_optionNormalTitle": {
|
||||
"context": "option",
|
||||
"string": "This is a normal product"
|
||||
"string": "Regular product type"
|
||||
},
|
||||
"src_dot_productTypes_dot_components_dot_ProductTypeDetails_dot_productTypeName": {
|
||||
"context": "label",
|
||||
|
@ -5985,15 +6154,15 @@
|
|||
"string": "SEO Information"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_2167661409": {
|
||||
"context": "export selected products to csv file",
|
||||
"context": "export selected items to csv file",
|
||||
"string": "Selected products ({number})"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_2318723509": {
|
||||
"context": "export products to csv file, choice field label",
|
||||
"context": "export items to csv file, choice field label",
|
||||
"string": "Export information for:"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_2355065897": {
|
||||
"context": "export all products to csv file",
|
||||
"context": "export all items to csv file",
|
||||
"string": "All products ({number})"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_2474350154": {
|
||||
|
@ -6005,17 +6174,9 @@
|
|||
"string": "Information exported"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_2693217446": {
|
||||
"context": "export products as csv or spreadsheet file",
|
||||
"context": "export items as csv or spreadsheet file",
|
||||
"string": "Export as:"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_2883720012": {
|
||||
"context": "export products to csv file, button",
|
||||
"string": "export products"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_3012202273": {
|
||||
"context": "export products to csv file, dialog header",
|
||||
"string": "Export Information"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_3365843236": {
|
||||
"context": "product export to csv file, header",
|
||||
"string": "Export Settings"
|
||||
|
@ -6025,7 +6186,7 @@
|
|||
"string": "Select All"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_3518309850": {
|
||||
"context": "export products as spreadsheet",
|
||||
"context": "export items as spreadsheet",
|
||||
"string": "Spreadsheet for Excel, Numbers etc."
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_3599582104": {
|
||||
|
@ -6039,7 +6200,7 @@
|
|||
"string": "Inventory Information"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_4118932547": {
|
||||
"context": "export products as csv file",
|
||||
"context": "export items as csv file",
|
||||
"string": "Plain CSV file"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_472026385": {
|
||||
|
@ -6051,13 +6212,25 @@
|
|||
"string": "Search by attribute name"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_700651641": {
|
||||
"context": "export filtered products to csv file",
|
||||
"context": "export filtered items to csv file",
|
||||
"string": "Current search ({number})"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_734825715": {
|
||||
"context": "informations about product prices etc, header",
|
||||
"string": "Financial Information"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_confirmButtonLabel": {
|
||||
"context": "export products to csv file, button",
|
||||
"string": "export products"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_productsLabel": {
|
||||
"context": "products export type label",
|
||||
"string": "products"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExportDialog_dot_title": {
|
||||
"context": "export products to csv file, dialog header",
|
||||
"string": "Export Information"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductExternalMediaDialog_dot_4146081479": {
|
||||
"context": "modal header",
|
||||
"string": "Media from the URL you supply will be shown in the media gallery. You will be able to define the order of the gallery."
|
||||
|
@ -6104,6 +6277,10 @@
|
|||
"context": "product is hidden",
|
||||
"string": "Hidden"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductListPage_dot_kind": {
|
||||
"context": "product kind",
|
||||
"string": "Product Kind"
|
||||
},
|
||||
"src_dot_products_dot_components_dot_ProductListPage_dot_outOfStock": {
|
||||
"context": "product status",
|
||||
"string": "Out Of Stock"
|
||||
|
@ -6716,6 +6893,14 @@
|
|||
"src_dot_products_dot_views_dot_ProductList_dot_44832327": {
|
||||
"string": "We are currently exporting your requested CSV. As soon as it is available it will be sent to your email address"
|
||||
},
|
||||
"src_dot_products_dot_views_dot_ProductList_dot_giftCardLabel": {
|
||||
"context": "label",
|
||||
"string": "Gift Card"
|
||||
},
|
||||
"src_dot_products_dot_views_dot_ProductList_dot_normalLabel": {
|
||||
"context": "label",
|
||||
"string": "Normal"
|
||||
},
|
||||
"src_dot_products_dot_views_dot_ProductUpdate_dot_3423943948": {
|
||||
"string": "Manage Products Channel Availability"
|
||||
},
|
||||
|
|
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -6413,23 +6413,6 @@
|
|||
"requires": {
|
||||
"@types/react": "*",
|
||||
"hoist-non-react-statics": "^3.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/react": {
|
||||
"version": "17.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.3.tgz",
|
||||
"integrity": "sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg==",
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"csstype": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.7.tgz",
|
||||
"integrity": "sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/html-minifier-terser": {
|
||||
|
|
2631
schema.graphql
2631
schema.graphql
File diff suppressed because it is too large
Load diff
|
@ -1,23 +1,32 @@
|
|||
import {
|
||||
CircularProgress,
|
||||
ClickAwayListener,
|
||||
Grow,
|
||||
IconButton,
|
||||
MenuItem,
|
||||
MenuList,
|
||||
Paper,
|
||||
Popper
|
||||
Popper,
|
||||
Typography
|
||||
} from "@material-ui/core";
|
||||
import MoreVertIcon from "@material-ui/icons/MoreVert";
|
||||
import { makeStyles } from "@saleor/macaw-ui";
|
||||
import React from "react";
|
||||
import classNames from "classnames";
|
||||
import * as React from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import { cardMenuMessages as messages } from "./messages";
|
||||
|
||||
const ITEM_HEIGHT = 48;
|
||||
|
||||
export interface CardMenuItem {
|
||||
disabled?: boolean;
|
||||
label: string;
|
||||
testId?: string;
|
||||
onSelect: () => void;
|
||||
loading?: boolean;
|
||||
withLoading?: boolean;
|
||||
hasError?: boolean;
|
||||
}
|
||||
|
||||
export interface CardMenuProps {
|
||||
|
@ -42,6 +51,14 @@ const useStyles = makeStyles(
|
|||
marginTop: theme.spacing(2),
|
||||
maxHeight: ITEM_HEIGHT * 4.5,
|
||||
overflowY: "scroll"
|
||||
},
|
||||
loadingContent: {
|
||||
width: "100%",
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 24px",
|
||||
gap: theme.spacing(2),
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-end"
|
||||
}
|
||||
}),
|
||||
{ name: "CardMenu" }
|
||||
|
@ -51,8 +68,8 @@ const CardMenu: React.FC<CardMenuProps> = props => {
|
|||
const { className, disabled, menuItems, ...rest } = props;
|
||||
const classes = useStyles(props);
|
||||
|
||||
const anchorRef = React.useRef<HTMLButtonElement | null>(null);
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const anchorRef = useRef<HTMLButtonElement | null>(null);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleToggle = () => setOpen(prevOpen => !prevOpen);
|
||||
|
||||
|
@ -74,8 +91,8 @@ const CardMenu: React.FC<CardMenuProps> = props => {
|
|||
}
|
||||
};
|
||||
|
||||
const prevOpen = React.useRef(open);
|
||||
React.useEffect(() => {
|
||||
const prevOpen = useRef(open);
|
||||
useEffect(() => {
|
||||
if (prevOpen.current === true && open === false) {
|
||||
anchorRef.current!.focus();
|
||||
}
|
||||
|
@ -83,11 +100,27 @@ const CardMenu: React.FC<CardMenuProps> = props => {
|
|||
prevOpen.current = open;
|
||||
}, [open]);
|
||||
|
||||
const handleMenuClick = (index: number) => {
|
||||
menuItems[index].onSelect();
|
||||
useEffect(() => {
|
||||
const hasAnyItemsLoadingOrWithError = menuItems
|
||||
?.filter(({ withLoading }) => withLoading)
|
||||
?.some(({ loading, hasError }) => loading || hasError);
|
||||
|
||||
if (!hasAnyItemsLoadingOrWithError) {
|
||||
setOpen(false);
|
||||
}
|
||||
}, [menuItems]);
|
||||
|
||||
const handleMenuClick = (index: number) => {
|
||||
const selectedItem = menuItems[index];
|
||||
selectedItem.onSelect();
|
||||
|
||||
if (!selectedItem.withLoading) {
|
||||
setOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
const isWithLoading = menuItems.some(({ withLoading }) => withLoading);
|
||||
|
||||
return (
|
||||
<div className={className} {...rest}>
|
||||
<IconButton
|
||||
|
@ -115,7 +148,8 @@ const CardMenu: React.FC<CardMenuProps> = props => {
|
|||
{...TransitionProps}
|
||||
style={{
|
||||
transformOrigin:
|
||||
placement === "bottom" ? "right top" : "right bottom"
|
||||
placement === "bottom" ? "right top" : "right bottom",
|
||||
overflowY: "auto"
|
||||
}}
|
||||
>
|
||||
<Paper className={classes.paper}>
|
||||
|
@ -128,12 +162,29 @@ const CardMenu: React.FC<CardMenuProps> = props => {
|
|||
{menuItems.map((menuItem, menuItemIndex) => (
|
||||
<MenuItem
|
||||
data-test-id={menuItem.testId}
|
||||
disabled={menuItem.disabled}
|
||||
disabled={menuItem.loading || menuItem.disabled}
|
||||
onClick={() => handleMenuClick(menuItemIndex)}
|
||||
key={menuItem.label}
|
||||
data-test={menuItem.testId}
|
||||
>
|
||||
{menuItem.label}
|
||||
<div
|
||||
className={classNames(className, {
|
||||
[classes.loadingContent]: isWithLoading
|
||||
})}
|
||||
>
|
||||
{menuItem.loading ? (
|
||||
<>
|
||||
<Typography variant="subtitle1">
|
||||
<FormattedMessage
|
||||
{...messages.cardMenuItemLoading}
|
||||
/>
|
||||
</Typography>
|
||||
<CircularProgress size={24} />
|
||||
</>
|
||||
) : (
|
||||
<Typography>{menuItem.label}</Typography>
|
||||
)}
|
||||
</div>
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
|
|
8
src/components/CardMenu/messages.ts
Normal file
8
src/components/CardMenu/messages.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { defineMessages } from "react-intl";
|
||||
|
||||
export const cardMenuMessages = defineMessages({
|
||||
cardMenuItemLoading: {
|
||||
defaultMessage: "working...",
|
||||
description: "menu item loading"
|
||||
}
|
||||
});
|
|
@ -27,6 +27,9 @@ const useStyles = makeStyles(
|
|||
fontWeight: 500,
|
||||
lineHeight: 1
|
||||
},
|
||||
subtitle: {
|
||||
fontWeight: 400
|
||||
},
|
||||
toolbar: {
|
||||
marginRight: theme.spacing(-1)
|
||||
}
|
||||
|
@ -39,6 +42,7 @@ interface CardTitleProps {
|
|||
className?: string;
|
||||
height?: "default" | "const";
|
||||
title: string | React.ReactNode;
|
||||
subtitle?: string | React.ReactNode;
|
||||
toolbar?: React.ReactNode;
|
||||
onClick?: (event: React.MouseEvent<any>) => void;
|
||||
}
|
||||
|
@ -49,6 +53,7 @@ const CardTitle: React.FC<CardTitleProps> = props => {
|
|||
children,
|
||||
height,
|
||||
title,
|
||||
subtitle,
|
||||
toolbar,
|
||||
onClick,
|
||||
...rest
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Divider } from "@material-ui/core";
|
||||
import initial from "lodash/initial";
|
||||
import React from "react";
|
||||
|
||||
interface CollectionWithDividersProps<T> {
|
||||
DividerComponent?: React.FunctionComponent;
|
||||
renderEmpty?: (collection: T[]) => any;
|
||||
withOuterDividers?: boolean;
|
||||
collection: T[];
|
||||
renderItem: (
|
||||
item: T | undefined,
|
||||
|
@ -13,7 +13,25 @@ interface CollectionWithDividersProps<T> {
|
|||
) => any;
|
||||
}
|
||||
|
||||
const Wrapper: React.FC<{
|
||||
withOuterDividers?: boolean;
|
||||
SelectedDivider?: React.FunctionComponent;
|
||||
}> = ({ withOuterDividers, SelectedDivider, children }) => (
|
||||
<div>
|
||||
{withOuterDividers && SelectedDivider ? (
|
||||
<>
|
||||
<SelectedDivider />
|
||||
{children}
|
||||
<SelectedDivider />
|
||||
</>
|
||||
) : (
|
||||
<>{children}</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
function CollectionWithDividers<T>({
|
||||
withOuterDividers = false,
|
||||
collection,
|
||||
renderItem,
|
||||
DividerComponent,
|
||||
|
@ -31,15 +49,20 @@ function CollectionWithDividers<T>({
|
|||
|
||||
const SelectedDividerComponent = DividerComponent || Divider;
|
||||
|
||||
return initial(
|
||||
collection.reduce(
|
||||
(result, item, index) => [
|
||||
...result,
|
||||
renderItem(item, index, collection),
|
||||
return (
|
||||
<Wrapper
|
||||
withOuterDividers={withOuterDividers}
|
||||
SelectedDivider={SelectedDividerComponent}
|
||||
>
|
||||
<>
|
||||
{collection.map((item, index) => (
|
||||
<>
|
||||
{renderItem(item, index, collection)}
|
||||
<SelectedDividerComponent />
|
||||
],
|
||||
[]
|
||||
)
|
||||
</>
|
||||
))}
|
||||
</>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Checkbox, FormControlLabel } from "@material-ui/core";
|
||||
import React from "react";
|
||||
|
||||
interface ControlledCheckboxProps {
|
||||
export interface ControlledCheckboxProps {
|
||||
className?: string;
|
||||
name: string;
|
||||
label?: React.ReactNode;
|
||||
|
|
|
@ -54,6 +54,7 @@ const useStyles = makeStyles(
|
|||
interface ExtendedPageHeaderProps {
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
childrenWrapperClassName?: string;
|
||||
inline?: boolean;
|
||||
underline?: boolean;
|
||||
title?: React.ReactNode;
|
||||
|
@ -61,7 +62,15 @@ interface ExtendedPageHeaderProps {
|
|||
}
|
||||
|
||||
const ExtendedPageHeader: React.FC<ExtendedPageHeaderProps> = props => {
|
||||
const { children, className, inline, underline, title, testId } = props;
|
||||
const {
|
||||
children,
|
||||
className,
|
||||
childrenWrapperClassName,
|
||||
inline,
|
||||
underline,
|
||||
title,
|
||||
testId
|
||||
} = props;
|
||||
|
||||
const classes = useStyles(props);
|
||||
|
||||
|
@ -75,7 +84,9 @@ const ExtendedPageHeader: React.FC<ExtendedPageHeaderProps> = props => {
|
|||
})}
|
||||
>
|
||||
{title}
|
||||
<div className={classes.action}>{children}</div>
|
||||
<div className={classNames(classes.action, childrenWrapperClassName)}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
{underline && (
|
||||
<div className={classes.underline}>
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer";
|
||||
import StatusChip from "@saleor/components/StatusChip";
|
||||
import { StatusType } from "@saleor/components/StatusChip/types";
|
||||
import { makeStyles } from "@saleor/macaw-ui";
|
||||
import React from "react";
|
||||
|
||||
import ExtendedPageHeader from "../ExtendedPageHeader";
|
||||
export interface PageTitleWithStatusChipProps {
|
||||
title: string;
|
||||
statusLabel: string;
|
||||
statusType: StatusType;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -22,17 +19,20 @@ const useStyles = makeStyles(
|
|||
|
||||
const PageTitleWithStatusChip: React.FC<PageTitleWithStatusChipProps> = ({
|
||||
title,
|
||||
statusLabel,
|
||||
statusType
|
||||
children
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
|
||||
return (
|
||||
<div className={classes.container}>
|
||||
{title}
|
||||
<ExtendedPageHeader
|
||||
title={title}
|
||||
childrenWrapperClassName={classes.container}
|
||||
>
|
||||
<>
|
||||
<HorizontalSpacer spacing={2} />
|
||||
<StatusChip label={statusLabel} status={statusType} />
|
||||
</div>
|
||||
{children}
|
||||
</>
|
||||
</ExtendedPageHeader>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -31,7 +31,13 @@ const Story: React.FC<Partial<
|
|||
SingleAutocompleteSelectFieldProps & {
|
||||
enableLoadMore: boolean;
|
||||
}
|
||||
>> = ({ allowCustomValues, emptyOption, enableLoadMore, nakedInput }) => {
|
||||
>> = ({
|
||||
allowCustomValues,
|
||||
emptyOption,
|
||||
enableLoadMore,
|
||||
nakedInput,
|
||||
disabled
|
||||
}) => {
|
||||
const [displayValue, setDisplayValue] = React.useState(suggestions[0].label);
|
||||
|
||||
return (
|
||||
|
@ -60,6 +66,7 @@ const Story: React.FC<Partial<
|
|||
allowCustomValues={allowCustomValues}
|
||||
emptyOption={emptyOption}
|
||||
nakedInput={nakedInput}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@ -106,9 +113,13 @@ storiesOf("Generics / Select with autocomplete", module)
|
|||
<SingleAutocompleteSelectFieldContent {...contentProps} choices={[]} />
|
||||
))
|
||||
.add("naked", () => <Story nakedInput />)
|
||||
.add("naked and disabled", () => <Story nakedInput disabled />)
|
||||
.add("interactive", () => <Story />)
|
||||
.add("interactive with custom option", () => (
|
||||
<Story allowCustomValues={true} />
|
||||
))
|
||||
.add("interactive with empty option", () => <Story emptyOption={true} />)
|
||||
.add("interactive with load more", () => <Story enableLoadMore={true} />);
|
||||
.add("interactive with load more", () => <Story enableLoadMore={true} />)
|
||||
.add("disabled", () => (
|
||||
<Story enableLoadMore={true} {...contentProps} disabled />
|
||||
));
|
||||
|
|
|
@ -187,7 +187,7 @@ const SingleAutocompleteSelectFieldComponent: React.FC<SingleAutocompleteSelectF
|
|||
error,
|
||||
id: undefined,
|
||||
onBlur: handleBlur,
|
||||
onClick: toggleMenu,
|
||||
onClick: !disabled && toggleMenu,
|
||||
onFocus: () => {
|
||||
if (fetchOnFocus) {
|
||||
fetchChoices(inputValue);
|
||||
|
|
|
@ -13,6 +13,8 @@ import classNames from "classnames";
|
|||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import { singleSelectFieldItemHeight } from "./consts";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
formControl: {
|
||||
|
@ -26,6 +28,9 @@ const useStyles = makeStyles(
|
|||
},
|
||||
noLabel: {
|
||||
padding: theme.spacing(2, 1.5)
|
||||
},
|
||||
paper: {
|
||||
maxHeight: `calc(${singleSelectFieldItemHeight}px * 10 + ${singleSelectFieldItemHeight}px * 0.5)`
|
||||
}
|
||||
}),
|
||||
{ name: "SingleSelectField" }
|
||||
|
@ -111,6 +116,11 @@ export const SingleSelectField: React.FC<SingleSelectFieldProps> = props => {
|
|||
/>
|
||||
}
|
||||
{...selectProps}
|
||||
MenuProps={{
|
||||
classes: {
|
||||
paper: classes.paper
|
||||
}
|
||||
}}
|
||||
>
|
||||
{choices.length > 0 ? (
|
||||
choices.map(choice => (
|
||||
|
|
1
src/components/SingleSelectField/consts.ts
Normal file
1
src/components/SingleSelectField/consts.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export const singleSelectFieldItemHeight = "36";
|
|
@ -25,7 +25,8 @@ const useStyles = makeStyles(
|
|||
},
|
||||
label: {
|
||||
alignSelf: "center",
|
||||
display: "inline-block"
|
||||
display: "inline-block",
|
||||
userSelect: "none"
|
||||
},
|
||||
labelContainer: {
|
||||
"&:hover": {
|
||||
|
@ -45,6 +46,9 @@ const useStyles = makeStyles(
|
|||
},
|
||||
root: {
|
||||
cursor: "pointer"
|
||||
},
|
||||
notSortable: {
|
||||
cursor: "unset"
|
||||
}
|
||||
}),
|
||||
{ name: "TableCellHeader" }
|
||||
|
@ -69,6 +73,7 @@ const TableCellHeader: React.FC<TableCellHeaderProps> = props => {
|
|||
textAlign,
|
||||
disabled = false,
|
||||
onClick,
|
||||
title,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
|
@ -76,12 +81,15 @@ const TableCellHeader: React.FC<TableCellHeaderProps> = props => {
|
|||
<TableCell
|
||||
{...rest}
|
||||
onClick={e => {
|
||||
if (!disabled) {
|
||||
if (disabled || !onClick) {
|
||||
e.preventDefault();
|
||||
} else {
|
||||
onClick(e);
|
||||
}
|
||||
}}
|
||||
className={classNames(classes.root, className, {
|
||||
[classes.disabled]: disabled
|
||||
[classes.disabled]: disabled,
|
||||
[classes.notSortable]: !onClick
|
||||
})}
|
||||
>
|
||||
<div
|
||||
|
|
|
@ -65,6 +65,7 @@ interface TimelineProps {
|
|||
}
|
||||
|
||||
interface TimelineAddNoteProps {
|
||||
disabled?: boolean;
|
||||
message: string;
|
||||
reset: () => void;
|
||||
onChange(event: React.ChangeEvent<any>);
|
||||
|
@ -80,7 +81,7 @@ export const Timeline: React.FC<TimelineProps> = props => {
|
|||
};
|
||||
|
||||
export const TimelineAddNote: React.FC<TimelineAddNoteProps> = props => {
|
||||
const { message, onChange, onSubmit, reset } = props;
|
||||
const { message, onChange, onSubmit, reset, disabled } = props;
|
||||
const classes = useStyles(props);
|
||||
|
||||
const intl = useIntl();
|
||||
|
@ -100,6 +101,7 @@ export const TimelineAddNote: React.FC<TimelineAddNoteProps> = props => {
|
|||
<PersonIcon />
|
||||
</Avatar>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
className={classes.input}
|
||||
placeholder={intl.formatMessage({
|
||||
defaultMessage: "Leave your note here..."
|
||||
|
@ -115,6 +117,7 @@ export const TimelineAddNote: React.FC<TimelineAddNoteProps> = props => {
|
|||
className={classes.button}
|
||||
color="primary"
|
||||
onClick={e => submit(e)}
|
||||
disabled={disabled}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Send"
|
||||
|
|
|
@ -80,7 +80,7 @@ export interface TimelineEventProps {
|
|||
children?: React.ReactNode;
|
||||
date: string;
|
||||
secondaryTitle?: string;
|
||||
title?: string;
|
||||
title?: React.ReactNode;
|
||||
titleElements?: TitleElement[];
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ export interface TitleElement {
|
|||
}
|
||||
|
||||
export interface TimelineEventHeaderProps {
|
||||
title?: string;
|
||||
title?: React.ReactNode;
|
||||
date: string;
|
||||
titleElements?: TitleElement[];
|
||||
secondaryTitle?: string;
|
||||
|
|
|
@ -66,6 +66,8 @@ interface TimelineNoteProps {
|
|||
message: string | null;
|
||||
user: {
|
||||
email: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -74,6 +76,14 @@ export const TimelineNote: React.FC<TimelineNoteProps> = props => {
|
|||
|
||||
const classes = useStyles(props);
|
||||
|
||||
const getUserTitleOrEmail = () => {
|
||||
if (user?.firstName && user?.lastName) {
|
||||
return `${user.firstName} ${user.lastName}`;
|
||||
}
|
||||
|
||||
return user?.email;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
{user && (
|
||||
|
@ -85,7 +95,7 @@ export const TimelineNote: React.FC<TimelineNoteProps> = props => {
|
|||
</Avatar>
|
||||
)}
|
||||
<div className={classes.title}>
|
||||
<Typography>{user?.email}</Typography>
|
||||
<Typography>{getUserTitleOrEmail()}</Typography>
|
||||
<Typography>
|
||||
<DateTime date={date} />
|
||||
</Typography>
|
||||
|
|
|
@ -8,6 +8,7 @@ import { MetadataFormData } from "@saleor/components/Metadata/types";
|
|||
import PageHeader from "@saleor/components/PageHeader";
|
||||
import Savebar from "@saleor/components/Savebar";
|
||||
import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment";
|
||||
import CustomerGiftCardsCard from "@saleor/giftCards/components/GiftCardCustomerCard/CustomerGiftCardsCard";
|
||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import { Backlink } from "@saleor/macaw-ui";
|
||||
|
@ -117,6 +118,8 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
|
|||
/>
|
||||
<CardSpacer />
|
||||
<CustomerStats customer={customer} />
|
||||
<CardSpacer />
|
||||
<CustomerGiftCardsCard />
|
||||
</div>
|
||||
</Grid>
|
||||
<Savebar
|
||||
|
|
8
src/customers/hooks/useCustomerDetails.ts
Normal file
8
src/customers/hooks/useCustomerDetails.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { CustomerDetailsContext } from "@saleor/customers/providers/CustomerDetailsProvider";
|
||||
import { useContext } from "react";
|
||||
|
||||
export const useCustomerDetails = () => {
|
||||
const customerDetails = useContext(CustomerDetailsContext);
|
||||
|
||||
return customerDetails;
|
||||
};
|
40
src/customers/providers/CustomerDetailsProvider.tsx
Normal file
40
src/customers/providers/CustomerDetailsProvider.tsx
Normal file
|
@ -0,0 +1,40 @@
|
|||
import React, { createContext } from "react";
|
||||
|
||||
import { useCustomerDetails } from "../queries";
|
||||
import { CustomerDetails } from "../types/CustomerDetails";
|
||||
|
||||
export interface CustomerDetailsProviderProps {
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface CustomerDetailsConsumerProps {
|
||||
customer: CustomerDetails | null;
|
||||
loading: boolean | null;
|
||||
}
|
||||
|
||||
export const CustomerDetailsContext = createContext<
|
||||
CustomerDetailsConsumerProps
|
||||
>(null);
|
||||
|
||||
export const CustomerDetailsProvider: React.FC<CustomerDetailsProviderProps> = ({
|
||||
children,
|
||||
id
|
||||
}) => {
|
||||
const { data, loading } = useCustomerDetails({
|
||||
displayLoader: true,
|
||||
variables: {
|
||||
id
|
||||
}
|
||||
});
|
||||
|
||||
const providerValues: CustomerDetailsConsumerProps = {
|
||||
customer: data,
|
||||
loading
|
||||
};
|
||||
|
||||
return (
|
||||
<CustomerDetailsContext.Provider value={providerValues}>
|
||||
{children}
|
||||
</CustomerDetailsContext.Provider>
|
||||
);
|
||||
};
|
|
@ -90,7 +90,8 @@ const customerDetails = gql`
|
|||
}
|
||||
}
|
||||
`;
|
||||
export const TypedCustomerDetailsQuery = TypedQuery<
|
||||
|
||||
export const useCustomerDetails = makeQuery<
|
||||
CustomerDetails,
|
||||
CustomerDetailsVariables
|
||||
>(customerDetails);
|
||||
|
|
|
@ -1,36 +1,18 @@
|
|||
import { DialogContentText } from "@material-ui/core";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { getStringOrPlaceholder } from "@saleor/misc";
|
||||
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
||||
import {
|
||||
useMetadataUpdate,
|
||||
usePrivateMetadataUpdate
|
||||
} from "@saleor/utils/metadata/updateMetadata";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { orderListUrl, orderUrl } from "../../orders/urls";
|
||||
import CustomerDetailsPage, {
|
||||
CustomerDetailsPageFormData
|
||||
} from "../components/CustomerDetailsPage/CustomerDetailsPage";
|
||||
import {
|
||||
TypedRemoveCustomerMutation,
|
||||
TypedUpdateCustomerMutation
|
||||
} from "../mutations";
|
||||
import { TypedCustomerDetailsQuery } from "../queries";
|
||||
import { CustomerDetailsProvider } from "../providers/CustomerDetailsProvider";
|
||||
import { RemoveCustomer } from "../types/RemoveCustomer";
|
||||
import { UpdateCustomer } from "../types/UpdateCustomer";
|
||||
import {
|
||||
customerAddressesUrl,
|
||||
customerListUrl,
|
||||
customerUrl,
|
||||
CustomerUrlQueryParams
|
||||
} from "../urls";
|
||||
import { customerListUrl, CustomerUrlQueryParams } from "../urls";
|
||||
import { CustomerDetailsContent } from "./CustomerDetailsContent";
|
||||
|
||||
interface CustomerDetailsViewProps {
|
||||
id: string;
|
||||
|
@ -75,109 +57,18 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
|
|||
{(removeCustomer, removeCustomerOpts) => (
|
||||
<TypedUpdateCustomerMutation onCompleted={handleCustomerUpdateSuccess}>
|
||||
{(updateCustomer, updateCustomerOpts) => (
|
||||
<TypedCustomerDetailsQuery displayLoader variables={{ id }}>
|
||||
{customerDetails => {
|
||||
const user = customerDetails.data?.user;
|
||||
|
||||
if (user === null) {
|
||||
return <NotFoundPage onBack={handleBack} />;
|
||||
}
|
||||
|
||||
const [updateMetadata] = useMetadataUpdate({});
|
||||
const [updatePrivateMetadata] = usePrivateMetadataUpdate({});
|
||||
|
||||
const updateData = async (
|
||||
data: CustomerDetailsPageFormData
|
||||
) => {
|
||||
const result = await updateCustomer({
|
||||
variables: {
|
||||
id,
|
||||
input: {
|
||||
email: data.email,
|
||||
firstName: data.firstName,
|
||||
isActive: data.isActive,
|
||||
lastName: data.lastName,
|
||||
note: data.note
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result.data.customerUpdate.errors;
|
||||
};
|
||||
|
||||
const handleSubmit = createMetadataUpdateHandler(
|
||||
user,
|
||||
updateData,
|
||||
variables => updateMetadata({ variables }),
|
||||
variables => updatePrivateMetadata({ variables })
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<WindowTitle title={user?.email} />
|
||||
<CustomerDetailsPage
|
||||
customer={user}
|
||||
disabled={
|
||||
customerDetails.loading ||
|
||||
updateCustomerOpts.loading ||
|
||||
removeCustomerOpts.loading
|
||||
}
|
||||
errors={
|
||||
updateCustomerOpts.data?.customerUpdate.errors || []
|
||||
}
|
||||
saveButtonBar={updateCustomerOpts.status}
|
||||
onAddressManageClick={() =>
|
||||
navigate(customerAddressesUrl(id))
|
||||
}
|
||||
onBack={handleBack}
|
||||
onRowClick={id => navigate(orderUrl(id))}
|
||||
onSubmit={handleSubmit}
|
||||
onDelete={() =>
|
||||
navigate(
|
||||
customerUrl(id, {
|
||||
action: "remove"
|
||||
})
|
||||
)
|
||||
}
|
||||
onViewAllOrdersClick={() =>
|
||||
navigate(
|
||||
orderListUrl({
|
||||
customer: user?.email
|
||||
})
|
||||
)
|
||||
}
|
||||
<CustomerDetailsProvider id={id}>
|
||||
<CustomerDetailsContent
|
||||
handleBack={handleBack}
|
||||
id={id}
|
||||
navigate={navigate}
|
||||
params={params}
|
||||
removeCustomer={removeCustomer}
|
||||
removeCustomerOpts={removeCustomerOpts}
|
||||
updateCustomer={updateCustomer}
|
||||
updateCustomerOpts={updateCustomerOpts}
|
||||
/>
|
||||
<ActionDialog
|
||||
confirmButtonState={removeCustomerOpts.status}
|
||||
onClose={() =>
|
||||
navigate(customerUrl(id), { replace: true })
|
||||
}
|
||||
onConfirm={() => removeCustomer()}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Delete Customer",
|
||||
description: "dialog header"
|
||||
})}
|
||||
variant="delete"
|
||||
open={params.action === "remove"}
|
||||
>
|
||||
<DialogContentText>
|
||||
<FormattedMessage
|
||||
defaultMessage="Are you sure you want to delete {email}?"
|
||||
description="delete customer, dialog content"
|
||||
values={{
|
||||
email: (
|
||||
<strong>
|
||||
{getStringOrPlaceholder(user?.email)}
|
||||
</strong>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</DialogContentText>
|
||||
</ActionDialog>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</TypedCustomerDetailsQuery>
|
||||
</CustomerDetailsProvider>
|
||||
)}
|
||||
</TypedUpdateCustomerMutation>
|
||||
)}
|
||||
|
|
150
src/customers/views/CustomerDetailsContent.tsx
Normal file
150
src/customers/views/CustomerDetailsContent.tsx
Normal file
|
@ -0,0 +1,150 @@
|
|||
import { DialogContentText } from "@material-ui/core";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||
import { UseNavigatorResult } from "@saleor/hooks/useNavigator";
|
||||
import { getStringOrPlaceholder } from "@saleor/misc";
|
||||
import { MutationResultAdditionalProps } from "@saleor/types";
|
||||
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
||||
import {
|
||||
useMetadataUpdate,
|
||||
usePrivateMetadataUpdate
|
||||
} from "@saleor/utils/metadata/updateMetadata";
|
||||
import React, { useContext } from "react";
|
||||
import { MutationFunction, MutationResult } from "react-apollo";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { orderListUrl, orderUrl } from "../../orders/urls";
|
||||
import CustomerDetailsPage, {
|
||||
CustomerDetailsPageFormData
|
||||
} from "../components/CustomerDetailsPage/CustomerDetailsPage";
|
||||
import { CustomerDetailsContext } from "../providers/CustomerDetailsProvider";
|
||||
import {
|
||||
RemoveCustomer,
|
||||
RemoveCustomerVariables
|
||||
} from "../types/RemoveCustomer";
|
||||
import {
|
||||
UpdateCustomer,
|
||||
UpdateCustomerVariables
|
||||
} from "../types/UpdateCustomer";
|
||||
import {
|
||||
customerAddressesUrl,
|
||||
customerUrl,
|
||||
CustomerUrlQueryParams
|
||||
} from "../urls";
|
||||
|
||||
export interface CustomerDetailsContentProps {
|
||||
handleBack: () => void;
|
||||
updateCustomer: MutationFunction<UpdateCustomer, UpdateCustomerVariables>;
|
||||
removeCustomer: MutationFunction<RemoveCustomer, RemoveCustomerVariables>;
|
||||
id: string;
|
||||
updateCustomerOpts: MutationResult<UpdateCustomer> &
|
||||
MutationResultAdditionalProps;
|
||||
removeCustomerOpts: MutationResult<RemoveCustomer> &
|
||||
MutationResultAdditionalProps;
|
||||
navigate: UseNavigatorResult;
|
||||
params: CustomerUrlQueryParams;
|
||||
}
|
||||
|
||||
export const CustomerDetailsContent: React.FC<CustomerDetailsContentProps> = ({
|
||||
handleBack,
|
||||
updateCustomer,
|
||||
id,
|
||||
updateCustomerOpts,
|
||||
removeCustomerOpts,
|
||||
navigate,
|
||||
removeCustomer,
|
||||
params
|
||||
}) => {
|
||||
const customerDetails = useContext(CustomerDetailsContext);
|
||||
const user = customerDetails?.customer?.user;
|
||||
const customerDetailsLoading = customerDetails?.loading;
|
||||
|
||||
const intl = useIntl();
|
||||
|
||||
if (user === null) {
|
||||
return <NotFoundPage onBack={handleBack} />;
|
||||
}
|
||||
|
||||
const [updateMetadata] = useMetadataUpdate({});
|
||||
const [updatePrivateMetadata] = usePrivateMetadataUpdate({});
|
||||
|
||||
const updateData = async (data: CustomerDetailsPageFormData) => {
|
||||
const result = await updateCustomer({
|
||||
variables: {
|
||||
id,
|
||||
input: {
|
||||
email: data.email,
|
||||
firstName: data.firstName,
|
||||
isActive: data.isActive,
|
||||
lastName: data.lastName,
|
||||
note: data.note
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result.data.customerUpdate.errors;
|
||||
};
|
||||
|
||||
const handleSubmit = createMetadataUpdateHandler(
|
||||
user,
|
||||
updateData,
|
||||
variables => updateMetadata({ variables }),
|
||||
variables => updatePrivateMetadata({ variables })
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<WindowTitle title={user?.email} />
|
||||
<CustomerDetailsPage
|
||||
customer={user}
|
||||
disabled={
|
||||
customerDetailsLoading ||
|
||||
updateCustomerOpts.loading ||
|
||||
removeCustomerOpts.loading
|
||||
}
|
||||
errors={updateCustomerOpts.data?.customerUpdate.errors || []}
|
||||
saveButtonBar={updateCustomerOpts.status}
|
||||
onAddressManageClick={() => navigate(customerAddressesUrl(id))}
|
||||
onBack={handleBack}
|
||||
onRowClick={id => navigate(orderUrl(id))}
|
||||
onSubmit={handleSubmit}
|
||||
onDelete={() =>
|
||||
navigate(
|
||||
customerUrl(id, {
|
||||
action: "remove"
|
||||
})
|
||||
)
|
||||
}
|
||||
onViewAllOrdersClick={() =>
|
||||
navigate(
|
||||
orderListUrl({
|
||||
customer: user?.email
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<ActionDialog
|
||||
confirmButtonState={removeCustomerOpts.status}
|
||||
onClose={() => navigate(customerUrl(id), { replace: true })}
|
||||
onConfirm={() => removeCustomer()}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Delete Customer",
|
||||
description: "dialog header"
|
||||
})}
|
||||
variant="delete"
|
||||
open={params.action === "remove"}
|
||||
>
|
||||
<DialogContentText>
|
||||
<FormattedMessage
|
||||
defaultMessage="Are you sure you want to delete {email}?"
|
||||
description="delete customer, dialog content"
|
||||
values={{
|
||||
email: <strong>{getStringOrPlaceholder(user?.email)}</strong>
|
||||
}}
|
||||
/>
|
||||
</DialogContentText>
|
||||
</ActionDialog>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,162 @@
|
|||
import { Dialog, DialogTitle } from "@material-ui/core";
|
||||
import { IMessage } from "@saleor/components/messages";
|
||||
import useCurrentDate from "@saleor/hooks/useCurrentDate";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { DialogProps } from "@saleor/types";
|
||||
import { GiftCardBulkCreateInput } from "@saleor/types/globalTypes";
|
||||
import { getFormErrors } from "@saleor/utils/errors";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import ContentWithProgress from "../GiftCardCreateDialog/ContentWithProgress";
|
||||
import GiftCardBulkCreateSuccessDialog from "../GiftCardCreateDialog/GiftCardBulkCreateSuccessDialog";
|
||||
import { useChannelCurrencies } from "../GiftCardCreateDialog/queries";
|
||||
import {
|
||||
getGiftCardCreateOnCompletedMessage,
|
||||
getGiftCardExpiryInputData
|
||||
} from "../GiftCardCreateDialog/utils";
|
||||
import { GIFT_CARD_LIST_QUERY } from "../GiftCardsList/types";
|
||||
import GiftCardBulkCreateDialogForm from "./GiftCardBulkCreateDialogForm";
|
||||
import { giftCardBulkCreateDialogMessages as messages } from "./messages";
|
||||
import { useGiftCardBulkCreateMutation } from "./mutations";
|
||||
import {
|
||||
giftCardBulkCreateErrorKeys,
|
||||
GiftCardBulkCreateFormData,
|
||||
GiftCardBulkCreateFormErrors
|
||||
} from "./types";
|
||||
import { GiftCardBulkCreate } from "./types/GiftCardBulkCreate";
|
||||
import { validateForm } from "./utils";
|
||||
|
||||
const GiftCardBulkCreateDialog: React.FC<DialogProps> = ({ onClose, open }) => {
|
||||
const intl = useIntl();
|
||||
const notify = useNotifier();
|
||||
const [formErrors, setFormErrors] = useState<GiftCardBulkCreateFormErrors>(
|
||||
null
|
||||
);
|
||||
const [issuedIds, setIssuedIds] = useState<string[] | null>(null);
|
||||
const [openIssueSuccessDialog, setOpenIssueSuccessDialog] = useState<boolean>(
|
||||
false
|
||||
);
|
||||
|
||||
const onIssueSuccessDialogClose = () => setOpenIssueSuccessDialog(false);
|
||||
|
||||
const { loading: loadingChannelCurrencies } = useChannelCurrencies({});
|
||||
|
||||
const onCompleted = (data: GiftCardBulkCreate) => {
|
||||
const errors = data?.giftCardBulkCreate?.errors;
|
||||
const cardsAmount = data?.giftCardBulkCreate?.giftCards?.length || 0;
|
||||
|
||||
const giftCardsBulkIssueSuccessMessage: IMessage = {
|
||||
status: "success",
|
||||
title: intl.formatMessage(messages.createdSuccessAlertTitle),
|
||||
text: intl.formatMessage(messages.createdSuccessAlertDescription, {
|
||||
cardsAmount
|
||||
})
|
||||
};
|
||||
|
||||
notify(
|
||||
getGiftCardCreateOnCompletedMessage(
|
||||
errors,
|
||||
intl,
|
||||
giftCardsBulkIssueSuccessMessage
|
||||
)
|
||||
);
|
||||
|
||||
setFormErrors(getFormErrors(giftCardBulkCreateErrorKeys, errors));
|
||||
|
||||
if (!errors.length) {
|
||||
setIssuedIds(
|
||||
data?.giftCardBulkCreate?.giftCards?.map(giftCard => giftCard.id)
|
||||
);
|
||||
setOpenIssueSuccessDialog(true);
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
const currentDate = useCurrentDate();
|
||||
|
||||
const getParsedSubmitInputData = (
|
||||
formData: GiftCardBulkCreateFormData
|
||||
): GiftCardBulkCreateInput => {
|
||||
const {
|
||||
balanceAmount,
|
||||
balanceCurrency,
|
||||
tags = [],
|
||||
requiresActivation,
|
||||
cardsAmount
|
||||
} = formData;
|
||||
|
||||
return {
|
||||
count: cardsAmount,
|
||||
tags,
|
||||
balance: {
|
||||
amount: balanceAmount,
|
||||
currency: balanceCurrency
|
||||
},
|
||||
expiryDate: getGiftCardExpiryInputData(formData, currentDate),
|
||||
isActive: !requiresActivation
|
||||
};
|
||||
};
|
||||
|
||||
const [
|
||||
bulkCreateGiftCard,
|
||||
bulkCreateGiftCardOpts
|
||||
] = useGiftCardBulkCreateMutation({
|
||||
onCompleted,
|
||||
refetchQueries: [GIFT_CARD_LIST_QUERY]
|
||||
});
|
||||
|
||||
const handleSubmit = (data: GiftCardBulkCreateFormData) => {
|
||||
const formErrors = validateForm(data);
|
||||
|
||||
if (!!Object.keys(formErrors).length) {
|
||||
setFormErrors(formErrors);
|
||||
} else {
|
||||
bulkCreateGiftCard({
|
||||
variables: {
|
||||
input: getParsedSubmitInputData(data)
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const apiErrors = bulkCreateGiftCardOpts?.data?.giftCardBulkCreate?.errors;
|
||||
|
||||
const handleSetSchemaErrors = () => {
|
||||
if (apiErrors?.length) {
|
||||
const formErrorsFromApi = getFormErrors(
|
||||
giftCardBulkCreateErrorKeys,
|
||||
apiErrors
|
||||
);
|
||||
|
||||
setFormErrors(formErrorsFromApi);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(handleSetSchemaErrors, [apiErrors]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog open={open} maxWidth="sm">
|
||||
<DialogTitle>{intl.formatMessage(messages.title)}</DialogTitle>
|
||||
<ContentWithProgress>
|
||||
{!loadingChannelCurrencies && (
|
||||
<GiftCardBulkCreateDialogForm
|
||||
opts={bulkCreateGiftCardOpts}
|
||||
onClose={onClose}
|
||||
formErrors={formErrors}
|
||||
onSubmit={handleSubmit}
|
||||
/>
|
||||
)}
|
||||
</ContentWithProgress>
|
||||
</Dialog>
|
||||
<GiftCardBulkCreateSuccessDialog
|
||||
onClose={onIssueSuccessDialogClose}
|
||||
open={openIssueSuccessDialog}
|
||||
idsToExport={issuedIds}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GiftCardBulkCreateDialog;
|
|
@ -0,0 +1,151 @@
|
|||
import {
|
||||
DialogContent,
|
||||
Divider,
|
||||
TextField,
|
||||
Typography
|
||||
} from "@material-ui/core";
|
||||
import VerticalSpacer from "@saleor/apps/components/VerticalSpacer";
|
||||
import DialogButtons from "@saleor/components/ActionDialog/DialogButtons";
|
||||
import CardSpacer from "@saleor/components/CardSpacer";
|
||||
import GiftCardTagInput from "@saleor/giftCards/components/GiftCardTagInput";
|
||||
import useForm from "@saleor/hooks/useForm";
|
||||
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
||||
import {
|
||||
GiftCardSettingsExpiryTypeEnum,
|
||||
TimePeriodTypeEnum
|
||||
} from "@saleor/types/globalTypes";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import GiftCardCreateExpirySelect from "../GiftCardCreateDialog/GiftCardCreateExpirySelect";
|
||||
import GiftCardCreateMoneyInput from "../GiftCardCreateDialog/GiftCardCreateMoneyInput";
|
||||
import GiftCardCreateRequiresActivationSection from "../GiftCardCreateDialog/GiftCardCreateRequiresActivationSection";
|
||||
import { giftCardCreateMessages as messages } from "../GiftCardCreateDialog/messages";
|
||||
import { useGiftCardCreateFormStyles as useStyles } from "../GiftCardCreateDialog/styles";
|
||||
import { useGiftCardSettingsQuery } from "../GiftCardSettings/queries";
|
||||
import { getGiftCardErrorMessage } from "../GiftCardUpdate/messages";
|
||||
import {
|
||||
GiftCardBulkCreateFormCommonProps,
|
||||
GiftCardBulkCreateFormData,
|
||||
GiftCardBulkCreateFormErrors
|
||||
} from "./types";
|
||||
|
||||
export const initialData: GiftCardBulkCreateFormData = {
|
||||
tags: [],
|
||||
balanceAmount: 1,
|
||||
balanceCurrency: null,
|
||||
expirySelected: false,
|
||||
expiryType: "EXPIRY_PERIOD",
|
||||
expiryDate: "",
|
||||
expiryPeriodType: TimePeriodTypeEnum.MONTH,
|
||||
expiryPeriodAmount: 12,
|
||||
requiresActivation: true,
|
||||
cardsAmount: 100
|
||||
};
|
||||
|
||||
interface GiftCardBulkCreateDialogFormProps {
|
||||
opts: { status: ConfirmButtonTransitionState };
|
||||
formErrors: GiftCardBulkCreateFormErrors;
|
||||
onSubmit: (data: GiftCardBulkCreateFormData) => void;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const GiftCardBulkCreateDialogForm: React.FC<GiftCardBulkCreateDialogFormProps> = ({
|
||||
onSubmit,
|
||||
opts,
|
||||
onClose,
|
||||
formErrors = {}
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
||||
const {
|
||||
data: settingsData,
|
||||
loading: loadingSettings
|
||||
} = useGiftCardSettingsQuery();
|
||||
|
||||
const getInitialExpirySettingsData = (): Partial<GiftCardBulkCreateFormData> => {
|
||||
if (loadingSettings) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const { expiryType, expiryPeriod } = settingsData?.giftCardSettings;
|
||||
|
||||
if (expiryType === GiftCardSettingsExpiryTypeEnum.NEVER_EXPIRE) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
expiryType,
|
||||
expiryPeriodType: expiryPeriod?.type,
|
||||
expiryPeriodAmount: expiryPeriod?.amount
|
||||
};
|
||||
};
|
||||
|
||||
const { submit, toggleValue, change, data, set } = useForm(
|
||||
{
|
||||
...initialData,
|
||||
...getInitialExpirySettingsData(),
|
||||
balanceCurrency: ""
|
||||
},
|
||||
onSubmit
|
||||
);
|
||||
|
||||
const { tags, requiresActivation, cardsAmount } = data;
|
||||
|
||||
const commonFormProps: GiftCardBulkCreateFormCommonProps = {
|
||||
data,
|
||||
errors: formErrors,
|
||||
toggleValue,
|
||||
change
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DialogContent className={classes.dialogContent}>
|
||||
<TextField
|
||||
error={!!formErrors?.count}
|
||||
name="cardsAmount"
|
||||
onChange={change}
|
||||
className={classes.fullWidthContainer}
|
||||
label={intl.formatMessage(messages.giftCardsAmountLabel)}
|
||||
value={cardsAmount}
|
||||
helperText={getGiftCardErrorMessage(formErrors?.count, intl)}
|
||||
/>
|
||||
<VerticalSpacer spacing={2} />
|
||||
<GiftCardCreateMoneyInput {...commonFormProps} set={set} />
|
||||
<VerticalSpacer spacing={2} />
|
||||
<GiftCardTagInput
|
||||
optional={false}
|
||||
error={formErrors?.tags}
|
||||
name="tags"
|
||||
values={tags}
|
||||
toggleChange={toggleValue}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<Divider />
|
||||
<VerticalSpacer />
|
||||
<GiftCardCreateExpirySelect {...commonFormProps} />
|
||||
<VerticalSpacer />
|
||||
<Divider />
|
||||
<VerticalSpacer spacing={2} />
|
||||
<GiftCardCreateRequiresActivationSection
|
||||
onChange={change}
|
||||
checked={requiresActivation}
|
||||
/>
|
||||
<VerticalSpacer spacing={2} />
|
||||
<Typography>
|
||||
{intl.formatMessage(messages.bulkCreateExplanation)}
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogButtons
|
||||
onConfirm={submit}
|
||||
confirmButtonLabel={intl.formatMessage(messages.issueButtonLabel)}
|
||||
confirmButtonState={opts?.status}
|
||||
onClose={onClose}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GiftCardBulkCreateDialogForm;
|
2
src/giftCards/GiftCardBulkCreateDialog/index.tsx
Normal file
2
src/giftCards/GiftCardBulkCreateDialog/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
|||
export * from "./GiftCardBulkCreateDialog";
|
||||
export { default } from "./GiftCardBulkCreateDialog";
|
16
src/giftCards/GiftCardBulkCreateDialog/messages.ts
Normal file
16
src/giftCards/GiftCardBulkCreateDialog/messages.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { defineMessages } from "react-intl";
|
||||
|
||||
export const giftCardBulkCreateDialogMessages = defineMessages({
|
||||
title: {
|
||||
defaultMessage: "Bulk Issue Gift Cards",
|
||||
description: "bulk issue gift cards dialog title"
|
||||
},
|
||||
createdSuccessAlertTitle: {
|
||||
defaultMessage: "Gift Cards Issued",
|
||||
description: "bulk issue gift cards success alert title"
|
||||
},
|
||||
createdSuccessAlertDescription: {
|
||||
defaultMessage: "Requested {cardsAmount} were successfully issued",
|
||||
description: "bulk issue gift cards success alert description"
|
||||
}
|
||||
});
|
26
src/giftCards/GiftCardBulkCreateDialog/mutations.ts
Normal file
26
src/giftCards/GiftCardBulkCreateDialog/mutations.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import makeMutation from "@saleor/hooks/makeMutation";
|
||||
import gql from "graphql-tag";
|
||||
|
||||
import {
|
||||
GiftCardBulkCreate,
|
||||
GiftCardBulkCreateVariables
|
||||
} from "./types/GiftCardBulkCreate";
|
||||
|
||||
const giftCardBulkCreate = gql`
|
||||
mutation GiftCardBulkCreate($input: GiftCardBulkCreateInput!) {
|
||||
giftCardBulkCreate(input: $input) {
|
||||
giftCards {
|
||||
id
|
||||
}
|
||||
errors {
|
||||
code
|
||||
field
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const useGiftCardBulkCreateMutation = makeMutation<
|
||||
GiftCardBulkCreate,
|
||||
GiftCardBulkCreateVariables
|
||||
>(giftCardBulkCreate);
|
58
src/giftCards/GiftCardBulkCreateDialog/types.ts
Normal file
58
src/giftCards/GiftCardBulkCreateDialog/types.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import { GiftCardError } from "@saleor/fragments/types/GiftCardError";
|
||||
import { FormChange } from "@saleor/hooks/useForm";
|
||||
import { TimePeriodTypeEnum } from "@saleor/types/globalTypes";
|
||||
|
||||
import { GiftCardExpiryType } from "../GiftCardCreateDialog/types";
|
||||
|
||||
export type GiftCardErrorKey =
|
||||
| "tags"
|
||||
| "expiryDate"
|
||||
| "currency"
|
||||
| "expiryPeriod"
|
||||
| "amount"
|
||||
| "balance"
|
||||
| "count";
|
||||
|
||||
export const giftCardBulkCreateErrorKeys: GiftCardErrorKey[] = [
|
||||
"tags",
|
||||
"expiryDate",
|
||||
"currency",
|
||||
"amount",
|
||||
"balance",
|
||||
"count"
|
||||
];
|
||||
|
||||
export interface GiftCardBulkCreateFormData
|
||||
extends GiftCardCreateCommonFormData {
|
||||
cardsAmount: number;
|
||||
}
|
||||
|
||||
export type GiftCardBulkCreateFormError = Pick<GiftCardError, "code" | "field">;
|
||||
|
||||
export type GiftCardBulkCreateFormErrors = Partial<
|
||||
Record<GiftCardErrorKey, GiftCardBulkCreateFormError>
|
||||
>;
|
||||
|
||||
export interface GiftCardBulkCreateFormCommonProps {
|
||||
change: FormChange;
|
||||
toggleValue: FormChange;
|
||||
errors: GiftCardBulkCreateFormErrors;
|
||||
data: GiftCardBulkCreateFormData;
|
||||
}
|
||||
|
||||
export interface GiftCardCreateCommonFormData {
|
||||
expirySelected: boolean;
|
||||
expiryType: GiftCardExpiryType;
|
||||
expiryPeriodType: TimePeriodTypeEnum;
|
||||
expiryPeriodAmount: number;
|
||||
requiresActivation: boolean;
|
||||
tags: string[];
|
||||
balanceAmount: number;
|
||||
balanceCurrency: string;
|
||||
expiryDate: string;
|
||||
}
|
||||
|
||||
export interface GiftCardBulkCreateFormData
|
||||
extends GiftCardCreateCommonFormData {
|
||||
cardsAmount: number;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { GiftCardBulkCreateInput, GiftCardErrorCode } from "./../../../types/globalTypes";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL mutation operation: GiftCardBulkCreate
|
||||
// ====================================================
|
||||
|
||||
export interface GiftCardBulkCreate_giftCardBulkCreate_giftCards {
|
||||
__typename: "GiftCard";
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface GiftCardBulkCreate_giftCardBulkCreate_errors {
|
||||
__typename: "GiftCardError";
|
||||
code: GiftCardErrorCode;
|
||||
field: string | null;
|
||||
}
|
||||
|
||||
export interface GiftCardBulkCreate_giftCardBulkCreate {
|
||||
__typename: "GiftCardBulkCreate";
|
||||
giftCards: GiftCardBulkCreate_giftCardBulkCreate_giftCards[];
|
||||
errors: GiftCardBulkCreate_giftCardBulkCreate_errors[];
|
||||
}
|
||||
|
||||
export interface GiftCardBulkCreate {
|
||||
giftCardBulkCreate: GiftCardBulkCreate_giftCardBulkCreate | null;
|
||||
}
|
||||
|
||||
export interface GiftCardBulkCreateVariables {
|
||||
input: GiftCardBulkCreateInput;
|
||||
}
|
64
src/giftCards/GiftCardBulkCreateDialog/utils.ts
Normal file
64
src/giftCards/GiftCardBulkCreateDialog/utils.ts
Normal file
|
@ -0,0 +1,64 @@
|
|||
import { GiftCardError } from "@saleor/fragments/types/GiftCardError";
|
||||
import { GiftCardErrorCode } from "@saleor/types/globalTypes";
|
||||
import reduce from "lodash/reduce";
|
||||
|
||||
import {
|
||||
GiftCardBulkCreateFormData,
|
||||
GiftCardBulkCreateFormErrors
|
||||
} from "./types";
|
||||
|
||||
export const validateField = (
|
||||
{
|
||||
expiryDate,
|
||||
expiryPeriodAmount,
|
||||
expiryType,
|
||||
expirySelected,
|
||||
expiryPeriodType
|
||||
}: GiftCardBulkCreateFormData,
|
||||
value,
|
||||
key: keyof GiftCardBulkCreateFormData
|
||||
): Pick<GiftCardError, "field" | "code"> | null => {
|
||||
const error = { code: GiftCardErrorCode.INVALID, field: key };
|
||||
const expiryDateSelected = expirySelected && expiryType === "EXPIRY_DATE";
|
||||
const expiryPeriodSelected = expirySelected && expiryType === "EXPIRY_PERIOD";
|
||||
|
||||
switch (key) {
|
||||
case "cardsAmount":
|
||||
case "tags":
|
||||
case "balanceCurrency":
|
||||
case "balanceAmount":
|
||||
return !value ? error : null;
|
||||
|
||||
case "expiryDate":
|
||||
return expiryDateSelected && !expiryDate ? error : null;
|
||||
|
||||
case "expiryPeriodAmount":
|
||||
return expiryPeriodSelected && (!expiryPeriodType || !expiryPeriodAmount)
|
||||
? { ...error, field: "expiryDate" }
|
||||
: null;
|
||||
}
|
||||
};
|
||||
|
||||
export const validateForm = (
|
||||
formData: GiftCardBulkCreateFormData
|
||||
): GiftCardBulkCreateFormErrors =>
|
||||
reduce(
|
||||
formData,
|
||||
(resultErrors, value, key: keyof GiftCardBulkCreateFormData) => {
|
||||
const correspondingKeys = {
|
||||
cardsAmount: "count",
|
||||
balanceCurrency: "balance",
|
||||
balanceAmount: "balance",
|
||||
expiryPeriodAmount: "expiryDate"
|
||||
};
|
||||
|
||||
const formError = validateField(formData, value, key);
|
||||
|
||||
if (!formError) {
|
||||
return resultErrors;
|
||||
}
|
||||
|
||||
return { ...resultErrors, [correspondingKeys[key] || key]: formError };
|
||||
},
|
||||
{}
|
||||
);
|
|
@ -15,7 +15,7 @@ export const useStyles = makeStyles(
|
|||
justifyContent: "center",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
padding: theme.spacing
|
||||
padding: theme.spacing(3)
|
||||
}
|
||||
}),
|
||||
{ name: "ContentWithProgress" }
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Typography
|
||||
} from "@material-ui/core";
|
||||
import { DialogProps } from "@saleor/types";
|
||||
import React from "react";
|
||||
import { useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import GiftCardExportDialogContent from "../GiftCardExportDialogContent";
|
||||
import { giftCardCreateMessages as messages } from "./messages";
|
||||
|
||||
interface GiftCardBulkCreateSuccessDialogProps extends DialogProps {
|
||||
idsToExport: string[] | null;
|
||||
}
|
||||
|
||||
const GiftCardBulkCreateSuccessDialog: React.FC<GiftCardBulkCreateSuccessDialogProps> = ({
|
||||
open,
|
||||
onClose,
|
||||
idsToExport
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const [openEmailExport, setOpenEmailExport] = useState(false);
|
||||
|
||||
const onExportDialogClose = () => {
|
||||
setOpenEmailExport(false);
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog open={open} maxWidth="sm">
|
||||
<DialogTitle>
|
||||
{intl.formatMessage(messages.bulkCreateIssuedTitle)}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography>
|
||||
{intl.formatMessage(messages.bulkCreateIssuedExplanation)}
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
onClick={() => setOpenEmailExport(true)}
|
||||
>
|
||||
<FormattedMessage {...messages.bulkCreateIssuedExportToEmail} />
|
||||
</Button>
|
||||
<Button variant="contained" color="primary" onClick={onClose}>
|
||||
<FormattedMessage {...messages.bulkCreateIssuedAccept} />
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
<Dialog open={openEmailExport} maxWidth="sm">
|
||||
<GiftCardExportDialogContent
|
||||
idsToExport={idsToExport}
|
||||
onClose={onExportDialogClose}
|
||||
/>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GiftCardBulkCreateSuccessDialog;
|
|
@ -7,7 +7,7 @@ import { buttonMessages } from "@saleor/intl";
|
|||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { giftCardCreateDialogMessages as messages } from "./messages";
|
||||
import { giftCardCreateMessages as messages } from "./messages";
|
||||
import { useGiftCardCreateDialogCodeContentStyles as useStyles } from "./styles";
|
||||
|
||||
interface GiftCardCreateDialogCodeContentProps {
|
||||
|
|
|
@ -1,28 +1,36 @@
|
|||
import { Dialog, DialogTitle } from "@material-ui/core";
|
||||
import { IMessage } from "@saleor/components/messages";
|
||||
import { DialogTitle } from "@material-ui/core";
|
||||
import useCurrentDate from "@saleor/hooks/useCurrentDate";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { DialogProps } from "@saleor/types";
|
||||
import { GiftCardCreateInput } from "@saleor/types/globalTypes";
|
||||
import commonErrorMessages from "@saleor/utils/errors/common";
|
||||
import { DialogActionHandlersProps } from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import React, { useState } from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { GIFT_CARD_LIST_QUERY } from "../GiftCardsList/types";
|
||||
import ContentWithProgress from "./ContentWithProgress";
|
||||
import GiftCardCreateDialogCodeContent from "./GiftCardCreateDialogCodeContent";
|
||||
import GiftCardCreateDialogForm, {
|
||||
GiftCardCreateFormData
|
||||
} from "./GiftCardCreateDialogForm";
|
||||
import { giftCardCreateDialogMessages as messages } from "./messages";
|
||||
import { giftCardCreateMessages as messages } from "./messages";
|
||||
import { useGiftCardCreateMutation } from "./mutations";
|
||||
import { useChannelCurrencies } from "./queries";
|
||||
import { GiftCardCreateFormCustomer } from "./types";
|
||||
import { GiftCardCreate } from "./types/GiftCardCreate";
|
||||
import { getGiftCardExpiryInputData } from "./utils";
|
||||
import {
|
||||
getGiftCardCreateOnCompletedMessage,
|
||||
getGiftCardExpiryInputData
|
||||
} from "./utils";
|
||||
|
||||
const GiftCardCreateDialog: React.FC<DialogActionHandlersProps> = ({
|
||||
closeDialog,
|
||||
open
|
||||
interface GiftCardCreateDialogContentProps
|
||||
extends Pick<DialogProps, "onClose"> {
|
||||
refetchQueries: string[];
|
||||
initialCustomer?: GiftCardCreateFormCustomer | null;
|
||||
}
|
||||
|
||||
const GiftCardCreateDialogContent: React.FC<GiftCardCreateDialogContentProps> = ({
|
||||
onClose,
|
||||
refetchQueries,
|
||||
initialCustomer
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const notify = useNotifier();
|
||||
|
@ -34,17 +42,7 @@ const GiftCardCreateDialog: React.FC<DialogActionHandlersProps> = ({
|
|||
const onCompleted = (data: GiftCardCreate) => {
|
||||
const errors = data?.giftCardCreate?.errors;
|
||||
|
||||
const notifierData: IMessage = !!errors?.length
|
||||
? {
|
||||
status: "error",
|
||||
text: intl.formatMessage(commonErrorMessages.unknownError)
|
||||
}
|
||||
: {
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.createdSuccessAlertTitle)
|
||||
};
|
||||
|
||||
notify(notifierData);
|
||||
notify(getGiftCardCreateOnCompletedMessage(errors, intl));
|
||||
|
||||
if (!errors?.length) {
|
||||
setCardCode(data?.giftCardCreate?.giftCard?.code);
|
||||
|
@ -60,7 +58,7 @@ const GiftCardCreateDialog: React.FC<DialogActionHandlersProps> = ({
|
|||
balanceAmount,
|
||||
balanceCurrency,
|
||||
note,
|
||||
tag,
|
||||
tags,
|
||||
sendToCustomerSelected,
|
||||
selectedCustomer,
|
||||
requiresActivation,
|
||||
|
@ -69,7 +67,7 @@ const GiftCardCreateDialog: React.FC<DialogActionHandlersProps> = ({
|
|||
|
||||
return {
|
||||
note: note || null,
|
||||
tag: tag || null,
|
||||
addTags: tags || null,
|
||||
userEmail: (sendToCustomerSelected && selectedCustomer.email) || null,
|
||||
channel: (sendToCustomerSelected && channelSlug) || null,
|
||||
balance: {
|
||||
|
@ -83,7 +81,7 @@ const GiftCardCreateDialog: React.FC<DialogActionHandlersProps> = ({
|
|||
|
||||
const [createGiftCard, createGiftCardOpts] = useGiftCardCreateMutation({
|
||||
onCompleted,
|
||||
refetchQueries: [GIFT_CARD_LIST_QUERY]
|
||||
refetchQueries
|
||||
});
|
||||
|
||||
const handleSubmit = (data: GiftCardCreateFormData) => {
|
||||
|
@ -95,14 +93,11 @@ const GiftCardCreateDialog: React.FC<DialogActionHandlersProps> = ({
|
|||
};
|
||||
|
||||
const handleClose = () => {
|
||||
closeDialog();
|
||||
// dialog closing animation runs slower than prop change
|
||||
// and we don't want to show the form for a split second
|
||||
setTimeout(() => setCardCode(null), 0);
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} maxWidth="sm">
|
||||
<>
|
||||
<DialogTitle>{intl.formatMessage(messages.title)}</DialogTitle>
|
||||
<ContentWithProgress>
|
||||
{!loadingChannelCurrencies &&
|
||||
|
@ -117,11 +112,12 @@ const GiftCardCreateDialog: React.FC<DialogActionHandlersProps> = ({
|
|||
onClose={handleClose}
|
||||
apiErrors={createGiftCardOpts?.data?.giftCardCreate?.errors}
|
||||
onSubmit={handleSubmit}
|
||||
initialCustomer={initialCustomer}
|
||||
/>
|
||||
))}
|
||||
</ContentWithProgress>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GiftCardCreateDialog;
|
||||
export default GiftCardCreateDialogContent;
|
|
@ -1,13 +1,7 @@
|
|||
import {
|
||||
DialogContent,
|
||||
Divider,
|
||||
TextField,
|
||||
Typography
|
||||
} from "@material-ui/core";
|
||||
import { DialogContent, Divider, TextField } from "@material-ui/core";
|
||||
import VerticalSpacer from "@saleor/apps/components/VerticalSpacer";
|
||||
import DialogButtons from "@saleor/components/ActionDialog/DialogButtons";
|
||||
import CardSpacer from "@saleor/components/CardSpacer";
|
||||
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||
import { GiftCardError } from "@saleor/fragments/types/GiftCardError";
|
||||
import GiftCardTagInput from "@saleor/giftCards/components/GiftCardTagInput";
|
||||
import useForm from "@saleor/hooks/useForm";
|
||||
|
@ -20,40 +14,30 @@ import {
|
|||
} from "@saleor/types/globalTypes";
|
||||
import { getFormErrors } from "@saleor/utils/errors";
|
||||
import React, { useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import GiftCardSendToCustomer from "../components/GiftCardSendToCustomer/GiftCardSendToCustomer";
|
||||
import { GiftCardCreateCommonFormData } from "../GiftCardBulkCreateDialog/types";
|
||||
import { useGiftCardSettingsQuery } from "../GiftCardSettings/queries";
|
||||
import GiftCardCreateDialogMoneyInput from "./GiftCardCreateDialogMoneyInput";
|
||||
import GiftCardCreateExpirySelect from "./GiftCardCreateExpirySelect";
|
||||
import { giftCardCreateDialogMessages as messages } from "./messages";
|
||||
import { useGiftCardCreateDialogFormStyles as useStyles } from "./styles";
|
||||
import GiftCardCreateMoneyInput from "./GiftCardCreateMoneyInput";
|
||||
import GiftCardCreateRequiresActivationSection from "./GiftCardCreateRequiresActivationSection";
|
||||
import { giftCardCreateMessages as messages } from "./messages";
|
||||
import { useGiftCardCreateFormStyles as useStyles } from "./styles";
|
||||
import {
|
||||
GiftCardCreateFormCommonProps,
|
||||
GiftCardCreateFormCustomer,
|
||||
GiftCardExpiryType
|
||||
GiftCardCreateFormCustomer
|
||||
} from "./types";
|
||||
|
||||
export interface GiftCardCreateFormData {
|
||||
export interface GiftCardCreateFormData extends GiftCardCreateCommonFormData {
|
||||
note: string;
|
||||
sendToCustomerSelected: boolean;
|
||||
selectedCustomer?: GiftCardCreateFormCustomer;
|
||||
channelSlug?: string;
|
||||
expirySelected: boolean;
|
||||
expiryType: GiftCardExpiryType;
|
||||
expiryPeriodType: TimePeriodTypeEnum;
|
||||
expiryPeriodAmount: number;
|
||||
requiresActivation: boolean;
|
||||
tag: string;
|
||||
balanceAmount: number;
|
||||
balanceCurrency: string;
|
||||
expiryDate: string;
|
||||
}
|
||||
|
||||
const initialCustomer = { email: "", name: "" };
|
||||
|
||||
export const initialData: GiftCardCreateFormData = {
|
||||
tag: "",
|
||||
tags: [],
|
||||
balanceAmount: 1,
|
||||
balanceCurrency: null,
|
||||
note: "",
|
||||
|
@ -65,19 +49,22 @@ export const initialData: GiftCardCreateFormData = {
|
|||
expiryPeriodAmount: 12,
|
||||
requiresActivation: true
|
||||
};
|
||||
|
||||
interface GiftCardCreateDialogFormProps {
|
||||
opts: { status: ConfirmButtonTransitionState };
|
||||
apiErrors: GiftCardError[];
|
||||
onSubmit: (data: GiftCardCreateFormData) => void;
|
||||
onClose: () => void;
|
||||
initialCustomer?: GiftCardCreateFormCustomer | null;
|
||||
}
|
||||
|
||||
const defaultInitialCustomer = { email: "", name: "" };
|
||||
|
||||
const GiftCardCreateDialogForm: React.FC<GiftCardCreateDialogFormProps> = ({
|
||||
onSubmit,
|
||||
opts,
|
||||
onClose,
|
||||
apiErrors
|
||||
apiErrors,
|
||||
initialCustomer
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
@ -89,7 +76,7 @@ const GiftCardCreateDialogForm: React.FC<GiftCardCreateDialogFormProps> = ({
|
|||
|
||||
const [selectedCustomer, setSelectedCustomer] = useState<
|
||||
GiftCardCreateFormCustomer
|
||||
>(initialCustomer);
|
||||
>(initialCustomer || defaultInitialCustomer);
|
||||
|
||||
const handleSubmit = (data: GiftCardCreateFormData) =>
|
||||
onSubmit({ ...data, selectedCustomer });
|
||||
|
@ -112,23 +99,24 @@ const GiftCardCreateDialogForm: React.FC<GiftCardCreateDialogFormProps> = ({
|
|||
};
|
||||
};
|
||||
|
||||
const { submit, change, data, set } = useForm(
|
||||
const { submit, change, toggleValue, data, set } = useForm(
|
||||
{
|
||||
...initialData,
|
||||
...getInitialExpirySettingsData(),
|
||||
balanceCurrency: "",
|
||||
channelSlug: ""
|
||||
channelSlug: "",
|
||||
sendToCustomerSelected: !!initialCustomer
|
||||
},
|
||||
handleSubmit
|
||||
);
|
||||
|
||||
const formErrors = getFormErrors(
|
||||
["tag", "expiryDate", "customer", "currency", "amount", "balance"],
|
||||
["tags", "expiryDate", "customer", "currency", "amount", "balance"],
|
||||
apiErrors
|
||||
);
|
||||
|
||||
const {
|
||||
tag,
|
||||
tags,
|
||||
sendToCustomerSelected,
|
||||
channelSlug,
|
||||
balanceAmount,
|
||||
|
@ -153,19 +141,25 @@ const GiftCardCreateDialogForm: React.FC<GiftCardCreateDialogFormProps> = ({
|
|||
const commonFormProps: GiftCardCreateFormCommonProps = {
|
||||
data,
|
||||
errors: formErrors,
|
||||
toggleValue,
|
||||
change
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DialogContent>
|
||||
<GiftCardCreateDialogMoneyInput {...commonFormProps} set={set} />
|
||||
<DialogContent
|
||||
style={{
|
||||
overflowY: "auto",
|
||||
overflowX: "hidden"
|
||||
}}
|
||||
>
|
||||
<GiftCardCreateMoneyInput {...commonFormProps} set={set} />
|
||||
<CardSpacer />
|
||||
<GiftCardTagInput
|
||||
error={formErrors?.tag}
|
||||
name="tag"
|
||||
value={tag}
|
||||
change={change}
|
||||
error={formErrors?.tags}
|
||||
name="tags"
|
||||
values={tags}
|
||||
toggleChange={toggleValue}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<Divider />
|
||||
|
@ -175,6 +169,7 @@ const GiftCardCreateDialogForm: React.FC<GiftCardCreateDialogFormProps> = ({
|
|||
sendToCustomerSelected={sendToCustomerSelected}
|
||||
selectedCustomer={selectedCustomer}
|
||||
setSelectedCustomer={setSelectedCustomer}
|
||||
disabled={!!initialCustomer}
|
||||
/>
|
||||
<Divider />
|
||||
<VerticalSpacer />
|
||||
|
@ -192,18 +187,9 @@ const GiftCardCreateDialogForm: React.FC<GiftCardCreateDialogFormProps> = ({
|
|||
<VerticalSpacer />
|
||||
<Label text={intl.formatMessage(messages.noteSubtitle)} />
|
||||
<VerticalSpacer spacing={2} />
|
||||
<ControlledCheckbox
|
||||
name="requiresActivation"
|
||||
label={
|
||||
<>
|
||||
<FormattedMessage {...messages.requiresActivationLabel} />
|
||||
<Typography variant="caption">
|
||||
<FormattedMessage {...messages.requiresActivationCaption} />
|
||||
</Typography>
|
||||
</>
|
||||
}
|
||||
checked={requiresActivation}
|
||||
<GiftCardCreateRequiresActivationSection
|
||||
onChange={change}
|
||||
checked={requiresActivation}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogButtons
|
||||
|
|
|
@ -5,12 +5,14 @@ import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
|||
import RadioGroupField from "@saleor/components/RadioGroupField";
|
||||
import TimePeriodField from "@saleor/giftCards/components/TimePeriodField";
|
||||
import {
|
||||
GiftCardCreateFormCommonProps,
|
||||
GiftCardExpiryType
|
||||
} from "@saleor/giftCards/GiftCardCreateDialog/types";
|
||||
GiftCardBulkCreateFormErrors,
|
||||
GiftCardCreateCommonFormData
|
||||
} from "@saleor/giftCards/GiftCardBulkCreateDialog/types";
|
||||
import { GiftCardExpiryType } from "@saleor/giftCards/GiftCardCreateDialog/types";
|
||||
import { getExpiryPeriodTerminationDate } from "@saleor/giftCards/GiftCardCreateDialog/utils";
|
||||
import { getGiftCardErrorMessage } from "@saleor/giftCards/GiftCardUpdate/messages";
|
||||
import useCurrentDate from "@saleor/hooks/useCurrentDate";
|
||||
import { FormChange } from "@saleor/hooks/useForm";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { MessageDescriptor, useIntl } from "react-intl";
|
||||
|
@ -34,7 +36,20 @@ const options: UntranslatedOption[] = [
|
|||
}
|
||||
];
|
||||
|
||||
const GiftCardCreateExpirySelect: React.FC<GiftCardCreateFormCommonProps> = ({
|
||||
interface GiftCardCreateExpirySelectProps {
|
||||
errors: GiftCardBulkCreateFormErrors;
|
||||
change: FormChange;
|
||||
data: Pick<
|
||||
GiftCardCreateCommonFormData,
|
||||
| "expirySelected"
|
||||
| "expiryPeriodType"
|
||||
| "expiryPeriodAmount"
|
||||
| "expiryType"
|
||||
| "expiryDate"
|
||||
>;
|
||||
}
|
||||
|
||||
const GiftCardCreateExpirySelect: React.FC<GiftCardCreateExpirySelectProps> = ({
|
||||
errors,
|
||||
change,
|
||||
data: {
|
||||
|
|
|
@ -3,18 +3,18 @@ import { defineMessages } from "react-intl";
|
|||
export const giftCardCreateExpirySelectMessages = defineMessages({
|
||||
expirySelectedLabel: {
|
||||
defaultMessage: "Set gift card expiry date",
|
||||
description: "GiftCarUpdateDetailsExpirySection expiry selected label"
|
||||
description: "set expiry date selected label"
|
||||
},
|
||||
expiryPeriodLabel: {
|
||||
defaultMessage: "Expires in",
|
||||
description: "GiftCarUpdateDetailsExpirySection expiry period label"
|
||||
description: "expires in label"
|
||||
},
|
||||
expiryDateLabel: {
|
||||
defaultMessage: "Exact date",
|
||||
description: "GiftCarUpdateDetailsExpirySection expiry date label"
|
||||
description: "expiry date label"
|
||||
},
|
||||
expiryOnLabel: {
|
||||
defaultMessage: "Will expire on:",
|
||||
description: "GiftCarUpdateDetailsExpirySection expiry on label"
|
||||
description: "expires on label"
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,24 +1,28 @@
|
|||
import TextWithSelectField from "@saleor/components/TextWithSelectField";
|
||||
import { ChangeEvent } from "@saleor/hooks/useForm";
|
||||
import { ChangeEvent, FormChange } from "@saleor/hooks/useForm";
|
||||
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
||||
import { mapSingleValueNodeToChoice } from "@saleor/utils/maps";
|
||||
import * as React from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import {
|
||||
GiftCardBulkCreateFormErrors,
|
||||
GiftCardCreateCommonFormData
|
||||
} from "../GiftCardBulkCreateDialog/types";
|
||||
import { getGiftCardErrorMessage } from "../GiftCardUpdate/messages";
|
||||
import { GiftCardCreateFormData } from "./GiftCardCreateDialogForm";
|
||||
import { giftCardCreateDialogMessages as messages } from "./messages";
|
||||
import { giftCardCreateMessages as messages } from "./messages";
|
||||
import { useChannelCurrencies } from "./queries";
|
||||
import { useGiftCardCreateDialogFormStyles as useStyles } from "./styles";
|
||||
import { GiftCardCreateFormCommonProps } from "./types";
|
||||
import { useGiftCardCreateFormStyles as useStyles } from "./styles";
|
||||
|
||||
interface GiftCardCreateDialogMoneyInputProps
|
||||
extends GiftCardCreateFormCommonProps {
|
||||
set: (data: Partial<GiftCardCreateFormData>) => void;
|
||||
interface GiftCardCreateMoneyInputProps {
|
||||
change: FormChange;
|
||||
errors: GiftCardBulkCreateFormErrors;
|
||||
data: Pick<GiftCardCreateCommonFormData, "balanceCurrency" | "balanceAmount">;
|
||||
set: (data: Partial<GiftCardCreateCommonFormData>) => void;
|
||||
}
|
||||
|
||||
const GiftCardCreateDialogMoneyInput: React.FC<GiftCardCreateDialogMoneyInputProps> = ({
|
||||
const GiftCardCreateMoneyInput: React.FC<GiftCardCreateMoneyInputProps> = ({
|
||||
errors,
|
||||
data: { balanceAmount, balanceCurrency },
|
||||
change,
|
||||
|
@ -32,7 +36,7 @@ const GiftCardCreateDialogMoneyInput: React.FC<GiftCardCreateDialogMoneyInputPro
|
|||
const { channelCurrencies } = channelCurrenciesData?.shop;
|
||||
|
||||
const [savedCurrency, setCurrency] = useLocalStorage(
|
||||
"giftCardCreateDialogCurrency",
|
||||
"giftCardCreateCurrency",
|
||||
undefined
|
||||
);
|
||||
|
||||
|
@ -67,7 +71,7 @@ const GiftCardCreateDialogMoneyInput: React.FC<GiftCardCreateDialogMoneyInputPro
|
|||
helperText={getGiftCardErrorMessage(errors?.balance, intl)}
|
||||
change={handleInputChange}
|
||||
choices={mapSingleValueNodeToChoice(channelCurrencies)}
|
||||
containerClassName={classes.balanceContainer}
|
||||
containerClassName={classes.fullWidthContainer}
|
||||
textFieldProps={{
|
||||
type: "float",
|
||||
label: intl.formatMessage(messages.amountLabel),
|
||||
|
@ -84,4 +88,4 @@ const GiftCardCreateDialogMoneyInput: React.FC<GiftCardCreateDialogMoneyInputPro
|
|||
);
|
||||
};
|
||||
|
||||
export default GiftCardCreateDialogMoneyInput;
|
||||
export default GiftCardCreateMoneyInput;
|
|
@ -0,0 +1,34 @@
|
|||
import { Typography } from "@material-ui/core";
|
||||
import ControlledCheckbox, {
|
||||
ControlledCheckboxProps
|
||||
} from "@saleor/components/ControlledCheckbox";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import { giftCardCreateMessages as messages } from "./messages";
|
||||
|
||||
type GiftCardCreateRequiresActivationSectionProps = Pick<
|
||||
ControlledCheckboxProps,
|
||||
"checked" | "onChange"
|
||||
>;
|
||||
|
||||
const GiftCardCreateRequiresActivationSection: React.FC<GiftCardCreateRequiresActivationSectionProps> = ({
|
||||
checked,
|
||||
onChange
|
||||
}) => (
|
||||
<ControlledCheckbox
|
||||
name="requiresActivation"
|
||||
label={
|
||||
<>
|
||||
<FormattedMessage {...messages.requiresActivationLabel} />
|
||||
<Typography variant="caption">
|
||||
<FormattedMessage {...messages.requiresActivationCaption} />
|
||||
</Typography>
|
||||
</>
|
||||
}
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
|
||||
export default GiftCardCreateRequiresActivationSection;
|
|
@ -7,17 +7,19 @@ import { mapEdgesToItems } from "@saleor/utils/maps";
|
|||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { giftCardCreateDialogMessages as messages } from "./messages";
|
||||
import { giftCardCreateMessages as messages } from "./messages";
|
||||
import { GiftCardCreateFormCustomer } from "./types";
|
||||
|
||||
export interface GiftCardCustomerSelectFieldProps {
|
||||
selectedCustomer: GiftCardCreateFormCustomer;
|
||||
setSelectedCustomer: (customer: GiftCardCreateFormCustomer) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const GiftCardCustomerSelectField: React.FC<GiftCardCustomerSelectFieldProps> = ({
|
||||
selectedCustomer,
|
||||
setSelectedCustomer
|
||||
setSelectedCustomer,
|
||||
disabled = false
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -54,6 +56,7 @@ const GiftCardCustomerSelectField: React.FC<GiftCardCustomerSelectFieldProps> =
|
|||
fetchChoices={search}
|
||||
onChange={handleSelect}
|
||||
onFetchMore={loadMore}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
export * from "./GiftCardCreateDialog";
|
||||
export { default } from "./GiftCardCreateDialog";
|
||||
export * from "./GiftCardCreateDialogContent";
|
||||
export { default } from "./GiftCardCreateDialogContent";
|
||||
|
|
|
@ -1,53 +1,79 @@
|
|||
import { defineMessages } from "react-intl";
|
||||
|
||||
export const giftCardCreateDialogMessages = defineMessages({
|
||||
export const giftCardCreateMessages = defineMessages({
|
||||
title: {
|
||||
defaultMessage: "Issue gift card",
|
||||
description: "GiftCardCreateDialog title"
|
||||
description: "issue gift card dialog title"
|
||||
},
|
||||
amountLabel: {
|
||||
defaultMessage: "Enter amount",
|
||||
description: "GiftCardCreateDialog amount label"
|
||||
description: "money amount input label"
|
||||
},
|
||||
issueButtonLabel: {
|
||||
defaultMessage: "Issue",
|
||||
description: "GiftCardCreateDialog issue button label"
|
||||
description: "issue gift card button label"
|
||||
},
|
||||
customerLabel: {
|
||||
defaultMessage: "Customer",
|
||||
description: "GiftCardCreateDialog customer label"
|
||||
description: "customer input label"
|
||||
},
|
||||
noteLabel: {
|
||||
defaultMessage: "Note",
|
||||
description: "GiftCardCreateDialog note label"
|
||||
description: "note input label"
|
||||
},
|
||||
noteSubtitle: {
|
||||
defaultMessage:
|
||||
"Why was this gift card issued. This note will not be shown to the customer. Note will be stored in gift card history",
|
||||
description: "GiftCardCreateDialog note subtitle"
|
||||
description: "note input subtitle"
|
||||
},
|
||||
createdGiftCardLabel: {
|
||||
defaultMessage: "This is the code of a created gift card:",
|
||||
description: "GiftCardCreateDialog created gift card label"
|
||||
description: "created gift card code label"
|
||||
},
|
||||
copyCodeLabel: {
|
||||
defaultMessage: "Copy code",
|
||||
description: "GiftCardCreateDialog copy code label"
|
||||
description: "copy code button label"
|
||||
},
|
||||
copiedToClipboardTitle: {
|
||||
defaultMessage: "Copied to clipboard",
|
||||
description: "GiftCardCreateDialog copied to clipboard title"
|
||||
description: "copied to clipboard alert title"
|
||||
},
|
||||
createdSuccessAlertTitle: {
|
||||
defaultMessage: "Successfully created gift card",
|
||||
description: "GiftCardCreateDialog createdSuccessAlertTitle"
|
||||
description: "successfully created gift card alert title"
|
||||
},
|
||||
requiresActivationLabel: {
|
||||
defaultMessage: "Requires activation",
|
||||
description: "GiftCarUpdateDetailsExpirySection requires activation label"
|
||||
description: "requires activation checkbox label"
|
||||
},
|
||||
requiresActivationCaption: {
|
||||
defaultMessage: "All issued cards require activation by staff before use.",
|
||||
description: "GiftCarUpdateDetailsExpirySection requires activation caption"
|
||||
description: "requires activation checkbox caption"
|
||||
},
|
||||
giftCardsAmountLabel: {
|
||||
defaultMessage: "Cards Issued",
|
||||
description: "issued cards amount label"
|
||||
},
|
||||
bulkCreateExplanation: {
|
||||
defaultMessage:
|
||||
"After creation Saleor will create a list of gift card codes that you will be able to download. ",
|
||||
description: "gift card bulk create modal bottom explanation"
|
||||
},
|
||||
bulkCreateIssuedTitle: {
|
||||
defaultMessage: "Bulk Issue Gift Cards",
|
||||
description: "gift card bulk create success dialog title"
|
||||
},
|
||||
bulkCreateIssuedExplanation: {
|
||||
defaultMessage:
|
||||
"We have issued all of your requested gift cards. You can download the list of new gift cards using the button below.",
|
||||
description: "gift card bulk create success dialog content"
|
||||
},
|
||||
bulkCreateIssuedAccept: {
|
||||
defaultMessage: "Ok",
|
||||
description: "gift card bulk create success dialog accept button"
|
||||
},
|
||||
bulkCreateIssuedExportToEmail: {
|
||||
defaultMessage: "Export To Email",
|
||||
description: "gift card bulk create success dialog export button"
|
||||
}
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ export const useGiftCardCreateDialogCodeContentStyles = makeStyles(
|
|||
{ name: "GiftCardCreateDialogCodeContent" }
|
||||
);
|
||||
|
||||
export const useGiftCardCreateDialogFormStyles = makeStyles(
|
||||
export const useGiftCardCreateFormStyles = makeStyles(
|
||||
() => ({
|
||||
noteField: {
|
||||
width: "100%"
|
||||
|
@ -19,7 +19,12 @@ export const useGiftCardCreateDialogFormStyles = makeStyles(
|
|||
currencySelectField: {
|
||||
width: 100
|
||||
},
|
||||
balanceContainer: { width: "100%" }
|
||||
fullWidthContainer: { width: "100%" },
|
||||
dialogContent: {
|
||||
minWidth: 550,
|
||||
overflowY: "auto",
|
||||
overflowX: "hidden"
|
||||
}
|
||||
}),
|
||||
{ name: "GiftCardCreateDialogForm" }
|
||||
);
|
||||
|
|
|
@ -10,13 +10,17 @@ export interface GiftCardCreateFormCustomer {
|
|||
email: string;
|
||||
}
|
||||
|
||||
export type GiftCardCreateFormErrors = Record<
|
||||
"tag" | "expiryDate" | "customer" | "currency" | "amount" | "balance",
|
||||
export type GiftCardCreateCommonFormErrors = Record<
|
||||
"tags" | "expiryDate" | "currency" | "amount" | "balance",
|
||||
GiftCardError
|
||||
>;
|
||||
|
||||
export type GiftCardCreateFormErrors = GiftCardCreateCommonFormErrors &
|
||||
Record<"customer", GiftCardError>;
|
||||
|
||||
export interface GiftCardCreateFormCommonProps {
|
||||
change: FormChange;
|
||||
toggleValue: FormChange;
|
||||
errors: GiftCardCreateFormErrors;
|
||||
data: GiftCardCreateFormData;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
import { IMessage } from "@saleor/components/messages";
|
||||
import { TimePeriodTypeEnum } from "@saleor/types/globalTypes";
|
||||
import commonErrorMessages from "@saleor/utils/errors/common";
|
||||
import moment from "moment-timezone";
|
||||
import { IntlShape } from "react-intl";
|
||||
|
||||
import { GiftCardCreateFormData } from "./GiftCardCreateDialogForm";
|
||||
import { GiftCardCreateCommonFormData } from "../GiftCardBulkCreateDialog/types";
|
||||
import { giftCardUpdateFormMessages } from "../GiftCardsList/messages";
|
||||
import { giftCardCreateMessages as messages } from "./messages";
|
||||
import { GiftCardCreate_giftCardCreate_errors } from "./types/GiftCardCreate";
|
||||
|
||||
const addToCurrentDate = (
|
||||
currentDate: number,
|
||||
|
@ -28,6 +34,39 @@ export const getExpiryPeriodTerminationDate = (
|
|||
}
|
||||
};
|
||||
|
||||
export const getGiftCardExpiryError = (intl: IntlShape): IMessage => ({
|
||||
title: intl.formatMessage(
|
||||
giftCardUpdateFormMessages.giftCardInvalidExpiryDateHeader
|
||||
),
|
||||
text: intl.formatMessage(
|
||||
giftCardUpdateFormMessages.giftCardInvalidExpiryDateContent
|
||||
),
|
||||
status: "error"
|
||||
});
|
||||
|
||||
export const getGiftCardCreateOnCompletedMessage = (
|
||||
errors: GiftCardCreate_giftCardCreate_errors[],
|
||||
intl: IntlShape,
|
||||
successMessage?: IMessage
|
||||
): IMessage => {
|
||||
const hasExpiryError = errors.some(error => error.field === "expiryDate");
|
||||
const successGiftCardMessage = successMessage || {
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.createdSuccessAlertTitle)
|
||||
};
|
||||
|
||||
if (hasExpiryError) {
|
||||
return getGiftCardExpiryError(intl);
|
||||
}
|
||||
|
||||
return !!errors?.length
|
||||
? {
|
||||
status: "error",
|
||||
text: intl.formatMessage(commonErrorMessages.unknownError)
|
||||
}
|
||||
: successGiftCardMessage;
|
||||
};
|
||||
|
||||
export const getGiftCardExpiryInputData = (
|
||||
{
|
||||
expirySelected,
|
||||
|
@ -35,7 +74,7 @@ export const getGiftCardExpiryInputData = (
|
|||
expiryDate,
|
||||
expiryPeriodAmount,
|
||||
expiryPeriodType
|
||||
}: GiftCardCreateFormData,
|
||||
}: GiftCardCreateCommonFormData,
|
||||
currentDate: number
|
||||
): string => {
|
||||
if (!expirySelected) {
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
import {
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Typography
|
||||
} from "@material-ui/core";
|
||||
import ConfirmButton from "@saleor/components/ConfirmButton";
|
||||
import { Task } from "@saleor/containers/BackgroundTasks/types";
|
||||
import useBackgroundTask from "@saleor/hooks/useBackgroundTask";
|
||||
import useForm from "@saleor/hooks/useForm";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import ExportDialogSettings from "@saleor/products/components/ProductExportDialog/ExportDialogSettings";
|
||||
import {
|
||||
ExportSettingsFormData,
|
||||
exportSettingsInitialFormData,
|
||||
exportSettingsInitialFormDataWithIds
|
||||
} from "@saleor/products/components/ProductExportDialog/types";
|
||||
import { DialogProps } from "@saleor/types";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import ContentWithProgress from "../GiftCardCreateDialog/ContentWithProgress";
|
||||
import useGiftCardList from "../GiftCardsList/providers/GiftCardListProvider/hooks/useGiftCardList";
|
||||
import useGiftCardListBulkActions from "../GiftCardsList/providers/GiftCardListProvider/hooks/useGiftCardListBulkActions";
|
||||
import { useGiftCardTotalCountQuery } from "../GiftCardsList/queries";
|
||||
import { giftCardExportDialogMessages as messages } from "./messages";
|
||||
import { useGiftCardExportMutation } from "./mutations";
|
||||
import { ExportGiftCards } from "./types/ExportGiftCards";
|
||||
import { getExportGiftCardsInput } from "./utils";
|
||||
|
||||
const GiftCardExportDialog: React.FC<Pick<DialogProps, "onClose"> & {
|
||||
idsToExport?: string[] | null;
|
||||
}> = ({ onClose, idsToExport }) => {
|
||||
const intl = useIntl();
|
||||
const notify = useNotifier();
|
||||
const { queue } = useBackgroundTask();
|
||||
|
||||
const hasIdsToExport = !!idsToExport?.length;
|
||||
|
||||
const {
|
||||
loading: loadingGiftCardList,
|
||||
totalCount: filteredGiftCardsCount
|
||||
} = useGiftCardList();
|
||||
|
||||
const { listElements } = useGiftCardListBulkActions();
|
||||
|
||||
const selectedIds = idsToExport ?? listElements;
|
||||
|
||||
const {
|
||||
data: allGiftCardsCountData,
|
||||
loading: loadingGiftCardCount
|
||||
} = useGiftCardTotalCountQuery();
|
||||
|
||||
const loading = loadingGiftCardList || loadingGiftCardCount;
|
||||
|
||||
const handleSubmitComplete = (data: ExportGiftCards) => {
|
||||
const errors = data?.exportGiftCards?.errors;
|
||||
|
||||
if (!errors.length) {
|
||||
notify({
|
||||
text: intl.formatMessage(messages.successAlertDescription),
|
||||
title: intl.formatMessage(messages.successAlertTitle)
|
||||
});
|
||||
|
||||
queue(Task.EXPORT, {
|
||||
id: data.exportGiftCards.exportFile.id
|
||||
});
|
||||
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
const [exportGiftCards, exportGiftCardsOpts] = useGiftCardExportMutation({
|
||||
onCompleted: handleSubmitComplete
|
||||
});
|
||||
|
||||
const handleSubmit = (data: ExportSettingsFormData) => {
|
||||
exportGiftCards({
|
||||
variables: {
|
||||
input: getExportGiftCardsInput({
|
||||
data,
|
||||
ids: selectedIds
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const { data, change, submit } = useForm(
|
||||
hasIdsToExport
|
||||
? exportSettingsInitialFormDataWithIds
|
||||
: exportSettingsInitialFormData,
|
||||
handleSubmit
|
||||
);
|
||||
const allGiftCardsCount = allGiftCardsCountData?.giftCards?.totalCount;
|
||||
|
||||
const exportScopeLabels = {
|
||||
allItems: intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "All gift cards ({number})",
|
||||
description: "export all items to csv file"
|
||||
},
|
||||
{
|
||||
number: allGiftCardsCount || "..."
|
||||
}
|
||||
),
|
||||
selectedItems: intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Selected giftCards ({number})",
|
||||
description: "export selected items to csv file"
|
||||
},
|
||||
{
|
||||
number: listElements.length
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DialogTitle>
|
||||
<FormattedMessage {...messages.title} />
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<ContentWithProgress>
|
||||
{!loading && (
|
||||
<>
|
||||
<ExportDialogSettings
|
||||
errors={exportGiftCardsOpts?.data?.exportGiftCards?.errors}
|
||||
onChange={change}
|
||||
selectedItems={selectedIds?.length}
|
||||
data={data}
|
||||
exportScopeLabels={exportScopeLabels}
|
||||
allowScopeSelection={!hasIdsToExport}
|
||||
itemsQuantity={{
|
||||
filter: filteredGiftCardsCount,
|
||||
all: allGiftCardsCount
|
||||
}}
|
||||
/>
|
||||
<Typography variant="subtitle2">
|
||||
{intl.formatMessage(messages.exportNote)}
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
</ContentWithProgress>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<ConfirmButton
|
||||
transitionState={exportGiftCardsOpts.status}
|
||||
variant="contained"
|
||||
type="submit"
|
||||
data-test="submit"
|
||||
onClick={submit}
|
||||
>
|
||||
<FormattedMessage {...messages.confirmButtonLabel} />
|
||||
</ConfirmButton>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GiftCardExportDialog;
|
2
src/giftCards/GiftCardExportDialogContent/index.tsx
Normal file
2
src/giftCards/GiftCardExportDialogContent/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
|||
export * from "./GiftCardExportDialogContent";
|
||||
export { default } from "./GiftCardExportDialogContent";
|
29
src/giftCards/GiftCardExportDialogContent/messages.ts
Normal file
29
src/giftCards/GiftCardExportDialogContent/messages.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { defineMessages } from "react-intl";
|
||||
|
||||
export const giftCardExportDialogMessages = defineMessages({
|
||||
title: {
|
||||
defaultMessage: "Export Gift Card Codes",
|
||||
description: "gift card export dialog title"
|
||||
},
|
||||
exportTypeLabel: {
|
||||
defaultMessage: "gift cards",
|
||||
description: "gift card export type label"
|
||||
},
|
||||
confirmButtonLabel: {
|
||||
defaultMessage: "Export codes",
|
||||
description: "gift card export dialog confirm button label"
|
||||
},
|
||||
successAlertDescription: {
|
||||
defaultMessage:
|
||||
"We are currently exporting your gift card codes. As soon as your file is available it will be sent to your email address",
|
||||
description: "gift card export success alert description"
|
||||
},
|
||||
successAlertTitle: {
|
||||
defaultMessage: "Exporting CSV",
|
||||
description: "gift card export csv success alert title"
|
||||
},
|
||||
exportNote: {
|
||||
defaultMessage: "Note: Only active and not used gift cards will be expored",
|
||||
description: "note on export gift cards"
|
||||
}
|
||||
});
|
27
src/giftCards/GiftCardExportDialogContent/mutations.ts
Normal file
27
src/giftCards/GiftCardExportDialogContent/mutations.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { exportErrorFragment } from "@saleor/fragments/errors";
|
||||
import makeMutation from "@saleor/hooks/makeMutation";
|
||||
import gql from "graphql-tag";
|
||||
|
||||
import {
|
||||
ExportGiftCards,
|
||||
ExportGiftCardsVariables
|
||||
} from "./types/ExportGiftCards";
|
||||
|
||||
const exportGiftCards = gql`
|
||||
${exportErrorFragment}
|
||||
mutation ExportGiftCards($input: ExportGiftCardsInput!) {
|
||||
exportGiftCards(input: $input) {
|
||||
errors {
|
||||
...ExportErrorFragment
|
||||
}
|
||||
exportFile {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const useGiftCardExportMutation = makeMutation<
|
||||
ExportGiftCards,
|
||||
ExportGiftCardsVariables
|
||||
>(exportGiftCards);
|
|
@ -0,0 +1,35 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { ExportGiftCardsInput, ExportErrorCode } from "../../../types/globalTypes";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL mutation operation: ExportGiftCards
|
||||
// ====================================================
|
||||
|
||||
export interface ExportGiftCards_exportGiftCards_errors {
|
||||
__typename: "ExportError";
|
||||
code: ExportErrorCode;
|
||||
field: string | null;
|
||||
}
|
||||
|
||||
export interface ExportGiftCards_exportGiftCards_exportFile {
|
||||
__typename: "ExportFile";
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface ExportGiftCards_exportGiftCards {
|
||||
__typename: "ExportGiftCards";
|
||||
errors: ExportGiftCards_exportGiftCards_errors[];
|
||||
exportFile: ExportGiftCards_exportGiftCards_exportFile | null;
|
||||
}
|
||||
|
||||
export interface ExportGiftCards {
|
||||
exportGiftCards: ExportGiftCards_exportGiftCards | null;
|
||||
}
|
||||
|
||||
export interface ExportGiftCardsVariables {
|
||||
input: ExportGiftCardsInput;
|
||||
}
|
27
src/giftCards/GiftCardExportDialogContent/utils.ts
Normal file
27
src/giftCards/GiftCardExportDialogContent/utils.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { ExportSettingsFormData } from "@saleor/products/components/ProductExportDialog/types";
|
||||
import { ExportScope } from "@saleor/types/globalTypes";
|
||||
|
||||
interface ExportGiftCardsInputProps {
|
||||
ids: string[] | null;
|
||||
data: ExportSettingsFormData;
|
||||
}
|
||||
|
||||
export const getExportGiftCardsInput = ({
|
||||
data,
|
||||
ids
|
||||
}: ExportGiftCardsInputProps) => {
|
||||
const { scope, fileType } = data;
|
||||
|
||||
if (scope === ExportScope.IDS) {
|
||||
return {
|
||||
fileType,
|
||||
scope,
|
||||
ids
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
fileType,
|
||||
scope
|
||||
};
|
||||
};
|
|
@ -3,10 +3,11 @@ import { defineMessages } from "react-intl";
|
|||
export const giftCardExpirySettingsCard = defineMessages({
|
||||
expiryDateSectionDescription: {
|
||||
defaultMessage:
|
||||
"You can set gift cards to expire after a certain time after their purchase. Remember that in some countries, gift cards expiry is prohibited by law."
|
||||
"You can set gift cards to expire after a certain time after their purchase. Remember that in some countries, gift cards expiry is prohibited by law.",
|
||||
description: "expiry date selection info message"
|
||||
},
|
||||
expiryDateTitle: {
|
||||
defaultMessage: "Expiry date",
|
||||
description: "section header"
|
||||
description: "expiry date section header"
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@ import { defineMessages, IntlShape } from "react-intl";
|
|||
export const giftCardSettingsPageMessages = defineMessages({
|
||||
title: {
|
||||
defaultMessage: "Gift Cards Settings",
|
||||
description: "header"
|
||||
description: "gift card settings header"
|
||||
}
|
||||
});
|
||||
|
||||
|
|
226
src/giftCards/GiftCardUpdate/GiftCardHistory/GiftCardHistory.tsx
Normal file
226
src/giftCards/GiftCardUpdate/GiftCardHistory/GiftCardHistory.tsx
Normal file
|
@ -0,0 +1,226 @@
|
|||
import { Typography } from "@material-ui/core";
|
||||
import { appPath } from "@saleor/apps/urls";
|
||||
import Form from "@saleor/components/Form";
|
||||
import Hr from "@saleor/components/Hr";
|
||||
import Link from "@saleor/components/Link";
|
||||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import Timeline, {
|
||||
TimelineAddNote,
|
||||
TimelineEvent,
|
||||
TimelineNote
|
||||
} from "@saleor/components/Timeline";
|
||||
import { customerPath } from "@saleor/customers/urls";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { orderPath } from "@saleor/orders/urls";
|
||||
import { staffMemberDetailsPath } from "@saleor/staff/urls";
|
||||
import { GiftCardEventsEnum } from "@saleor/types/globalTypes";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { IntlShape } from "react-intl";
|
||||
|
||||
import { useGiftCardTimelineNoteAddMutation } from "../mutations";
|
||||
import { GIFT_CARD_DETAILS_QUERY } from "../queries";
|
||||
import { GiftCardAddNote } from "../types/GiftCardAddNote";
|
||||
import { GiftCardDetails_giftCard_events } from "../types/GiftCardDetails";
|
||||
import useGiftCardHistoryEvents from "./hooks/useGiftCardHistoryEvents";
|
||||
import {
|
||||
giftCardHistoryMessages as messages,
|
||||
giftCardHistoryTimelineMessages as timelineMessages
|
||||
} from "./messages";
|
||||
import useStyles from "./styles";
|
||||
|
||||
interface FormData {
|
||||
message: string;
|
||||
}
|
||||
|
||||
const getEventMessage = (
|
||||
event: GiftCardDetails_giftCard_events,
|
||||
intl: IntlShape
|
||||
) => {
|
||||
const getUserOrApp = () => {
|
||||
if (event.user) {
|
||||
const { firstName, lastName, email } = event.user;
|
||||
|
||||
if (lastName === "" || firstName === "") {
|
||||
return email;
|
||||
}
|
||||
|
||||
return `${firstName} ${lastName}`;
|
||||
}
|
||||
|
||||
if (event.app) {
|
||||
return event.app.name;
|
||||
}
|
||||
};
|
||||
|
||||
const getUserOrAppLink = () => {
|
||||
if (event.user) {
|
||||
return customerPath(event.user.id);
|
||||
}
|
||||
|
||||
if (event.app) {
|
||||
return appPath(event.app.id);
|
||||
}
|
||||
};
|
||||
|
||||
switch (event.type) {
|
||||
case GiftCardEventsEnum.ACTIVATED:
|
||||
return intl.formatMessage(timelineMessages.giftCardActivated, {
|
||||
activatedBy: (
|
||||
<Link href={staffMemberDetailsPath(event.user.id)}>
|
||||
{getUserOrApp()}
|
||||
</Link>
|
||||
)
|
||||
});
|
||||
case GiftCardEventsEnum.BALANCE_RESET:
|
||||
return intl.formatMessage(timelineMessages.giftCardBalanceReset, {
|
||||
resetBy: (
|
||||
<Link href={staffMemberDetailsPath(event.user.id)}>
|
||||
{getUserOrApp()}
|
||||
</Link>
|
||||
)
|
||||
});
|
||||
case GiftCardEventsEnum.BOUGHT:
|
||||
return intl.formatMessage(timelineMessages.giftCardBought, {
|
||||
orderNumber: (
|
||||
<Link href={orderPath(event.orderId)}>#{event.orderNumber}</Link>
|
||||
)
|
||||
});
|
||||
case GiftCardEventsEnum.DEACTIVATED:
|
||||
return intl.formatMessage(timelineMessages.giftCardDeactivated, {
|
||||
deactivatedBy: (
|
||||
<Link href={staffMemberDetailsPath(event.user.id)}>
|
||||
{getUserOrApp()}
|
||||
</Link>
|
||||
)
|
||||
});
|
||||
case GiftCardEventsEnum.EXPIRY_DATE_UPDATED:
|
||||
return intl.formatMessage(timelineMessages.giftCardExpiryDateUpdate, {
|
||||
expiryUpdatedBy: (
|
||||
<Link href={staffMemberDetailsPath(event.user.id)}>
|
||||
{getUserOrApp()}
|
||||
</Link>
|
||||
)
|
||||
});
|
||||
case GiftCardEventsEnum.ISSUED:
|
||||
return intl.formatMessage(timelineMessages.giftCardIssued, {
|
||||
issuedBy: (
|
||||
<Link href={staffMemberDetailsPath(event.user.id)}>
|
||||
{getUserOrApp()}
|
||||
</Link>
|
||||
)
|
||||
});
|
||||
case GiftCardEventsEnum.RESENT:
|
||||
return intl.formatMessage(timelineMessages.giftCardResent);
|
||||
case GiftCardEventsEnum.SENT_TO_CUSTOMER:
|
||||
return intl.formatMessage(timelineMessages.giftCardSentToCustomer);
|
||||
case GiftCardEventsEnum.TAGS_UPDATED:
|
||||
return intl.formatMessage(timelineMessages.giftCardTagsUpdated);
|
||||
case GiftCardEventsEnum.UPDATED:
|
||||
return intl.formatMessage(timelineMessages.giftCardTagsUpdated);
|
||||
case GiftCardEventsEnum.USED_IN_ORDER:
|
||||
return intl.formatMessage(timelineMessages.giftCardUsedInOrder, {
|
||||
orderLink: (
|
||||
<Link href={orderPath(event.orderId)}>#{event.orderNumber}</Link>
|
||||
),
|
||||
buyer: content =>
|
||||
getUserOrApp() ? (
|
||||
<Link
|
||||
href={getUserOrAppLink()}
|
||||
>{`${content} ${getUserOrApp()}`}</Link>
|
||||
) : null
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const GiftCardHistory: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const notify = useNotifier();
|
||||
const { id, events } = useGiftCardHistoryEvents();
|
||||
const classes = useStyles();
|
||||
|
||||
const onTimelineNoteAddCompleted = ({ giftCardAddNote }: GiftCardAddNote) => {
|
||||
const { errors } = giftCardAddNote;
|
||||
|
||||
if (errors.length > 0) {
|
||||
notify({
|
||||
status: "error",
|
||||
text: intl.formatMessage(messages.noteAddError)
|
||||
});
|
||||
} else {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.noteAddedSuccessfully)
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const [addTimelineNote, { loading }] = useGiftCardTimelineNoteAddMutation({
|
||||
refetchQueries: [GIFT_CARD_DETAILS_QUERY],
|
||||
onCompleted: onTimelineNoteAddCompleted
|
||||
});
|
||||
|
||||
const onNoteAdd = (data: FormData) => {
|
||||
const { message } = data;
|
||||
addTimelineNote({ variables: { id, input: { message } } });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Typography className={classes.header} color="textSecondary">
|
||||
<FormattedMessage {...messages.historyHeaderTitle} />
|
||||
</Typography>
|
||||
<Hr />
|
||||
<Timeline>
|
||||
<Skeleton>
|
||||
{events && (
|
||||
<>
|
||||
<Form
|
||||
initial={{ message: "" }}
|
||||
onSubmit={onNoteAdd}
|
||||
resetOnSubmit
|
||||
>
|
||||
{({ change, data, reset, submit }) => (
|
||||
<TimelineAddNote
|
||||
message={data.message}
|
||||
reset={reset}
|
||||
onChange={change}
|
||||
onSubmit={submit}
|
||||
disabled={loading}
|
||||
/>
|
||||
)}
|
||||
</Form>
|
||||
{events
|
||||
.slice()
|
||||
.reverse()
|
||||
.map(event => {
|
||||
const { id, message, type, date, user } = event;
|
||||
|
||||
if (type === GiftCardEventsEnum.NOTE_ADDED) {
|
||||
return (
|
||||
<TimelineNote
|
||||
date={date}
|
||||
user={user}
|
||||
message={message}
|
||||
key={id}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<TimelineEvent
|
||||
key={id}
|
||||
date={date}
|
||||
title={getEventMessage(event, intl)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</Skeleton>
|
||||
</Timeline>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GiftCardHistory;
|
|
@ -0,0 +1,14 @@
|
|||
import { useContext } from "react";
|
||||
|
||||
import { GiftCardDetailsContext } from "../../providers/GiftCardDetailsProvider";
|
||||
|
||||
const useGiftCardHistoryEvents = () => {
|
||||
const { giftCard } = useContext(GiftCardDetailsContext);
|
||||
|
||||
return {
|
||||
id: giftCard?.id,
|
||||
events: giftCard?.events
|
||||
};
|
||||
};
|
||||
|
||||
export default useGiftCardHistoryEvents;
|
62
src/giftCards/GiftCardUpdate/GiftCardHistory/messages.ts
Normal file
62
src/giftCards/GiftCardUpdate/GiftCardHistory/messages.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
import { defineMessages } from "react-intl";
|
||||
|
||||
const giftCardHistoryMessages = defineMessages({
|
||||
noteAddedSuccessfully: {
|
||||
defaultMessage: "Note was added sucessfully",
|
||||
description: "notifier message"
|
||||
},
|
||||
noteAddError: {
|
||||
defaultMessage: "There was an error adding a note",
|
||||
description: "notifier message"
|
||||
},
|
||||
historyHeaderTitle: {
|
||||
defaultMessage: "Gift Card Timeline",
|
||||
description: "section header title"
|
||||
}
|
||||
});
|
||||
|
||||
const giftCardHistoryTimelineMessages = defineMessages({
|
||||
giftCardActivated: {
|
||||
defaultMessage: "Gift card was activated by {activatedBy}",
|
||||
description: "gift card history message"
|
||||
},
|
||||
giftCardBalanceReset: {
|
||||
defaultMessage: "Gift card balance was reset by {resetBy}",
|
||||
description: "gift card history message"
|
||||
},
|
||||
giftCardBought: {
|
||||
defaultMessage: "Gift card was bought in order {orderNumber}",
|
||||
description: "gift card history message"
|
||||
},
|
||||
giftCardDeactivated: {
|
||||
defaultMessage: "Gift card was deactivated by {deactivatedBy}",
|
||||
description: "gift card history message"
|
||||
},
|
||||
giftCardExpiryDateUpdate: {
|
||||
defaultMessage: "Gift card expiry date was updated by {expiryUpdatedBy}",
|
||||
description: "gift card history message"
|
||||
},
|
||||
giftCardIssued: {
|
||||
defaultMessage: "Gift card was issued by {issuedBy}",
|
||||
description: "dsc"
|
||||
},
|
||||
giftCardResent: {
|
||||
defaultMessage: "Gift card was resent",
|
||||
description: "gift card history message"
|
||||
},
|
||||
giftCardSentToCustomer: {
|
||||
defaultMessage: "Gift card was sent to customer",
|
||||
description: "gift card history message"
|
||||
},
|
||||
giftCardTagsUpdated: {
|
||||
defaultMessage: "Gift card tags were updated",
|
||||
description: "gift card history message"
|
||||
},
|
||||
giftCardUsedInOrder: {
|
||||
defaultMessage:
|
||||
"Gift card was used as a payment method on order {orderLink} <buyer>by</buyer>",
|
||||
description: "gift card history message"
|
||||
}
|
||||
});
|
||||
|
||||
export { giftCardHistoryMessages, giftCardHistoryTimelineMessages };
|
14
src/giftCards/GiftCardUpdate/GiftCardHistory/styles.ts
Normal file
14
src/giftCards/GiftCardUpdate/GiftCardHistory/styles.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { makeStyles } from "@saleor/macaw-ui";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
header: {
|
||||
fontWeight: 500,
|
||||
marginBottom: theme.spacing(1)
|
||||
},
|
||||
root: { marginTop: theme.spacing(4) }
|
||||
}),
|
||||
{ name: "GiftCardHistory" }
|
||||
);
|
||||
|
||||
export default useStyles;
|
|
@ -9,8 +9,8 @@ import SingleAutocompleteSelectField from "@saleor/components/SingleAutocomplete
|
|||
import useForm from "@saleor/hooks/useForm";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { getBySlug } from "@saleor/products/components/ProductVariantCreatorPage/utils";
|
||||
import { DialogProps } from "@saleor/types";
|
||||
import commonErrorMessages from "@saleor/utils/errors/common";
|
||||
import { DialogActionHandlersProps } from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import { mapSlugNodeToChoice } from "@saleor/utils/maps";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
@ -29,10 +29,7 @@ export interface GiftCardResendCodeFormData {
|
|||
channelSlug: string;
|
||||
}
|
||||
|
||||
const GiftCardResendCodeDialog: React.FC<DialogActionHandlersProps> = ({
|
||||
open,
|
||||
closeDialog
|
||||
}) => {
|
||||
const GiftCardResendCodeDialog: React.FC<DialogProps> = ({ open, onClose }) => {
|
||||
const intl = useIntl();
|
||||
const notify = useNotifier();
|
||||
const classes = useStyles();
|
||||
|
@ -99,7 +96,7 @@ const GiftCardResendCodeDialog: React.FC<DialogActionHandlersProps> = ({
|
|||
notify(notifierData);
|
||||
|
||||
if (!errors.length) {
|
||||
closeDialog();
|
||||
onClose();
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
@ -128,7 +125,7 @@ const GiftCardResendCodeDialog: React.FC<DialogActionHandlersProps> = ({
|
|||
open={open}
|
||||
onConfirm={submit}
|
||||
confirmButtonLabel={intl.formatMessage(messages.submitButtonLabel)}
|
||||
onClose={closeDialog}
|
||||
onClose={onClose}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
confirmButtonState={status}
|
||||
disabled={loading}
|
||||
|
|
|
@ -3,31 +3,31 @@ import { defineMessages } from "react-intl";
|
|||
export const giftCardResendCodeDialogMessages = defineMessages({
|
||||
title: {
|
||||
defaultMessage: "Resend code to customer",
|
||||
description: "GiftCardResendCodeDialog title"
|
||||
description: "resend code to customer title"
|
||||
},
|
||||
description: {
|
||||
defaultMessage:
|
||||
"Gift Card Code will be resent to email provided during checkout. You can provide a different email address if you want to:",
|
||||
description: "GiftCardResendCodeDialog description"
|
||||
description: "resend code to customer description"
|
||||
},
|
||||
consentCheckboxLabel: {
|
||||
defaultMessage: "Yes, I want to send gift card to different address",
|
||||
description: "GiftCardResendCodeDialog consentCheckboxLabel"
|
||||
description: "consent to send gift card to different address checkbox label"
|
||||
},
|
||||
submitButtonLabel: {
|
||||
defaultMessage: "Resend",
|
||||
description: "GiftCardResendCodeDialog submitButtonLabel"
|
||||
description: "resend button label"
|
||||
},
|
||||
emailInputPlaceholder: {
|
||||
defaultMessage: "Provided email address",
|
||||
description: "GiftCardResendCodeDialog emailInputPlaceholder"
|
||||
description: "provided email input placeholder"
|
||||
},
|
||||
successResendAlertText: {
|
||||
defaultMessage: "Successfully resent code to customer!",
|
||||
description: "GiftCardResendCodeDialog successResendAlertText"
|
||||
description: "resent code success message"
|
||||
},
|
||||
sendToChannelSelectLabel: {
|
||||
defaultMessage: "Send to channel",
|
||||
description: "ChannelPickerSelectField sendToChannelLabel"
|
||||
description: "send to channel select label"
|
||||
}
|
||||
});
|
||||
|
|
|
@ -65,11 +65,16 @@ export interface GiftCardResend_giftCardResend_giftCard_currentBalance {
|
|||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardResend_giftCardResend_giftCard_tags {
|
||||
__typename: "GiftCardTag";
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GiftCardResend_giftCardResend_giftCard {
|
||||
__typename: "GiftCard";
|
||||
metadata: (GiftCardResend_giftCardResend_giftCard_metadata | null)[];
|
||||
privateMetadata: (GiftCardResend_giftCardResend_giftCard_privateMetadata | null)[];
|
||||
displayCode: string;
|
||||
last4CodeChars: string;
|
||||
boughtInChannel: string | null;
|
||||
createdBy: GiftCardResend_giftCardResend_giftCard_createdBy | null;
|
||||
product: GiftCardResend_giftCardResend_giftCard_product | null;
|
||||
|
@ -84,7 +89,7 @@ export interface GiftCardResend_giftCardResend_giftCard {
|
|||
initialBalance: GiftCardResend_giftCardResend_giftCard_initialBalance | null;
|
||||
currentBalance: GiftCardResend_giftCardResend_giftCard_currentBalance | null;
|
||||
id: string;
|
||||
tag: string | null;
|
||||
tags: GiftCardResend_giftCardResend_giftCard_tags[] | null;
|
||||
}
|
||||
|
||||
export interface GiftCardResend_giftCardResend {
|
||||
|
|
|
@ -4,8 +4,8 @@ import CardSpacer from "@saleor/components/CardSpacer";
|
|||
import { IMessage } from "@saleor/components/messages";
|
||||
import useForm from "@saleor/hooks/useForm";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { DialogProps } from "@saleor/types";
|
||||
import commonErrorMessages from "@saleor/utils/errors/common";
|
||||
import { DialogActionHandlersProps } from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
|
@ -22,9 +22,9 @@ export interface GiftCardBalanceUpdateFormData {
|
|||
balanceAmount: number;
|
||||
}
|
||||
|
||||
const GiftCardUpdateBalanceDialog: React.FC<DialogActionHandlersProps> = ({
|
||||
const GiftCardUpdateBalanceDialog: React.FC<DialogProps> = ({
|
||||
open,
|
||||
closeDialog
|
||||
onClose
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
@ -57,7 +57,7 @@ const GiftCardUpdateBalanceDialog: React.FC<DialogActionHandlersProps> = ({
|
|||
notify(notifierData);
|
||||
|
||||
if (!errors.length) {
|
||||
closeDialog();
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -103,7 +103,7 @@ const GiftCardUpdateBalanceDialog: React.FC<DialogActionHandlersProps> = ({
|
|||
open={open}
|
||||
onConfirm={submit}
|
||||
confirmButtonLabel={intl.formatMessage(messages.changeButtonLabel)}
|
||||
onClose={closeDialog}
|
||||
onClose={onClose}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
confirmButtonState={status}
|
||||
disabled={loading || !hasChanged}
|
||||
|
|
|
@ -3,20 +3,19 @@ import { defineMessages } from "react-intl";
|
|||
export const giftCardUpdateBalanceDialogMessages = defineMessages({
|
||||
title: {
|
||||
defaultMessage: "Set balance",
|
||||
description: "GiftCardUpdateDetailsCard set balance button label"
|
||||
description: "set balance dialog title label"
|
||||
},
|
||||
subtitle: {
|
||||
defaultMessage:
|
||||
"What would you like to set cards balance to. When you change the balance both values will be changed",
|
||||
description: "GiftCardUpdateDetailsCard set balance dialog subtitle"
|
||||
description: "set balance dialog subtitle"
|
||||
},
|
||||
updatedSuccessAlertTitle: {
|
||||
defaultMessage: "Successfully updated card balance",
|
||||
description: "GiftCardUpdateDetailsCard update success alert title"
|
||||
description: "card update success alert title"
|
||||
},
|
||||
changeButtonLabel: {
|
||||
defaultMessage: "Change",
|
||||
description:
|
||||
"GiftCardUpdateDetailsCard set balance dialog change button label"
|
||||
description: "change button label"
|
||||
}
|
||||
});
|
||||
|
|
|
@ -26,8 +26,8 @@ const GiftCardUpdateDetailsCard: React.FC = () => {
|
|||
const { loading, giftCard } = useGiftCardDetails();
|
||||
const { openSetBalanceDialog } = useGiftCardUpdateDialogs();
|
||||
const {
|
||||
change,
|
||||
data: { tag },
|
||||
toggleValue,
|
||||
data: { tags },
|
||||
formErrors
|
||||
} = useGiftCardUpdateForm();
|
||||
|
||||
|
@ -61,10 +61,10 @@ const GiftCardUpdateDetailsCard: React.FC = () => {
|
|||
</Typography>
|
||||
<VerticalSpacer />
|
||||
<GiftCardTagInput
|
||||
error={formErrors?.tag}
|
||||
name="tag"
|
||||
value={tag}
|
||||
change={change}
|
||||
error={formErrors?.tags}
|
||||
name="tags"
|
||||
values={tags}
|
||||
toggleChange={toggleValue}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<GiftCardUpdateExpirySelect />
|
||||
|
|
|
@ -3,18 +3,18 @@ import { defineMessages } from "react-intl";
|
|||
export const giftCardUpdateDetailsCardMessages = defineMessages({
|
||||
title: {
|
||||
defaultMessage: "Details",
|
||||
description: "GiftCardUpdateDetailsCard title"
|
||||
description: "details title"
|
||||
},
|
||||
setBalanceButtonLabel: {
|
||||
defaultMessage: "set balance",
|
||||
description: "GiftCardUpdateDetailsCard set balance button label"
|
||||
description: "set balance button label"
|
||||
},
|
||||
cardBalanceLabel: {
|
||||
defaultMessage: "Card Balance",
|
||||
description: "GiftCardUpdateDetailsCard card balance label"
|
||||
description: "card balance label"
|
||||
},
|
||||
tagInputLabel: {
|
||||
defaultMessage: "Card Tag",
|
||||
description: "GiftCardTagInput tag label"
|
||||
description: "tag label"
|
||||
}
|
||||
});
|
||||
|
|
|
@ -3,14 +3,14 @@ import { defineMessages } from "react-intl";
|
|||
export const giftCardExpirySelectMessages = defineMessages({
|
||||
expiryDateCheckboxLabel: {
|
||||
defaultMessage: "Gift card expires",
|
||||
description: "GiftCarUpdateDetailsExpirySection expiry date checkbox label"
|
||||
description: "expiry date checkbox label"
|
||||
},
|
||||
expiryDateLabel: {
|
||||
defaultMessage: "Expiration date",
|
||||
description: "GiftCarUpdateDetailsExpirySection expiry date label"
|
||||
description: "expiration date label"
|
||||
},
|
||||
expiredOnLabel: {
|
||||
defaultMessage: "Expired on {date}",
|
||||
description: "GiftCarUpdateDetailsExpirySection expired on label"
|
||||
description: "expired on label"
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,7 +4,6 @@ import CardSpacer from "@saleor/components/CardSpacer";
|
|||
import Link from "@saleor/components/Link";
|
||||
import { customerUrl } from "@saleor/customers/urls";
|
||||
import useDateLocalize from "@saleor/hooks/useDateLocalize";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import { getFullName, getStringOrPlaceholder } from "@saleor/misc";
|
||||
import Label from "@saleor/orders/components/OrderHistory/Label";
|
||||
import { getOrderNumberLinkObject } from "@saleor/orders/components/OrderHistory/utils";
|
||||
|
@ -22,7 +21,6 @@ import { giftCardUpdateInfoCardMessages as messages } from "./messages";
|
|||
const GiftCardUpdateInfoCardContent: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const localizeDate = useDateLocalize();
|
||||
const navigate = useNavigator();
|
||||
|
||||
const { giftCard } = useGiftCardDetails();
|
||||
|
||||
|
@ -122,7 +120,7 @@ const GiftCardUpdateInfoCardContent: React.FC = () => {
|
|||
|
||||
<Label text={intl.formatMessage(messages.orderNumberLabel)} />
|
||||
{orderData ? (
|
||||
<Link onClick={() => navigate(orderData.link)}>{orderData.text}</Link>
|
||||
<Link href={orderData.link}>{orderData.text}</Link>
|
||||
) : (
|
||||
<Typography>{PLACEHOLDER}</Typography>
|
||||
)}
|
||||
|
@ -130,9 +128,7 @@ const GiftCardUpdateInfoCardContent: React.FC = () => {
|
|||
|
||||
<Label text={intl.formatMessage(messages.productLabel)} />
|
||||
{product ? (
|
||||
<Link onClick={() => navigate(productUrl(product?.id))}>
|
||||
{product?.name}
|
||||
</Link>
|
||||
<Link href={productUrl(product?.id)}>{product?.name}</Link>
|
||||
) : (
|
||||
<Typography>{PLACEHOLDER}</Typography>
|
||||
)}
|
||||
|
@ -140,7 +136,7 @@ const GiftCardUpdateInfoCardContent: React.FC = () => {
|
|||
|
||||
<Label text={intl.formatMessage(buyerLabelMessage)} />
|
||||
{buyerUrl ? (
|
||||
<Link onClick={() => navigate(buyerUrl)}>{buyerName}</Link>
|
||||
<Link href={buyerUrl}>{buyerName}</Link>
|
||||
) : (
|
||||
<Typography>{buyerName}</Typography>
|
||||
)}
|
||||
|
@ -148,9 +144,7 @@ const GiftCardUpdateInfoCardContent: React.FC = () => {
|
|||
|
||||
<Label text={intl.formatMessage(messages.usedByLabel)} />
|
||||
{usedBy ? (
|
||||
<Link onClick={() => navigate(customerUrl(usedBy.id))}>
|
||||
{getFullName(usedBy)}
|
||||
</Link>
|
||||
<Link href={customerUrl(usedBy.id)}>{getFullName(usedBy)}</Link>
|
||||
) : (
|
||||
<Typography>
|
||||
{getStringOrPlaceholder(usedByEmail, PLACEHOLDER)}
|
||||
|
|
|
@ -3,34 +3,34 @@ import { defineMessages } from "react-intl";
|
|||
export const giftCardUpdateInfoCardMessages = defineMessages({
|
||||
title: {
|
||||
defaultMessage: "Card information",
|
||||
description: "GiftCardUpdateInfoCard title"
|
||||
description: "info card title"
|
||||
},
|
||||
creationLabel: {
|
||||
defaultMessage: "Creation",
|
||||
description: "GiftCardUpdateInfoCard creation label"
|
||||
description: "creation label"
|
||||
},
|
||||
orderNumberLabel: {
|
||||
defaultMessage: "Order number",
|
||||
description: "GiftCardUpdateInfoCard order number label"
|
||||
description: "order number label"
|
||||
},
|
||||
productLabel: {
|
||||
defaultMessage: "Product bought to get gift card",
|
||||
description: "GiftCardUpdateInfoCard product label"
|
||||
description: "product label"
|
||||
},
|
||||
issuedByLabel: {
|
||||
defaultMessage: "Issued by",
|
||||
description: "GiftCardUpdateInfoCard issued by label"
|
||||
description: "issued by label"
|
||||
},
|
||||
issuedByAppLabel: {
|
||||
defaultMessage: "Issued by app",
|
||||
description: "GiftCardUpdateInfoCard issued by app label"
|
||||
description: "issued by app label"
|
||||
},
|
||||
boughtByLabel: {
|
||||
defaultMessage: "Bought by",
|
||||
description: "GiftCardUpdateInfoCard bought by label"
|
||||
description: "bought by label"
|
||||
},
|
||||
usedByLabel: {
|
||||
defaultMessage: "Used by",
|
||||
description: "GiftCardUpdateInfoCard used by label"
|
||||
description: "used by label"
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ import Metadata from "@saleor/components/Metadata";
|
|||
import Savebar from "@saleor/components/Savebar";
|
||||
import React from "react";
|
||||
|
||||
import GiftCardHistory from "./GiftCardHistory/GiftCardHistory";
|
||||
import GiftCardUpdateDetailsCard from "./GiftCardUpdateDetailsCard";
|
||||
import GiftCardUpdateInfoCard from "./GiftCardUpdateInfoCard";
|
||||
import GiftCardUpdatePageHeader from "./GiftCardUpdatePageHeader";
|
||||
|
@ -38,6 +39,7 @@ const GiftCardUpdatePage: React.FC = () => {
|
|||
<div>
|
||||
<GiftCardUpdateInfoCard />
|
||||
</div>
|
||||
<GiftCardHistory />
|
||||
</Grid>
|
||||
<Savebar
|
||||
state={status}
|
||||
|
|
|
@ -1,22 +1,13 @@
|
|||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { ConfirmButton } from "@saleor/macaw-ui";
|
||||
import commonErrorMessages from "@saleor/utils/errors/common";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { bulkEnableDisableSectionMessages as buttonMessages } from "../../GiftCardsList/GiftCardsListTable/GiftCardsListTableHeader/messages";
|
||||
import useGiftCardDetails from "../providers/GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||
import { giftCardEnableDisableSectionMessages as messages } from "./messages";
|
||||
import {
|
||||
useGiftCardActivateMutation,
|
||||
useGiftCardDeactivateMutation
|
||||
} from "./mutations";
|
||||
import { GiftCardActivate } from "./types/GiftCardActivate";
|
||||
import { GiftCardDeactivate } from "./types/GiftCardDeactivate";
|
||||
import useGiftCardActivateToggle from "./hooks/useGiftCardActivateToggle";
|
||||
|
||||
const GiftCardEnableDisableSection: React.FC = () => {
|
||||
const notify = useNotifier();
|
||||
const intl = useIntl();
|
||||
|
||||
const {
|
||||
|
@ -27,50 +18,12 @@ const GiftCardEnableDisableSection: React.FC = () => {
|
|||
return null;
|
||||
}
|
||||
|
||||
const onActivateCompleted = (data: GiftCardActivate) => {
|
||||
const errors = data?.giftCardActivate?.errors;
|
||||
|
||||
if (!!errors?.length) {
|
||||
notify({
|
||||
status: "error",
|
||||
text: intl.formatMessage(commonErrorMessages.unknownError)
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.successfullyEnabledTitle)
|
||||
});
|
||||
};
|
||||
|
||||
const onDeactivateCompleted = (data: GiftCardDeactivate) => {
|
||||
const errors = data?.giftCardDeactivate?.errors;
|
||||
|
||||
if (!!errors?.length) {
|
||||
notify({
|
||||
status: "error",
|
||||
text: intl.formatMessage(commonErrorMessages.unknownError)
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.successfullyDisabledTitle)
|
||||
});
|
||||
};
|
||||
|
||||
const [giftCardActivate, giftCardActivateOpts] = useGiftCardActivateMutation({
|
||||
onCompleted: onActivateCompleted
|
||||
});
|
||||
|
||||
const [
|
||||
const {
|
||||
giftCardActivate,
|
||||
giftCardDeactivate,
|
||||
giftCardDeactivateOpts
|
||||
] = useGiftCardDeactivateMutation({
|
||||
onCompleted: onDeactivateCompleted
|
||||
currentOpts
|
||||
} = useGiftCardActivateToggle({
|
||||
isActive
|
||||
});
|
||||
|
||||
const handleClick = () =>
|
||||
|
@ -82,8 +35,6 @@ const GiftCardEnableDisableSection: React.FC = () => {
|
|||
? buttonMessages.disableLabel
|
||||
: buttonMessages.enableLabel;
|
||||
|
||||
const currentOpts = isActive ? giftCardDeactivateOpts : giftCardActivateOpts;
|
||||
|
||||
return (
|
||||
<ConfirmButton
|
||||
data-test-id="enable-button"
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Button } from "@material-ui/core";
|
|||
import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
import PageTitleWithStatusChip from "@saleor/components/PageTitleWithStatusChip";
|
||||
import { StatusType } from "@saleor/components/StatusChip/types";
|
||||
import GiftCardStatusChip from "@saleor/giftCards/components/GiftCardStatusChip/GiftCardStatusChip";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import { Backlink } from "@saleor/macaw-ui";
|
||||
import React from "react";
|
||||
|
@ -25,42 +25,25 @@ const GiftCardUpdatePageHeader: React.FC = () => {
|
|||
|
||||
const { openResendCodeDialog } = useGiftCardUpdateDialogs();
|
||||
|
||||
const { displayCode, isActive, isExpired } = giftCard;
|
||||
const { last4CodeChars, isExpired } = giftCard;
|
||||
|
||||
const title = intl.formatMessage(tableMessages.codeEndingWithLabel, {
|
||||
displayCode
|
||||
last4CodeChars
|
||||
});
|
||||
|
||||
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 (
|
||||
<>
|
||||
<Backlink onClick={navigateBack}>
|
||||
{intl.formatMessage(sectionNames.giftCards)}
|
||||
</Backlink>
|
||||
<PageHeader inline title={getPageTitle()}>
|
||||
<PageHeader
|
||||
inline
|
||||
title={
|
||||
<PageTitleWithStatusChip title={title}>
|
||||
<GiftCardStatusChip giftCard={giftCard} />
|
||||
</PageTitleWithStatusChip>
|
||||
}
|
||||
>
|
||||
<GiftCardEnableDisableSection />
|
||||
<HorizontalSpacer />
|
||||
{!isExpired && (
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import commonErrorMessages from "@saleor/utils/errors/common";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import { GIFT_CARD_DETAILS_QUERY } from "../../queries";
|
||||
import { giftCardEnableDisableSectionMessages as messages } from "../messages";
|
||||
import {
|
||||
useGiftCardActivateMutation,
|
||||
useGiftCardDeactivateMutation
|
||||
} from "../mutations";
|
||||
import { GiftCardActivate } from "../types/GiftCardActivate";
|
||||
import { GiftCardDeactivate } from "../types/GiftCardDeactivate";
|
||||
|
||||
interface useGiftCardActivateToggleProps {
|
||||
onActivateActionComplete?: () => void | undefined;
|
||||
onDeactivateActionComplete?: () => void | undefined;
|
||||
isActive?: boolean;
|
||||
}
|
||||
|
||||
const useGiftCardActivateToggle = ({
|
||||
onActivateActionComplete,
|
||||
onDeactivateActionComplete,
|
||||
isActive
|
||||
}: useGiftCardActivateToggleProps) => {
|
||||
const intl = useIntl();
|
||||
const notify = useNotifier();
|
||||
|
||||
const onActivateCompleted = (data: GiftCardActivate) => {
|
||||
const errors = data?.giftCardActivate?.errors;
|
||||
|
||||
if (!!errors?.length) {
|
||||
notify({
|
||||
status: "error",
|
||||
text: intl.formatMessage(commonErrorMessages.unknownError)
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.successfullyEnabledTitle)
|
||||
});
|
||||
|
||||
if (!!onActivateActionComplete) {
|
||||
onActivateActionComplete();
|
||||
}
|
||||
};
|
||||
|
||||
const onDeactivateCompleted = (data: GiftCardDeactivate) => {
|
||||
const errors = data?.giftCardDeactivate?.errors;
|
||||
|
||||
if (!!errors?.length) {
|
||||
notify({
|
||||
status: "error",
|
||||
text: intl.formatMessage(commonErrorMessages.unknownError)
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(messages.successfullyDisabledTitle)
|
||||
});
|
||||
|
||||
if (!!onDeactivateActionComplete) {
|
||||
onDeactivateActionComplete();
|
||||
}
|
||||
};
|
||||
|
||||
const [giftCardActivate, giftCardActivateOpts] = useGiftCardActivateMutation({
|
||||
onCompleted: onActivateCompleted,
|
||||
refetchQueries: [GIFT_CARD_DETAILS_QUERY]
|
||||
});
|
||||
|
||||
const [
|
||||
giftCardDeactivate,
|
||||
giftCardDeactivateOpts
|
||||
] = useGiftCardDeactivateMutation({
|
||||
onCompleted: onDeactivateCompleted,
|
||||
refetchQueries: [GIFT_CARD_DETAILS_QUERY]
|
||||
});
|
||||
|
||||
const currentOpts = isActive ? giftCardDeactivateOpts : giftCardActivateOpts;
|
||||
|
||||
return {
|
||||
giftCardActivate,
|
||||
giftCardActivateOpts,
|
||||
giftCardDeactivate,
|
||||
giftCardDeactivateOpts,
|
||||
currentOpts
|
||||
};
|
||||
};
|
||||
|
||||
export default useGiftCardActivateToggle;
|
|
@ -3,25 +3,25 @@ import { defineMessages } from "react-intl";
|
|||
export const giftCardEnableDisableSectionMessages = defineMessages({
|
||||
successfullyEnabledTitle: {
|
||||
defaultMessage: "Successfully enabled gift card",
|
||||
description: "GiftCardEnableDisableSection enable success"
|
||||
description: "success gift card enable message"
|
||||
},
|
||||
successfullyDisabledTitle: {
|
||||
defaultMessage: "Successfully disabled gift card",
|
||||
description: "GiftCardEnableDisableSection disable success"
|
||||
description: "success gift card disable message"
|
||||
}
|
||||
});
|
||||
|
||||
export const giftCardUpdatePageHeaderMessages = defineMessages({
|
||||
resendButtonLabel: {
|
||||
defaultMessage: "Resend code",
|
||||
description: "giftCardUpdatePageHeader resendButtonLabel"
|
||||
description: "resend code label"
|
||||
},
|
||||
expiredStatusLabel: {
|
||||
defaultMessage: "Expired",
|
||||
description: "giftCardUpdatePageHeader expired status label"
|
||||
description: "expired status label"
|
||||
},
|
||||
disabledStatusLabel: {
|
||||
defaultMessage: "Disabled",
|
||||
description: "giftCardUpdatePageHeader disabled status label"
|
||||
description: "disabled status label"
|
||||
}
|
||||
});
|
||||
|
|
|
@ -65,11 +65,16 @@ export interface GiftCardActivate_giftCardActivate_giftCard_currentBalance {
|
|||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardActivate_giftCardActivate_giftCard_tags {
|
||||
__typename: "GiftCardTag";
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GiftCardActivate_giftCardActivate_giftCard {
|
||||
__typename: "GiftCard";
|
||||
metadata: (GiftCardActivate_giftCardActivate_giftCard_metadata | null)[];
|
||||
privateMetadata: (GiftCardActivate_giftCardActivate_giftCard_privateMetadata | null)[];
|
||||
displayCode: string;
|
||||
last4CodeChars: string;
|
||||
boughtInChannel: string | null;
|
||||
createdBy: GiftCardActivate_giftCardActivate_giftCard_createdBy | null;
|
||||
product: GiftCardActivate_giftCardActivate_giftCard_product | null;
|
||||
|
@ -84,7 +89,7 @@ export interface GiftCardActivate_giftCardActivate_giftCard {
|
|||
initialBalance: GiftCardActivate_giftCardActivate_giftCard_initialBalance | null;
|
||||
currentBalance: GiftCardActivate_giftCardActivate_giftCard_currentBalance | null;
|
||||
id: string;
|
||||
tag: string | null;
|
||||
tags: GiftCardActivate_giftCardActivate_giftCard_tags[] | null;
|
||||
}
|
||||
|
||||
export interface GiftCardActivate_giftCardActivate {
|
||||
|
|
|
@ -65,11 +65,16 @@ export interface GiftCardDeactivate_giftCardDeactivate_giftCard_currentBalance {
|
|||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_tags {
|
||||
__typename: "GiftCardTag";
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GiftCardDeactivate_giftCardDeactivate_giftCard {
|
||||
__typename: "GiftCard";
|
||||
metadata: (GiftCardDeactivate_giftCardDeactivate_giftCard_metadata | null)[];
|
||||
privateMetadata: (GiftCardDeactivate_giftCardDeactivate_giftCard_privateMetadata | null)[];
|
||||
displayCode: string;
|
||||
last4CodeChars: string;
|
||||
boughtInChannel: string | null;
|
||||
createdBy: GiftCardDeactivate_giftCardDeactivate_giftCard_createdBy | null;
|
||||
product: GiftCardDeactivate_giftCardDeactivate_giftCard_product | null;
|
||||
|
@ -84,7 +89,7 @@ export interface GiftCardDeactivate_giftCardDeactivate_giftCard {
|
|||
initialBalance: GiftCardDeactivate_giftCardDeactivate_giftCard_initialBalance | null;
|
||||
currentBalance: GiftCardDeactivate_giftCardDeactivate_giftCard_currentBalance | null;
|
||||
id: string;
|
||||
tag: string | null;
|
||||
tags: GiftCardDeactivate_giftCardDeactivate_giftCard_tags[] | null;
|
||||
}
|
||||
|
||||
export interface GiftCardDeactivate_giftCardDeactivate {
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
import { GiftCardError } from "@saleor/fragments/types/GiftCardError";
|
||||
import { GiftCardErrorCode } from "@saleor/types/globalTypes";
|
||||
import { getCommonFormFieldErrorMessage } from "@saleor/utils/errors/common";
|
||||
import commonErrorMessages, {
|
||||
getCommonFormFieldErrorMessage
|
||||
} from "@saleor/utils/errors/common";
|
||||
import { defineMessages, IntlShape } from "react-intl";
|
||||
|
||||
export const giftCardUpdateDetailsCardMessages = defineMessages({
|
||||
title: {
|
||||
defaultMessage: "Details",
|
||||
description: "GiftCardUpdateDetailsCard title"
|
||||
description: "title"
|
||||
}
|
||||
});
|
||||
|
||||
const giftCardErrorMessages = defineMessages({
|
||||
notFound: {
|
||||
defaultMessage: "Couldn't find gift card",
|
||||
description: "giftCardErrorMessages not found"
|
||||
description: "gift card not found message"
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -25,6 +27,8 @@ export function getGiftCardErrorMessage(
|
|||
switch (error.code) {
|
||||
case GiftCardErrorCode.NOT_FOUND:
|
||||
return intl.formatMessage(giftCardErrorMessages.notFound);
|
||||
case GiftCardErrorCode.INVALID:
|
||||
return intl.formatMessage(commonErrorMessages.invalid);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,11 @@ import { giftCardErrorFragment } from "@saleor/fragments/errors";
|
|||
import makeMutation from "@saleor/hooks/makeMutation";
|
||||
import gql from "graphql-tag";
|
||||
|
||||
import { giftCardDataFragment } from "./queries";
|
||||
import { giftCardDataFragment, giftCardEventsFragment } from "./queries";
|
||||
import {
|
||||
GiftCardAddNote,
|
||||
GiftCardAddNoteVariables
|
||||
} from "./types/GiftCardAddNote";
|
||||
import {
|
||||
GiftCardUpdate,
|
||||
GiftCardUpdateVariables
|
||||
|
@ -11,6 +15,7 @@ import {
|
|||
const giftCardUpdate = gql`
|
||||
${giftCardDataFragment}
|
||||
${giftCardErrorFragment}
|
||||
${giftCardEventsFragment}
|
||||
mutation GiftCardUpdate($id: ID!, $input: GiftCardUpdateInput!) {
|
||||
giftCardUpdate(id: $id, input: $input) {
|
||||
errors {
|
||||
|
@ -18,6 +23,9 @@ const giftCardUpdate = gql`
|
|||
}
|
||||
giftCard {
|
||||
...GiftCardData
|
||||
events {
|
||||
...GiftCardEvent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,3 +35,28 @@ export const useGiftCardUpdateMutation = makeMutation<
|
|||
GiftCardUpdate,
|
||||
GiftCardUpdateVariables
|
||||
>(giftCardUpdate);
|
||||
|
||||
export const giftCardTimelineNoteAdd = gql`
|
||||
${giftCardDataFragment}
|
||||
${giftCardErrorFragment}
|
||||
${giftCardEventsFragment}
|
||||
mutation GiftCardAddNote($id: ID!, $input: GiftCardAddNoteInput!) {
|
||||
giftCardAddNote(id: $id, input: $input) {
|
||||
errors {
|
||||
...GiftCardError
|
||||
message
|
||||
}
|
||||
giftCard {
|
||||
...GiftCardData
|
||||
}
|
||||
event {
|
||||
...GiftCardEvent
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const useGiftCardTimelineNoteAddMutation = makeMutation<
|
||||
GiftCardAddNote,
|
||||
GiftCardAddNoteVariables
|
||||
>(giftCardTimelineNoteAdd);
|
||||
|
|
|
@ -20,7 +20,7 @@ interface GiftCardUpdateDialogsProviderProps {
|
|||
|
||||
export interface GiftCardUpdateDialogsConsumerProps {
|
||||
navigateBack: () => void;
|
||||
closeDialog: () => void;
|
||||
onClose: () => void;
|
||||
openSetBalanceDialog: () => void;
|
||||
openDeleteDialog: () => void;
|
||||
openResendCodeDialog: () => void;
|
||||
|
@ -45,7 +45,7 @@ const GiftCardUpdateDialogsProvider: React.FC<GiftCardUpdateDialogsProviderProps
|
|||
RESEND_CODE
|
||||
} = GiftCardUpdatePageActionParamsEnum;
|
||||
|
||||
const [openDialog, closeDialog] = createDialogActionHandlers<
|
||||
const [openDialog, onClose] = createDialogActionHandlers<
|
||||
GiftCardUpdatePageActionParamsEnum,
|
||||
GiftCardUpdatePageUrlQueryParams
|
||||
>(navigate, params => giftCardUrl(id, params), params);
|
||||
|
@ -59,7 +59,7 @@ const GiftCardUpdateDialogsProvider: React.FC<GiftCardUpdateDialogsProviderProps
|
|||
openSetBalanceDialog: () => openDialog(SET_BALANCE),
|
||||
openDeleteDialog: () => openDialog(DELETE),
|
||||
openResendCodeDialog: () => openDialog(RESEND_CODE),
|
||||
closeDialog,
|
||||
onClose,
|
||||
navigateBack
|
||||
};
|
||||
|
||||
|
@ -69,17 +69,17 @@ const GiftCardUpdateDialogsProvider: React.FC<GiftCardUpdateDialogsProviderProps
|
|||
{!loadingGiftCard && (
|
||||
<>
|
||||
<GiftCardUpdateBalanceDialog
|
||||
closeDialog={closeDialog}
|
||||
onClose={onClose}
|
||||
open={isDialogOpen(SET_BALANCE)}
|
||||
/>
|
||||
<GiftCardUpdatePageDeleteDialog
|
||||
closeDialog={closeDialog}
|
||||
onClose={onClose}
|
||||
open={isDialogOpen(DELETE)}
|
||||
navigateBack={navigateBack}
|
||||
/>
|
||||
<GiftCardResendCodeDialog
|
||||
open={isDialogOpen(RESEND_CODE)}
|
||||
closeDialog={closeDialog}
|
||||
onClose={onClose}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { MetadataFormData } from "@saleor/components/Metadata";
|
||||
import { GiftCardError } from "@saleor/fragments/types/GiftCardError";
|
||||
import { giftCardUpdateFormMessages } from "@saleor/giftCards/GiftCardsList/messages";
|
||||
import { MutationResultWithOpts } from "@saleor/hooks/makeMutation";
|
||||
import useForm, { FormChange, UseFormResult } from "@saleor/hooks/useForm";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
|
@ -14,6 +15,7 @@ import {
|
|||
usePrivateMetadataUpdate
|
||||
} from "@saleor/utils/metadata/updateMetadata";
|
||||
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||
import difference from "lodash/difference";
|
||||
import React, { createContext } from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
|
@ -30,7 +32,7 @@ interface GiftCardUpdateFormProviderProps {
|
|||
}
|
||||
|
||||
export type GiftCardUpdateFormData = MetadataFormData &
|
||||
Pick<GiftCardCreateFormData, "tag" | "expiryDate">;
|
||||
Pick<GiftCardCreateFormData, "tags" | "expiryDate">;
|
||||
|
||||
export interface GiftCardUpdateFormConsumerData
|
||||
extends GiftCardUpdateFormErrors {
|
||||
|
@ -38,7 +40,7 @@ export interface GiftCardUpdateFormConsumerData
|
|||
}
|
||||
|
||||
export interface GiftCardUpdateFormErrors {
|
||||
formErrors: Record<"tag" | "expiryDate", GiftCardError>;
|
||||
formErrors: Record<"tags" | "expiryDate", GiftCardError>;
|
||||
handlers: { changeMetadata: FormChange };
|
||||
}
|
||||
|
||||
|
@ -51,6 +53,19 @@ export const GiftCardUpdateFormContext = createContext<
|
|||
GiftCardUpdateFormConsumerProps
|
||||
>(null);
|
||||
|
||||
const getGiftCardTagsAddRemoveData = (
|
||||
initTags: string[],
|
||||
changedTags: string[]
|
||||
) => {
|
||||
const removed = difference(initTags, changedTags);
|
||||
const added = difference(changedTags, initTags);
|
||||
|
||||
return {
|
||||
addTags: added,
|
||||
removeTags: removed
|
||||
};
|
||||
};
|
||||
|
||||
const GiftCardUpdateFormProvider: React.FC<GiftCardUpdateFormProviderProps> = ({
|
||||
children
|
||||
}) => {
|
||||
|
@ -66,10 +81,10 @@ const GiftCardUpdateFormProvider: React.FC<GiftCardUpdateFormProviderProps> = ({
|
|||
return { ...emptyFormData, metadata: [], privateMetadata: [] };
|
||||
}
|
||||
|
||||
const { tag, expiryDate, privateMetadata, metadata } = giftCard;
|
||||
const { tags, expiryDate, privateMetadata, metadata } = giftCard;
|
||||
|
||||
return {
|
||||
tag,
|
||||
tags: tags.map(({ name }) => name),
|
||||
expiryDate,
|
||||
privateMetadata: privateMetadata?.map(mapMetadataItemToInput),
|
||||
metadata: metadata?.map(mapMetadataItemToInput)
|
||||
|
@ -78,21 +93,37 @@ const GiftCardUpdateFormProvider: React.FC<GiftCardUpdateFormProviderProps> = ({
|
|||
|
||||
const onSubmit = (data: GiftCardUpdate) => {
|
||||
const errors = data.giftCardUpdate.errors;
|
||||
const hasExpiryError = errors.some(error => error.field === "expiryDate");
|
||||
|
||||
notify(getDefaultNotifierSuccessErrorData(errors, intl));
|
||||
notify(
|
||||
hasExpiryError
|
||||
? {
|
||||
title: intl.formatMessage(
|
||||
giftCardUpdateFormMessages.giftCardInvalidExpiryDateHeader
|
||||
),
|
||||
text: intl.formatMessage(
|
||||
giftCardUpdateFormMessages.giftCardInvalidExpiryDateContent
|
||||
),
|
||||
status: "error"
|
||||
}
|
||||
: getDefaultNotifierSuccessErrorData(errors, intl)
|
||||
);
|
||||
};
|
||||
|
||||
const [updateGiftCard, updateGiftCardOpts] = useGiftCardUpdateMutation({
|
||||
onCompleted: onSubmit
|
||||
});
|
||||
|
||||
const submit = async ({ tag, expiryDate }: GiftCardUpdateFormData) => {
|
||||
const submit = async ({ tags, expiryDate }: GiftCardUpdateFormData) => {
|
||||
const result = await updateGiftCard({
|
||||
variables: {
|
||||
id: giftCard?.id,
|
||||
input: {
|
||||
tag,
|
||||
expiryDate
|
||||
expiryDate,
|
||||
...getGiftCardTagsAddRemoveData(
|
||||
giftCard.tags.map(el => el.name),
|
||||
tags
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -128,7 +159,7 @@ const GiftCardUpdateFormProvider: React.FC<GiftCardUpdateFormProviderProps> = ({
|
|||
handleFormSubmit(submitData, handleSubmit, setChanged);
|
||||
|
||||
const formErrors = getFormErrors(
|
||||
["tag", "expiryDate"],
|
||||
["tags", "expiryDate"],
|
||||
updateGiftCardOpts?.data?.giftCardUpdate?.errors
|
||||
);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ export const giftCardDataFragment = gql`
|
|||
${fragmentUserBase}
|
||||
fragment GiftCardData on GiftCard {
|
||||
...MetadataFragment
|
||||
displayCode
|
||||
last4CodeChars
|
||||
boughtInChannel
|
||||
createdBy {
|
||||
...UserBase
|
||||
|
@ -48,7 +48,9 @@ export const giftCardDataFragment = gql`
|
|||
}
|
||||
|
||||
id
|
||||
tag
|
||||
tags {
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -65,17 +67,17 @@ export const giftCardDetails = gql`
|
|||
type
|
||||
user {
|
||||
...UserBase
|
||||
email
|
||||
}
|
||||
app {
|
||||
id
|
||||
name
|
||||
}
|
||||
message
|
||||
email
|
||||
orderId
|
||||
orderNumber
|
||||
tag
|
||||
oldTag
|
||||
tags
|
||||
oldTags
|
||||
balance {
|
||||
initialBalance {
|
||||
...Money
|
||||
|
@ -95,7 +97,46 @@ export const giftCardDetails = gql`
|
|||
}
|
||||
`;
|
||||
|
||||
export const giftCardEventsFragment = gql`
|
||||
fragment GiftCardEvent on GiftCardEvent {
|
||||
expiryDate
|
||||
oldExpiryDate
|
||||
id
|
||||
date
|
||||
type
|
||||
user {
|
||||
...UserBase
|
||||
}
|
||||
app {
|
||||
id
|
||||
name
|
||||
}
|
||||
message
|
||||
email
|
||||
orderId
|
||||
orderNumber
|
||||
tags
|
||||
oldTags
|
||||
balance {
|
||||
initialBalance {
|
||||
...Money
|
||||
}
|
||||
currentBalance {
|
||||
...Money
|
||||
}
|
||||
oldInitialBalance {
|
||||
...Money
|
||||
}
|
||||
oldCurrentBalance {
|
||||
...Money
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const useGiftCardDetailsQuery = makeQuery<
|
||||
GiftCardDetails,
|
||||
GiftCardDetailsVariables
|
||||
>(giftCardDetails);
|
||||
|
||||
export const GIFT_CARD_DETAILS_QUERY = "GiftCardDetails";
|
||||
|
|
173
src/giftCards/GiftCardUpdate/types/GiftCardAddNote.ts
Normal file
173
src/giftCards/GiftCardUpdate/types/GiftCardAddNote.ts
Normal file
|
@ -0,0 +1,173 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { GiftCardAddNoteInput, GiftCardErrorCode, GiftCardEventsEnum } from "./../../../types/globalTypes";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL mutation operation: GiftCardAddNote
|
||||
// ====================================================
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_errors {
|
||||
__typename: "GiftCardError";
|
||||
code: GiftCardErrorCode;
|
||||
field: string | null;
|
||||
message: string | null;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_giftCard_metadata {
|
||||
__typename: "MetadataItem";
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_giftCard_privateMetadata {
|
||||
__typename: "MetadataItem";
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_giftCard_createdBy {
|
||||
__typename: "User";
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_giftCard_product {
|
||||
__typename: "Product";
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_giftCard_usedBy {
|
||||
__typename: "User";
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_giftCard_app {
|
||||
__typename: "App";
|
||||
id: string;
|
||||
name: string | null;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_giftCard_initialBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_giftCard_currentBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_giftCard_tags {
|
||||
__typename: "GiftCardTag";
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_giftCard {
|
||||
__typename: "GiftCard";
|
||||
metadata: (GiftCardAddNote_giftCardAddNote_giftCard_metadata | null)[];
|
||||
privateMetadata: (GiftCardAddNote_giftCardAddNote_giftCard_privateMetadata | null)[];
|
||||
last4CodeChars: string;
|
||||
boughtInChannel: string | null;
|
||||
createdBy: GiftCardAddNote_giftCardAddNote_giftCard_createdBy | null;
|
||||
product: GiftCardAddNote_giftCardAddNote_giftCard_product | null;
|
||||
usedBy: GiftCardAddNote_giftCardAddNote_giftCard_usedBy | null;
|
||||
usedByEmail: string | null;
|
||||
createdByEmail: string | null;
|
||||
app: GiftCardAddNote_giftCardAddNote_giftCard_app | null;
|
||||
created: any;
|
||||
expiryDate: any | null;
|
||||
lastUsedOn: any | null;
|
||||
isActive: boolean;
|
||||
initialBalance: GiftCardAddNote_giftCardAddNote_giftCard_initialBalance | null;
|
||||
currentBalance: GiftCardAddNote_giftCardAddNote_giftCard_currentBalance | null;
|
||||
id: string;
|
||||
tags: GiftCardAddNote_giftCardAddNote_giftCard_tags[] | null;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_event_user {
|
||||
__typename: "User";
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_event_app {
|
||||
__typename: "App";
|
||||
id: string;
|
||||
name: string | null;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_event_balance_initialBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_event_balance_currentBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_event_balance_oldInitialBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_event_balance_oldCurrentBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_event_balance {
|
||||
__typename: "GiftCardEventBalance";
|
||||
initialBalance: GiftCardAddNote_giftCardAddNote_event_balance_initialBalance | null;
|
||||
currentBalance: GiftCardAddNote_giftCardAddNote_event_balance_currentBalance;
|
||||
oldInitialBalance: GiftCardAddNote_giftCardAddNote_event_balance_oldInitialBalance | null;
|
||||
oldCurrentBalance: GiftCardAddNote_giftCardAddNote_event_balance_oldCurrentBalance | null;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote_event {
|
||||
__typename: "GiftCardEvent";
|
||||
expiryDate: any | null;
|
||||
oldExpiryDate: any | null;
|
||||
id: string;
|
||||
date: any | null;
|
||||
type: GiftCardEventsEnum | null;
|
||||
user: GiftCardAddNote_giftCardAddNote_event_user | null;
|
||||
app: GiftCardAddNote_giftCardAddNote_event_app | null;
|
||||
message: string | null;
|
||||
email: string | null;
|
||||
orderId: string | null;
|
||||
orderNumber: string | null;
|
||||
tags: string[] | null;
|
||||
oldTags: string[] | null;
|
||||
balance: GiftCardAddNote_giftCardAddNote_event_balance | null;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote_giftCardAddNote {
|
||||
__typename: "GiftCardAddNote";
|
||||
errors: GiftCardAddNote_giftCardAddNote_errors[];
|
||||
giftCard: GiftCardAddNote_giftCardAddNote_giftCard | null;
|
||||
event: GiftCardAddNote_giftCardAddNote_event | null;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNote {
|
||||
giftCardAddNote: GiftCardAddNote_giftCardAddNote | null;
|
||||
}
|
||||
|
||||
export interface GiftCardAddNoteVariables {
|
||||
id: string;
|
||||
input: GiftCardAddNoteInput;
|
||||
}
|
|
@ -57,11 +57,16 @@ export interface GiftCardData_currentBalance {
|
|||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardData_tags {
|
||||
__typename: "GiftCardTag";
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GiftCardData {
|
||||
__typename: "GiftCard";
|
||||
metadata: (GiftCardData_metadata | null)[];
|
||||
privateMetadata: (GiftCardData_privateMetadata | null)[];
|
||||
displayCode: string;
|
||||
last4CodeChars: string;
|
||||
boughtInChannel: string | null;
|
||||
createdBy: GiftCardData_createdBy | null;
|
||||
product: GiftCardData_product | null;
|
||||
|
@ -76,5 +81,5 @@ export interface GiftCardData {
|
|||
initialBalance: GiftCardData_initialBalance | null;
|
||||
currentBalance: GiftCardData_currentBalance | null;
|
||||
id: string;
|
||||
tag: string | null;
|
||||
tags: GiftCardData_tags[] | null;
|
||||
}
|
||||
|
|
|
@ -59,11 +59,17 @@ export interface GiftCardDetails_giftCard_currentBalance {
|
|||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardDetails_giftCard_tags {
|
||||
__typename: "GiftCardTag";
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GiftCardDetails_giftCard_events_user {
|
||||
__typename: "User";
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
export interface GiftCardDetails_giftCard_events_app {
|
||||
|
@ -114,11 +120,10 @@ export interface GiftCardDetails_giftCard_events {
|
|||
user: GiftCardDetails_giftCard_events_user | null;
|
||||
app: GiftCardDetails_giftCard_events_app | null;
|
||||
message: string | null;
|
||||
email: string | null;
|
||||
orderId: string | null;
|
||||
orderNumber: string | null;
|
||||
tag: string | null;
|
||||
oldTag: string | null;
|
||||
tags: string[] | null;
|
||||
oldTags: string[] | null;
|
||||
balance: GiftCardDetails_giftCard_events_balance | null;
|
||||
}
|
||||
|
||||
|
@ -126,7 +131,7 @@ export interface GiftCardDetails_giftCard {
|
|||
__typename: "GiftCard";
|
||||
metadata: (GiftCardDetails_giftCard_metadata | null)[];
|
||||
privateMetadata: (GiftCardDetails_giftCard_privateMetadata | null)[];
|
||||
displayCode: string;
|
||||
last4CodeChars: string;
|
||||
boughtInChannel: string | null;
|
||||
createdBy: GiftCardDetails_giftCard_createdBy | null;
|
||||
product: GiftCardDetails_giftCard_product | null;
|
||||
|
@ -141,7 +146,7 @@ export interface GiftCardDetails_giftCard {
|
|||
initialBalance: GiftCardDetails_giftCard_initialBalance | null;
|
||||
currentBalance: GiftCardDetails_giftCard_currentBalance | null;
|
||||
id: string;
|
||||
tag: string | null;
|
||||
tags: GiftCardDetails_giftCard_tags[] | null;
|
||||
events: GiftCardDetails_giftCard_events[];
|
||||
}
|
||||
|
||||
|
|
73
src/giftCards/GiftCardUpdate/types/GiftCardEvent.ts
Normal file
73
src/giftCards/GiftCardUpdate/types/GiftCardEvent.ts
Normal file
|
@ -0,0 +1,73 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { GiftCardEventsEnum } from "./../../../types/globalTypes";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL fragment: GiftCardEvent
|
||||
// ====================================================
|
||||
|
||||
export interface GiftCardEvent_user {
|
||||
__typename: "User";
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
}
|
||||
|
||||
export interface GiftCardEvent_app {
|
||||
__typename: "App";
|
||||
id: string;
|
||||
name: string | null;
|
||||
}
|
||||
|
||||
export interface GiftCardEvent_balance_initialBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardEvent_balance_currentBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardEvent_balance_oldInitialBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardEvent_balance_oldCurrentBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardEvent_balance {
|
||||
__typename: "GiftCardEventBalance";
|
||||
initialBalance: GiftCardEvent_balance_initialBalance | null;
|
||||
currentBalance: GiftCardEvent_balance_currentBalance;
|
||||
oldInitialBalance: GiftCardEvent_balance_oldInitialBalance | null;
|
||||
oldCurrentBalance: GiftCardEvent_balance_oldCurrentBalance | null;
|
||||
}
|
||||
|
||||
export interface GiftCardEvent {
|
||||
__typename: "GiftCardEvent";
|
||||
expiryDate: any | null;
|
||||
oldExpiryDate: any | null;
|
||||
id: string;
|
||||
date: any | null;
|
||||
type: GiftCardEventsEnum | null;
|
||||
user: GiftCardEvent_user | null;
|
||||
app: GiftCardEvent_app | null;
|
||||
message: string | null;
|
||||
email: string | null;
|
||||
orderId: string | null;
|
||||
orderNumber: string | null;
|
||||
tags: string[] | null;
|
||||
oldTags: string[] | null;
|
||||
balance: GiftCardEvent_balance | null;
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { GiftCardUpdateInput, GiftCardErrorCode } from "./../../../types/globalTypes";
|
||||
import { GiftCardUpdateInput, GiftCardErrorCode, GiftCardEventsEnum } from "./../../../types/globalTypes";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL mutation operation: GiftCardUpdate
|
||||
|
@ -65,11 +65,79 @@ export interface GiftCardUpdate_giftCardUpdate_giftCard_currentBalance {
|
|||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate_giftCard_tags {
|
||||
__typename: "GiftCardTag";
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate_giftCard_events_user {
|
||||
__typename: "User";
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate_giftCard_events_app {
|
||||
__typename: "App";
|
||||
id: string;
|
||||
name: string | null;
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate_giftCard_events_balance_initialBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate_giftCard_events_balance_currentBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate_giftCard_events_balance_oldInitialBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate_giftCard_events_balance_oldCurrentBalance {
|
||||
__typename: "Money";
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate_giftCard_events_balance {
|
||||
__typename: "GiftCardEventBalance";
|
||||
initialBalance: GiftCardUpdate_giftCardUpdate_giftCard_events_balance_initialBalance | null;
|
||||
currentBalance: GiftCardUpdate_giftCardUpdate_giftCard_events_balance_currentBalance;
|
||||
oldInitialBalance: GiftCardUpdate_giftCardUpdate_giftCard_events_balance_oldInitialBalance | null;
|
||||
oldCurrentBalance: GiftCardUpdate_giftCardUpdate_giftCard_events_balance_oldCurrentBalance | null;
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate_giftCard_events {
|
||||
__typename: "GiftCardEvent";
|
||||
expiryDate: any | null;
|
||||
oldExpiryDate: any | null;
|
||||
id: string;
|
||||
date: any | null;
|
||||
type: GiftCardEventsEnum | null;
|
||||
user: GiftCardUpdate_giftCardUpdate_giftCard_events_user | null;
|
||||
app: GiftCardUpdate_giftCardUpdate_giftCard_events_app | null;
|
||||
message: string | null;
|
||||
email: string | null;
|
||||
orderId: string | null;
|
||||
orderNumber: string | null;
|
||||
tags: string[] | null;
|
||||
oldTags: string[] | null;
|
||||
balance: GiftCardUpdate_giftCardUpdate_giftCard_events_balance | null;
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate_giftCard {
|
||||
__typename: "GiftCard";
|
||||
metadata: (GiftCardUpdate_giftCardUpdate_giftCard_metadata | null)[];
|
||||
privateMetadata: (GiftCardUpdate_giftCardUpdate_giftCard_privateMetadata | null)[];
|
||||
displayCode: string;
|
||||
last4CodeChars: string;
|
||||
boughtInChannel: string | null;
|
||||
createdBy: GiftCardUpdate_giftCardUpdate_giftCard_createdBy | null;
|
||||
product: GiftCardUpdate_giftCardUpdate_giftCard_product | null;
|
||||
|
@ -84,7 +152,8 @@ export interface GiftCardUpdate_giftCardUpdate_giftCard {
|
|||
initialBalance: GiftCardUpdate_giftCardUpdate_giftCard_initialBalance | null;
|
||||
currentBalance: GiftCardUpdate_giftCardUpdate_giftCard_currentBalance | null;
|
||||
id: string;
|
||||
tag: string | null;
|
||||
tags: GiftCardUpdate_giftCardUpdate_giftCard_tags[] | null;
|
||||
events: GiftCardUpdate_giftCardUpdate_giftCard_events[];
|
||||
}
|
||||
|
||||
export interface GiftCardUpdate_giftCardUpdate {
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import VerticalSpacer from "@saleor/apps/components/VerticalSpacer";
|
||||
import Container from "@saleor/components/Container";
|
||||
import React from "react";
|
||||
|
||||
import GiftCardsListHeader from "./GiftCardsListHeader";
|
||||
import GiftCardsListOrderInfoCard from "./GiftCardsListOrderInfoCard/GiftCardsListOrderInfoCard";
|
||||
import GiftCardsListTable from "./GiftCardsListTable";
|
||||
|
||||
const GiftCardsListPage: React.FC = () => (
|
||||
<Container>
|
||||
<GiftCardsListHeader />
|
||||
<GiftCardsListTable />
|
||||
<VerticalSpacer spacing={2} />
|
||||
<GiftCardsListOrderInfoCard />
|
||||
</Container>
|
||||
);
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ const GiftCardListSearchAndFilters: React.FC = () => {
|
|||
const { reset } = useGiftCardListBulkActions();
|
||||
|
||||
const {
|
||||
closeDialog,
|
||||
onClose,
|
||||
openSearchDeleteDialog,
|
||||
openSearchSaveDialog
|
||||
} = useGiftCardListDialogs();
|
||||
|
@ -98,7 +98,7 @@ const GiftCardListSearchAndFilters: React.FC = () => {
|
|||
},
|
||||
tags: compact(
|
||||
mapEdgesToItems(searchGiftCardTagsResult?.data?.search)?.map(
|
||||
({ tag }) => tag
|
||||
({ name }) => name
|
||||
)
|
||||
)
|
||||
});
|
||||
|
@ -168,13 +168,13 @@ const GiftCardListSearchAndFilters: React.FC = () => {
|
|||
<SaveFilterTabDialog
|
||||
open={params.action === GiftCardListActionParamsEnum.SAVE_SEARCH}
|
||||
confirmButtonState="default"
|
||||
onClose={closeDialog}
|
||||
onClose={onClose}
|
||||
onSubmit={handleTabSave}
|
||||
/>
|
||||
<DeleteFilterTabDialog
|
||||
open={params.action === GiftCardListActionParamsEnum.DELETE_SEARCH}
|
||||
confirmButtonState="default"
|
||||
onClose={closeDialog}
|
||||
onClose={onClose}
|
||||
onSubmit={handleTabDelete}
|
||||
tabName={maybe(() => tabs[currentTab - 1].name, "...")}
|
||||
/>
|
||||
|
|
|
@ -62,7 +62,6 @@ export const getFilterOpts = ({
|
|||
value: params?.currency,
|
||||
choices: mapSingleValueNodeToChoice(currencies),
|
||||
displayValues: mapSingleValueNodeToChoice(currencies),
|
||||
initialSearch: "",
|
||||
loading: loadingCurrencies
|
||||
},
|
||||
product: {
|
||||
|
@ -222,7 +221,8 @@ export function createFilterStructure(
|
|||
multiple:
|
||||
opts?.initialBalanceAmount?.value?.min !==
|
||||
opts?.initialBalanceAmount?.value?.max,
|
||||
active: opts.initialBalanceAmount.active
|
||||
active: opts.initialBalanceAmount.active,
|
||||
dependencies: [GiftCardListFilterKeys.currency]
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -234,23 +234,16 @@ export function createFilterStructure(
|
|||
multiple:
|
||||
opts?.currentBalanceAmount?.value?.min !==
|
||||
opts?.currentBalanceAmount?.value?.max,
|
||||
active: opts.currentBalanceAmount.active
|
||||
active: opts.currentBalanceAmount.active,
|
||||
dependencies: [GiftCardListFilterKeys.currency]
|
||||
},
|
||||
{
|
||||
...createAutocompleteField(
|
||||
...createOptionsField(
|
||||
GiftCardListFilterKeys.currency,
|
||||
intl.formatMessage(messages.currencyLabel),
|
||||
[opts.currency.value],
|
||||
opts.currency.displayValues,
|
||||
false,
|
||||
opts.currency.choices,
|
||||
{
|
||||
hasMore: opts.currency.hasMore,
|
||||
initialSearch: "",
|
||||
loading: opts.currency.loading,
|
||||
onFetchMore: opts.currency.onFetchMore,
|
||||
onSearchChange: opts.currency.onSearchChange
|
||||
}
|
||||
opts.currency.choices
|
||||
),
|
||||
active: opts.currency.active
|
||||
},
|
||||
|
|
|
@ -3,21 +3,21 @@ import { defineMessages } from "react-intl";
|
|||
export const giftCardListFilterErrorMessages = defineMessages({
|
||||
balanceAmount: {
|
||||
defaultMessage: "Balance amount is missing",
|
||||
description: "Filter balance amount error"
|
||||
description: "balance amound missing error message"
|
||||
},
|
||||
balanceCurrency: {
|
||||
defaultMessage: "Balance currency is missing",
|
||||
description: "Filter balance currency error"
|
||||
description: "balance curreny missing error message"
|
||||
}
|
||||
});
|
||||
|
||||
export const giftCardListSearchAndFiltersMessages = defineMessages({
|
||||
searchPlaceholder: {
|
||||
defaultMessage: "Search Gift Cards, e.g {exampleGiftCardCode}",
|
||||
description: "gift card search placeholder"
|
||||
description: "search gift card placeholder"
|
||||
},
|
||||
defaultTabLabel: {
|
||||
defaultMessage: "All Gift Cards",
|
||||
description: "gift card default tab label"
|
||||
description: "all gift cards label"
|
||||
}
|
||||
});
|
||||
|
|
|
@ -17,7 +17,11 @@ const GiftCardsListHeader: React.FC = () => {
|
|||
const intl = useIntl();
|
||||
const navigate = useNavigator();
|
||||
|
||||
const { openCreateDialog } = useGiftCardListDialogs();
|
||||
const {
|
||||
openCreateDialog,
|
||||
openBulkCreateDialog,
|
||||
openExportDialog
|
||||
} = useGiftCardListDialogs();
|
||||
|
||||
const openSettings = () => navigate(giftCardSettingsUrl);
|
||||
|
||||
|
@ -26,17 +30,17 @@ const GiftCardsListHeader: React.FC = () => {
|
|||
label: intl.formatMessage(messages.settings),
|
||||
testId: "settingsMenuItem",
|
||||
onSelect: openSettings
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(messages.bulkIssue),
|
||||
testId: "bulkIssueMenuItem",
|
||||
onSelect: openBulkCreateDialog
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage(messages.exportCodes),
|
||||
testId: "exportCodesMenuItem",
|
||||
onSelect: openExportDialog
|
||||
}
|
||||
// {
|
||||
// label: intl.formatMessage(messages.bulkIssue),
|
||||
// testId: "bulkIssueMenuItem"
|
||||
// // onSelect:
|
||||
// },
|
||||
// {
|
||||
// label: intl.formatMessage(messages.exportCodes),
|
||||
// testId: "exportCodesMenuItem"
|
||||
// // onSelect:
|
||||
// }
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import { Alert } from "@saleor/macaw-ui";
|
||||
import { productAddUrl } from "@saleor/products/urls";
|
||||
import { productTypeAddUrl } from "@saleor/productTypes/urls";
|
||||
import { ProductTypeKindEnum } from "@saleor/types/globalTypes";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
|
@ -12,7 +8,6 @@ import GiftCardsListHeaderAlertContent from "./GiftCardsListHeaderAlertContent";
|
|||
|
||||
const GiftCardsListHeaderAlert: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const navigate = useNavigator();
|
||||
|
||||
const {
|
||||
data: giftCardProductsCount,
|
||||
|
@ -28,15 +23,6 @@ const GiftCardsListHeaderAlert: React.FC = () => {
|
|||
!giftCardProductsCountLoading &&
|
||||
(!giftCardProductTypesExist || !giftCardProductsExist);
|
||||
|
||||
const handleCreateGiftCardProductType = () =>
|
||||
navigate(
|
||||
productTypeAddUrl({
|
||||
kind: ProductTypeKindEnum.GIFT_CARD
|
||||
})
|
||||
);
|
||||
|
||||
const handleCreateGiftCardProduct = () => navigate(productAddUrl());
|
||||
|
||||
if (showNoGiftCardProductsAlert) {
|
||||
return (
|
||||
<Alert
|
||||
|
@ -47,8 +33,6 @@ const GiftCardsListHeaderAlert: React.FC = () => {
|
|||
<GiftCardsListHeaderAlertContent
|
||||
giftCardProductTypesExist={giftCardProductTypesExist}
|
||||
giftCardProductsExist={giftCardProductsExist}
|
||||
handleCreateGiftCardProductType={handleCreateGiftCardProductType}
|
||||
handleCreateGiftCardProduct={handleCreateGiftCardProduct}
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import Link from "@saleor/components/Link";
|
||||
import { productAddUrl } from "@saleor/products/urls";
|
||||
import { productTypeAddUrl } from "@saleor/productTypes/urls";
|
||||
import { ProductTypeKindEnum } from "@saleor/types/globalTypes";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
|
@ -8,28 +11,27 @@ import { useHeaderStyles as useStyles } from "../styles";
|
|||
interface GiftCardsListHeaderAlertContentProps {
|
||||
giftCardProductTypesExist: boolean;
|
||||
giftCardProductsExist: boolean;
|
||||
handleCreateGiftCardProductType: () => void;
|
||||
handleCreateGiftCardProduct: () => void;
|
||||
}
|
||||
|
||||
const GiftCardsListHeaderAlertContent: React.FC<GiftCardsListHeaderAlertContentProps> = ({
|
||||
giftCardProductTypesExist,
|
||||
giftCardProductsExist,
|
||||
handleCreateGiftCardProductType,
|
||||
handleCreateGiftCardProduct
|
||||
giftCardProductsExist
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
|
||||
const giftCardProductTypeUrl = productTypeAddUrl({
|
||||
kind: ProductTypeKindEnum.GIFT_CARD
|
||||
});
|
||||
|
||||
const giftCardCreateGiftCardProductUrl = productAddUrl();
|
||||
|
||||
if (!giftCardProductTypesExist) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
{...messages.noGiftCardsProductTypes}
|
||||
values={{
|
||||
createGiftCardProductType: (
|
||||
<Link
|
||||
onClick={handleCreateGiftCardProductType}
|
||||
className={classes.alertLink}
|
||||
>
|
||||
<Link href={giftCardProductTypeUrl} className={classes.alertLink}>
|
||||
<FormattedMessage {...messages.createGiftCardProductType} />
|
||||
</Link>
|
||||
)
|
||||
|
@ -45,7 +47,7 @@ const GiftCardsListHeaderAlertContent: React.FC<GiftCardsListHeaderAlertContentP
|
|||
values={{
|
||||
createGiftCardProduct: (
|
||||
<Link
|
||||
onClick={handleCreateGiftCardProduct}
|
||||
href={giftCardCreateGiftCardProductUrl}
|
||||
className={classes.alertLink}
|
||||
>
|
||||
<FormattedMessage {...messages.createGiftCardProduct} />
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import { Typography } from "@material-ui/core";
|
||||
import Link from "@saleor/components/Link";
|
||||
import { Alert } from "@saleor/macaw-ui";
|
||||
import { orderGiftCardBoughtPath } from "@saleor/orders/urls";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import { giftCardListOrderCardMessages as messages } from "./messages";
|
||||
|
||||
const GiftCardsListOrderInfoCard: React.FC = () => (
|
||||
<Alert variant="info" close={false}>
|
||||
<Typography>
|
||||
<FormattedMessage
|
||||
{...messages.giftCardOrderInfoMessage}
|
||||
values={{
|
||||
link: content => (
|
||||
<Link href={orderGiftCardBoughtPath()}>{content}</Link>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Typography>
|
||||
</Alert>
|
||||
);
|
||||
|
||||
export default GiftCardsListOrderInfoCard;
|
|
@ -0,0 +1,9 @@
|
|||
import { defineMessages } from "react-intl";
|
||||
|
||||
export const giftCardListOrderCardMessages = defineMessages({
|
||||
giftCardOrderInfoMessage: {
|
||||
defaultMessage:
|
||||
"Gift cards will appear after their order is fullfilled. <link>View Orders with Gift Cards</link>",
|
||||
description: "alert card message"
|
||||
}
|
||||
});
|
|
@ -11,95 +11,80 @@ import DeleteIconButton from "@saleor/components/DeleteIconButton";
|
|||
import Link from "@saleor/components/Link";
|
||||
import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
||||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import StatusChip from "@saleor/components/StatusChip";
|
||||
import { StatusType } from "@saleor/components/StatusChip/types";
|
||||
import { customerUrl } from "@saleor/customers/urls";
|
||||
import GiftCardStatusChip from "@saleor/giftCards/components/GiftCardStatusChip/GiftCardStatusChip";
|
||||
import { PLACEHOLDER } from "@saleor/giftCards/GiftCardUpdate/types";
|
||||
import { giftCardUrl } from "@saleor/giftCards/urls";
|
||||
import { giftCardListUrl, giftCardUrl } from "@saleor/giftCards/urls";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import { renderCollection } from "@saleor/misc";
|
||||
import { productUrl } from "@saleor/products/urls";
|
||||
import React from "react";
|
||||
import { useEffect } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { giftCardUpdatePageHeaderMessages as giftCardStatusChipMessages } from "../../GiftCardUpdate/GiftCardUpdatePageHeader/messages";
|
||||
import GiftCardListSearchAndFilters from "../GiftCardListSearchAndFilters";
|
||||
import { giftCardsListTableMessages as messages } from "../messages";
|
||||
import useGiftCardListDialogs from "../providers/GiftCardListDialogsProvider/hooks/useGiftCardListDialogs";
|
||||
import useGiftCardList from "../providers/GiftCardListProvider/hooks/useGiftCardList";
|
||||
import useGiftCardListBulkActions from "../providers/GiftCardListProvider/hooks/useGiftCardListBulkActions";
|
||||
import { canBeSorted } from "../sort";
|
||||
import { useTableStyles as useStyles } from "../styles";
|
||||
import { GiftCardUrlSortField } from "../types";
|
||||
import GiftCardsListTableFooter from "./GiftCardsListTableFooter";
|
||||
import GiftCardsListTableHeader from "./GiftCardsListTableHeader";
|
||||
import { getTagCellText } from "./utils";
|
||||
|
||||
const GiftCardsListTable: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
const navigate = useNavigator();
|
||||
|
||||
const { giftCards, numberOfColumns, loading } = useGiftCardList();
|
||||
const { giftCards, numberOfColumns, loading, params } = useGiftCardList();
|
||||
const { toggle, isSelected } = useGiftCardListBulkActions();
|
||||
const { openDeleteDialog } = useGiftCardListDialogs();
|
||||
|
||||
const isCurrencySelected = !!params.currency;
|
||||
|
||||
useEffect(() => {
|
||||
if (!canBeSorted(params.sort, isCurrencySelected)) {
|
||||
navigate(
|
||||
giftCardListUrl({
|
||||
...params,
|
||||
sort: GiftCardUrlSortField.usedBy
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const redirectToGiftCardUpdate = (id: string) => () =>
|
||||
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 (
|
||||
<Card>
|
||||
<GiftCardListSearchAndFilters />
|
||||
<ResponsiveTable>
|
||||
<GiftCardsListTableHeader />
|
||||
<GiftCardsListTableHeader isCurrencySelected={isCurrencySelected} />
|
||||
<GiftCardsListTableFooter />
|
||||
<TableBody>
|
||||
{renderCollection(
|
||||
giftCards,
|
||||
({
|
||||
giftCard => {
|
||||
const {
|
||||
id,
|
||||
displayCode,
|
||||
last4CodeChars,
|
||||
usedBy,
|
||||
usedByEmail,
|
||||
tag,
|
||||
isActive,
|
||||
tags,
|
||||
product,
|
||||
currentBalance,
|
||||
isExpired
|
||||
}) => (
|
||||
currentBalance
|
||||
} = giftCard;
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
onClick={redirectToGiftCardUpdate(id)}
|
||||
className={classes.row}
|
||||
key={id}
|
||||
hover={!!giftCard}
|
||||
>
|
||||
<TableCell padding="checkbox">
|
||||
<Checkbox
|
||||
|
@ -112,21 +97,21 @@ const GiftCardsListTable: React.FC = () => {
|
|||
<div className={classes.cardCodeContainer}>
|
||||
<Typography>
|
||||
{intl.formatMessage(messages.codeEndingWithLabel, {
|
||||
displayCode
|
||||
last4CodeChars
|
||||
})}
|
||||
</Typography>
|
||||
<>
|
||||
<HorizontalSpacer spacing={2} />
|
||||
{selectGiftCardStatusChip({ isActive, isExpired })}
|
||||
<GiftCardStatusChip giftCard={giftCard} />
|
||||
</>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography>{tag || PLACEHOLDER}</Typography>
|
||||
<Typography>{getTagCellText(tags)}</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{product ? (
|
||||
<Link onClick={() => navigate(productUrl(product?.id))}>
|
||||
<Link href={productUrl(product?.id)}>
|
||||
{product?.name}
|
||||
</Link>
|
||||
) : (
|
||||
|
@ -135,11 +120,13 @@ const GiftCardsListTable: React.FC = () => {
|
|||
</TableCell>
|
||||
<TableCell>
|
||||
{usedBy ? (
|
||||
<Link onClick={() => navigate(customerUrl(usedBy?.id))}>
|
||||
<Link href={customerUrl(usedBy?.id)}>
|
||||
{`${usedBy?.firstName} ${usedBy?.lastName}`}
|
||||
</Link>
|
||||
) : (
|
||||
<Typography noWrap>{usedByEmail || PLACEHOLDER}</Typography>
|
||||
<Typography noWrap>
|
||||
{usedByEmail || PLACEHOLDER}
|
||||
</Typography>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="right" className={classes.colBalance}>
|
||||
|
@ -160,7 +147,8 @@ const GiftCardsListTable: React.FC = () => {
|
|||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
),
|
||||
);
|
||||
},
|
||||
() => (
|
||||
<TableRow>
|
||||
<TableCell colSpan={numberOfColumns}>
|
||||
|
|
|
@ -69,10 +69,18 @@ const BulkEnableDisableSection: React.FC = () => {
|
|||
.filter(getByIds(ids))
|
||||
.some(({ isActive }) => isActive);
|
||||
|
||||
const areAllSelectedCardsActive = giftCards
|
||||
.filter(getByIds(ids))
|
||||
.every(({ isActive }) => isActive);
|
||||
|
||||
const hasAnyDisabledCardsSelected = giftCards
|
||||
.filter(getByIds(ids))
|
||||
.some(({ isActive }) => !isActive);
|
||||
|
||||
const areAllSelectedCardsDisabled = giftCards
|
||||
.filter(getByIds(ids))
|
||||
.every(({ isActive }) => !isActive);
|
||||
|
||||
const [
|
||||
activateGiftCards,
|
||||
activateGiftCardsOpts
|
||||
|
@ -95,24 +103,29 @@ const BulkEnableDisableSection: React.FC = () => {
|
|||
const handleDeactivateGiftCards = () =>
|
||||
deactivateGiftCards({ variables: { ids } });
|
||||
|
||||
const isSelectionMixed =
|
||||
hasAnyEnabledCardsSelected && hasAnyDisabledCardsSelected;
|
||||
|
||||
return (
|
||||
<>
|
||||
{(areAllSelectedCardsDisabled || isSelectionMixed) && (
|
||||
<ConfirmButton
|
||||
disabled={hasAnyEnabledCardsSelected}
|
||||
onClick={handleActivateGiftCards}
|
||||
variant="text"
|
||||
transitionState={activateGiftCardsOpts?.status}
|
||||
>
|
||||
{intl.formatMessage(messages.enableLabel)}
|
||||
</ConfirmButton>
|
||||
)}
|
||||
{(areAllSelectedCardsActive || isSelectionMixed) && (
|
||||
<ConfirmButton
|
||||
disabled={hasAnyDisabledCardsSelected}
|
||||
onClick={handleDeactivateGiftCards}
|
||||
variant="text"
|
||||
transitionState={deactivateGiftCardsOpts?.status}
|
||||
>
|
||||
{intl.formatMessage(messages.disableLabel)}
|
||||
</ConfirmButton>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,34 +1,52 @@
|
|||
import { TableCell } from "@material-ui/core";
|
||||
import DeleteIconButton from "@saleor/components/DeleteIconButton";
|
||||
import TableCellHeader, {
|
||||
TableCellHeaderArrowDirection,
|
||||
TableCellHeaderProps
|
||||
} from "@saleor/components/TableCellHeader";
|
||||
import TableHead from "@saleor/components/TableHead";
|
||||
import Label, {
|
||||
LabelSizes
|
||||
} from "@saleor/orders/components/OrderHistory/Label";
|
||||
import { getArrowDirection } from "@saleor/utils/sort";
|
||||
import React from "react";
|
||||
import { MessageDescriptor, useIntl } from "react-intl";
|
||||
|
||||
import { giftCardsListTableMessages as messages } from "../../messages";
|
||||
import useGiftCardListDialogs from "../../providers/GiftCardListDialogsProvider/hooks/useGiftCardListDialogs";
|
||||
import useGiftCardListSort from "../../providers/GiftCardListDialogsProvider/hooks/useGiftCardListSort";
|
||||
import useGiftCardList from "../../providers/GiftCardListProvider/hooks/useGiftCardList";
|
||||
import useGiftCardListBulkActions from "../../providers/GiftCardListProvider/hooks/useGiftCardListBulkActions";
|
||||
import { canBeSorted } from "../../sort";
|
||||
import { useTableStyles as useStyles } from "../../styles";
|
||||
import { GiftCardUrlSortField } from "../../types";
|
||||
import BulkEnableDisableSection from "./BulkEnableDisableSection";
|
||||
|
||||
interface HeaderItem {
|
||||
title?: MessageDescriptor;
|
||||
options?: TableCellHeaderProps;
|
||||
onClick?: () => void;
|
||||
direction?: TableCellHeaderArrowDirection;
|
||||
canBeSorted?: boolean;
|
||||
}
|
||||
|
||||
const GiftCardsListTableHeader: React.FC = () => {
|
||||
interface GiftCardsListTableHeaderProps {
|
||||
isCurrencySelected: boolean;
|
||||
}
|
||||
|
||||
const GiftCardsListTableHeader: React.FC<GiftCardsListTableHeaderProps> = ({
|
||||
isCurrencySelected
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
||||
const { giftCards, numberOfColumns, loading } = useGiftCardList();
|
||||
const { toggleAll, listElements } = useGiftCardListBulkActions();
|
||||
const { openDeleteDialog } = useGiftCardListDialogs();
|
||||
const { onSort, sort } = useGiftCardListSort();
|
||||
|
||||
const getDirection = (sortField: GiftCardUrlSortField) =>
|
||||
sort.sort === sortField ? getArrowDirection(sort.asc) : undefined;
|
||||
|
||||
const headerItems: HeaderItem[] = [
|
||||
{
|
||||
|
@ -42,17 +60,24 @@ const GiftCardsListTableHeader: React.FC = () => {
|
|||
title: messages.giftCardsTableColumnTagTitle
|
||||
},
|
||||
{
|
||||
title: messages.giftCardsTableColumnProductTitle
|
||||
title: messages.giftCardsTableColumnProductTitle,
|
||||
onClick: () => onSort(GiftCardUrlSortField.product),
|
||||
direction: getDirection(GiftCardUrlSortField.product)
|
||||
},
|
||||
{
|
||||
title: messages.giftCardsTableColumnCustomerTitle
|
||||
title: messages.giftCardsTableColumnCustomerTitle,
|
||||
onClick: () => onSort(GiftCardUrlSortField.usedBy),
|
||||
direction: getDirection(GiftCardUrlSortField.usedBy)
|
||||
},
|
||||
{
|
||||
title: messages.giftCardsTableColumnBalanceTitle,
|
||||
options: {
|
||||
className: classes.colBalance,
|
||||
textAlign: "right"
|
||||
}
|
||||
},
|
||||
onClick: () => onSort(GiftCardUrlSortField.balance),
|
||||
direction: getDirection(GiftCardUrlSortField.balance),
|
||||
canBeSorted: canBeSorted(GiftCardUrlSortField.balance, isCurrencySelected)
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -76,15 +101,22 @@ const GiftCardsListTableHeader: React.FC = () => {
|
|||
toolbar={
|
||||
<>
|
||||
<BulkEnableDisableSection />
|
||||
<DeleteIconButton onClick={openDeleteDialog} />
|
||||
<DeleteIconButton onClick={() => openDeleteDialog()} />
|
||||
</>
|
||||
}
|
||||
>
|
||||
{headerItems.map(({ title, options }) => (
|
||||
<TableCellHeader {...options}>
|
||||
{headerItems.map(
|
||||
({ title, options, onClick, direction, canBeSorted = true }) => (
|
||||
<TableCellHeader
|
||||
{...options}
|
||||
onClick={onClick}
|
||||
disabled={!canBeSorted}
|
||||
direction={direction}
|
||||
>
|
||||
<Label text={intl.formatMessage(title)} size={LabelSizes.md} />
|
||||
</TableCellHeader>
|
||||
))}
|
||||
)
|
||||
)}
|
||||
<TableCell className={classes.colDelete} />
|
||||
</TableHead>
|
||||
</>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue