* Add gift cards section to menu and add empty list component * Update messages * Change styling of app wide page header to match design * Add gift cards list table wip * Update prop name for status chip component to make it more consistent with other components * Replace old trash icon with new one * Add Size type based on action dialog sizes to be used app wide * Add delete icon button * Add new sizes option to status chip component * Add / update gift cards list components * Add bulk actions type * Work on gift cards list WIP * Small refactor * Fix styling of gift cards table * Remove temp files * Remove unnecessary type * Add gift cards section to menu and add empty list component * Update schema and types * Add link to gift card update page to gift cards list and add route to gift cards index * Extract order page title with status chip into a separate generic component and use it in order page title * wip * Update money component * Add gift card details card balance section * Refactor gift card details * Add vertical spacer component * Update schema and types * Add gift card tag input component along with necessary queries * Add gift card tag input to gift card update page * Add gift card update details card expiry section WIP * Add time period select field WIP * Post rebase refactor * Add time period select field to gift card update view * Fixes after review * Update schema, types and gift cards query * Add getFullName util function and replace existing manual usages * Add text with select field component * Add gift card update info card and refactor * Fix import * Add displaying order link in gift card update * Refactor * Connect gift card list to api * refactor * Add gift card create dialog * Fix gift card list styles, change location for gift card list query, minor refactor * Fix menu structure data for gift cards * Add channel currencies type to shop * Refactor text with select field * Add gift card expiry select component * Add gift card error type and fragment * Update global types * Add default prop to getFormErrors function * Move gift card details provider to providers dir * Update global utils with mapSingleValueNodeToChoice function * Update gift card tag input * Move and refactor time period field * Update schema * move format money function to other money ulities * Update gift card urls * Add content or skeleton component * Add gift card create util for extracting expiry settings input data * Remove content or skeleton component and move displaying logic to existing skeleton * Move displaying logic of gift card create dialog to list * Refactor * Add hooks for gift card bulk actions and gift card list to be used instead of context directly * Fix types for text with select field + add parsing for number typed field * Add initial currency to gift card create form * Fix gift card create dialog closing animation * Add gift card update info card * Refactor gift card update details card * Add gift card balance dialog * Move gift card update form providers to providers dir * Connect gift card update page to api, add necessary contexts etc. * Refactor * Refactor * Add hooks to use instead of gift card contexts directly * Fix types * Fix text field target name missing in passed event in text with select field * Add minimal value option to text with select field, add to gift card inputs * Fix gift card update balance dialog not changing hasChanged prop after submit * Refactor * Fix update balance dialog crashing the app when enetered wrong amount * Fix gift card list table header styles * Add enable / disable section to gift card update * Refactor * Refactor * Refactor * Add metadata to gift card update * Update messages ids * Refactor * Refactor * Refactor * Refactor * Update types after rebase * Fix types * Fixes after qa * Fix tests
This commit is contained in:
parent
6b24fa0dc3
commit
dae95cb410
142 changed files with 11118 additions and 670 deletions
|
@ -1459,6 +1459,9 @@
|
||||||
"context": "dialog title",
|
"context": "dialog title",
|
||||||
"string": "Delete categories"
|
"string": "Delete categories"
|
||||||
},
|
},
|
||||||
|
"src_dot_channel": {
|
||||||
|
"string": "Channel"
|
||||||
|
},
|
||||||
"src_dot_channels": {
|
"src_dot_channels": {
|
||||||
"context": "channels section name",
|
"context": "channels section name",
|
||||||
"string": "Channels"
|
"string": "Channels"
|
||||||
|
@ -1681,8 +1684,8 @@
|
||||||
"context": "tab name",
|
"context": "tab name",
|
||||||
"string": "All Collections"
|
"string": "All Collections"
|
||||||
},
|
},
|
||||||
"src_dot_collections_dot_components_dot_CollectionListPage_dot_4057224233": {
|
"src_dot_collections_dot_components_dot_CollectionListPage_dot_2685595924": {
|
||||||
"string": "Search Collection"
|
"string": "Search Collections"
|
||||||
},
|
},
|
||||||
"src_dot_collections_dot_components_dot_CollectionListPage_dot_686910896": {
|
"src_dot_collections_dot_components_dot_CollectionListPage_dot_686910896": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
|
@ -1709,6 +1712,18 @@
|
||||||
"context": "collection availability",
|
"context": "collection availability",
|
||||||
"string": "Availability"
|
"string": "Availability"
|
||||||
},
|
},
|
||||||
|
"src_dot_collections_dot_components_dot_CollectionList_dot_published": {
|
||||||
|
"context": "collection publication date",
|
||||||
|
"string": "Published on {date}"
|
||||||
|
},
|
||||||
|
"src_dot_collections_dot_components_dot_CollectionList_dot_unpublished": {
|
||||||
|
"context": "collection publication date",
|
||||||
|
"string": "Unpublished"
|
||||||
|
},
|
||||||
|
"src_dot_collections_dot_components_dot_CollectionList_dot_willBePublished": {
|
||||||
|
"context": "collection publication date",
|
||||||
|
"string": "Becomes published on {date}"
|
||||||
|
},
|
||||||
"src_dot_collections_dot_components_dot_CollectionProducts_dot_1657559629": {
|
"src_dot_collections_dot_components_dot_CollectionProducts_dot_1657559629": {
|
||||||
"string": "No products found"
|
"string": "No products found"
|
||||||
},
|
},
|
||||||
|
@ -3385,6 +3400,218 @@
|
||||||
"src_dot_generalInformations": {
|
"src_dot_generalInformations": {
|
||||||
"string": "General Information"
|
"string": "General Information"
|
||||||
},
|
},
|
||||||
|
"src_dot_giftCards": {
|
||||||
|
"context": "gift cards section name",
|
||||||
|
"string": "Gift Cards"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_amountLabel": {
|
||||||
|
"context": "GiftCardCreateDialog amount label",
|
||||||
|
"string": "Enter amount"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_copiedToClipboardTitle": {
|
||||||
|
"context": "GiftCardCreateDialog copied to clipboard title",
|
||||||
|
"string": "Copied to clipboard"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_copyCodeLabel": {
|
||||||
|
"context": "GiftCardCreateDialog copy code label",
|
||||||
|
"string": "Copy code"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_createdGiftCardLabel": {
|
||||||
|
"context": "GiftCardCreateDialog created gift card label",
|
||||||
|
"string": "This is the code of a created gift card:"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_createdSuccessAlertTitle": {
|
||||||
|
"context": "GiftCardCreateDialog createdSuccessAlertTitle",
|
||||||
|
"string": "Successfully created gift card"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_customerLabel": {
|
||||||
|
"context": "GiftCardCreateDialog customer label",
|
||||||
|
"string": "Customer"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_customerSubtitle": {
|
||||||
|
"context": "GiftCardCreateDialog customer 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_GiftCardCreateDialog_dot_issueButtonLabel": {
|
||||||
|
"context": "GiftCardCreateDialog issue button label",
|
||||||
|
"string": "Issue"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_noteLabel": {
|
||||||
|
"context": "GiftCardCreateDialog note label",
|
||||||
|
"string": "Note"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardCreateDialog_dot_noteSubtitle": {
|
||||||
|
"context": "GiftCardCreateDialog note 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_title": {
|
||||||
|
"context": "GiftCardCreateDialog title",
|
||||||
|
"string": "Issue gift card"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateBalanceDialog_dot_changeButtonLabel": {
|
||||||
|
"context": "GiftCardUpdateDetailsCard set balance dialog change button label",
|
||||||
|
"string": "Change"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateBalanceDialog_dot_subtitle": {
|
||||||
|
"context": "GiftCardUpdateDetailsCard 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",
|
||||||
|
"string": "Set balance"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateBalanceDialog_dot_updatedSuccessAlertTitle": {
|
||||||
|
"context": "GiftCardUpdateDetailsCard update success alert title",
|
||||||
|
"string": "Successfully updated card balance"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateDetailsCard_dot_cardBalanceLabel": {
|
||||||
|
"context": "GiftCardUpdateDetailsCard card balance label",
|
||||||
|
"string": "Card Balance"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateDetailsCard_dot_setBalanceButtonLabel": {
|
||||||
|
"context": "GiftCardUpdateDetailsCard set balance button label",
|
||||||
|
"string": "set balance"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateDetailsCard_dot_title": {
|
||||||
|
"context": "GiftCardUpdateDetailsCard title",
|
||||||
|
"string": "Details"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_boughtByLabel": {
|
||||||
|
"context": "GiftCardUpdateInfoCard bought by label",
|
||||||
|
"string": "Bought by"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_creationLabel": {
|
||||||
|
"context": "GiftCardUpdateInfoCard creation label",
|
||||||
|
"string": "Creation"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_issuedByAppLabel": {
|
||||||
|
"context": "GiftCardUpdateInfoCard issued by app label",
|
||||||
|
"string": "Issued by app"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_issuedByLabel": {
|
||||||
|
"context": "GiftCardUpdateInfoCard issued by label",
|
||||||
|
"string": "Issued by"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_orderNumberLabel": {
|
||||||
|
"context": "GiftCardUpdateInfoCard order number label",
|
||||||
|
"string": "Order number"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_productLabel": {
|
||||||
|
"context": "GiftCardUpdateInfoCard product label",
|
||||||
|
"string": "Product bought to get gift card"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_title": {
|
||||||
|
"context": "GiftCardUpdateInfoCard title",
|
||||||
|
"string": "Card information"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdateInfoCard_dot_usedByLabel": {
|
||||||
|
"context": "GiftCardUpdateInfoCard used by label",
|
||||||
|
"string": "Used by"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_disableLabel": {
|
||||||
|
"context": "GiftCardEnableDisableSection enable label",
|
||||||
|
"string": "Disable"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_enableLabel": {
|
||||||
|
"context": "GiftCardEnableDisableSection enable label",
|
||||||
|
"string": "Enable"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_successfullyDisabledTitle": {
|
||||||
|
"context": "GiftCardEnableDisableSection disable success",
|
||||||
|
"string": "Successfully disabled gift card"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_GiftCardUpdatePageHeader_dot_successfullyEnabledTitle": {
|
||||||
|
"context": "GiftCardEnableDisableSection enable success",
|
||||||
|
"string": "Successfully enabled gift card"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardUpdate_dot_title": {
|
||||||
|
"context": "GiftCardUpdateDetailsCard title",
|
||||||
|
"string": "Details"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_bulkIssue": {
|
||||||
|
"context": "GiftCardsListHeader menu item settings",
|
||||||
|
"string": "Bulk Issue"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_codeEndingWithLabel": {
|
||||||
|
"context": "GiftCardsListTable code ending with label",
|
||||||
|
"string": "Code ending with {displayCode}"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_exportCodes": {
|
||||||
|
"context": "GiftCardsListHeader menu item settings",
|
||||||
|
"string": "Export card codes"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardDisabledLabel": {
|
||||||
|
"context": "GiftCardsListTable disabled label",
|
||||||
|
"string": "Disabled"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardsTableColumnBalanceTitle": {
|
||||||
|
"context": "GiftCardsListTable column title balance",
|
||||||
|
"string": "Balance"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardsTableColumnCustomerTitle": {
|
||||||
|
"context": "GiftCardsListTable column title customer",
|
||||||
|
"string": "Used by"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardsTableColumnGiftCardTitle": {
|
||||||
|
"context": "GiftCardsListTable column title gift card",
|
||||||
|
"string": "Gift Card"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardsTableColumnProductTitle": {
|
||||||
|
"context": "GiftCardsListTable column title product",
|
||||||
|
"string": "Product"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_giftCardsTableColumnTagTitle": {
|
||||||
|
"context": "GiftCardsListTable column title tag",
|
||||||
|
"string": "Tag"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_issueButtonLabel": {
|
||||||
|
"context": "GiftCardsListHeader issue button label",
|
||||||
|
"string": "Issue card"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_noGiftCardsFound": {
|
||||||
|
"context": "GiftCardsListTable no cards found title",
|
||||||
|
"string": "No gift cards found"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_GiftCardsList_dot_settings": {
|
||||||
|
"context": "GiftCardsListHeader menu item settings",
|
||||||
|
"string": "Settings"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_components_dot_GiftCardExpirySelect_dot_expirationDateLabel": {
|
||||||
|
"context": "GiftCarUpdateDetailsExpirySection expiration date label",
|
||||||
|
"string": "Expiration date"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_components_dot_GiftCardExpirySelect_dot_expiryDateLabel": {
|
||||||
|
"context": "GiftCarUpdateDetailsExpirySection expiry date label",
|
||||||
|
"string": "Expiration date"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_components_dot_GiftCardExpirySelect_dot_expiryPeriodLabel": {
|
||||||
|
"context": "GiftCarUpdateDetailsExpirySection expiry period label",
|
||||||
|
"string": "Expiry period"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_components_dot_GiftCardExpirySelect_dot_neverExpireLabel": {
|
||||||
|
"context": "GiftCarUpdateDetailsExpirySection never expire label",
|
||||||
|
"string": "Never expire"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_components_dot_GiftCardTagInput_dot_label": {
|
||||||
|
"context": "GiftCardTagInput tag label",
|
||||||
|
"string": "Card Tag"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_components_dot_GiftCardTagInput_dot_placeholder": {
|
||||||
|
"context": "GiftCardTagInput tag placeholder",
|
||||||
|
"string": "Tag"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_components_dot_TimePeriodField_dot_dayLabel": {
|
||||||
|
"context": "TimePeriodTextWithSelectField day label",
|
||||||
|
"string": "days after usage"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_components_dot_TimePeriodField_dot_monthLabel": {
|
||||||
|
"context": "TimePeriodTextWithSelectField month label",
|
||||||
|
"string": "months after usage"
|
||||||
|
},
|
||||||
|
"src_dot_giftCards_dot_components_dot_TimePeriodField_dot_yearLabel": {
|
||||||
|
"context": "TimePeriodTextWithSelectField year label",
|
||||||
|
"string": "years after usage"
|
||||||
|
},
|
||||||
"src_dot_home": {
|
"src_dot_home": {
|
||||||
"context": "home section name",
|
"context": "home section name",
|
||||||
"string": "Home"
|
"string": "Home"
|
||||||
|
@ -5231,18 +5458,6 @@
|
||||||
"context": "products section name",
|
"context": "products section name",
|
||||||
"string": "Products"
|
"string": "Products"
|
||||||
},
|
},
|
||||||
"src_dot_products_dot_components_dot_ProductAvailabilityStatusLabel_dot_published": {
|
|
||||||
"context": "product publication date",
|
|
||||||
"string": "Published on {date}"
|
|
||||||
},
|
|
||||||
"src_dot_products_dot_components_dot_ProductAvailabilityStatusLabel_dot_unpublished": {
|
|
||||||
"context": "product publication date",
|
|
||||||
"string": "Unpublished"
|
|
||||||
},
|
|
||||||
"src_dot_products_dot_components_dot_ProductAvailabilityStatusLabel_dot_willBePublished": {
|
|
||||||
"context": "product publication date",
|
|
||||||
"string": "Becomes published on {date}"
|
|
||||||
},
|
|
||||||
"src_dot_products_dot_components_dot_ProductCategoryAndCollectionsForm_dot_1755013298": {
|
"src_dot_products_dot_components_dot_ProductCategoryAndCollectionsForm_dot_1755013298": {
|
||||||
"string": "Category"
|
"string": "Category"
|
||||||
},
|
},
|
||||||
|
@ -5466,6 +5681,18 @@
|
||||||
"context": "product",
|
"context": "product",
|
||||||
"string": "Name"
|
"string": "Name"
|
||||||
},
|
},
|
||||||
|
"src_dot_products_dot_components_dot_ProductList_dot_published": {
|
||||||
|
"context": "product publication date",
|
||||||
|
"string": "Published on {date}"
|
||||||
|
},
|
||||||
|
"src_dot_products_dot_components_dot_ProductList_dot_unpublished": {
|
||||||
|
"context": "product publication date",
|
||||||
|
"string": "Unpublished"
|
||||||
|
},
|
||||||
|
"src_dot_products_dot_components_dot_ProductList_dot_willBePublished": {
|
||||||
|
"context": "product publication date",
|
||||||
|
"string": "Becomes published on {date}"
|
||||||
|
},
|
||||||
"src_dot_products_dot_components_dot_ProductMediaNavigation_dot_allMedia": {
|
"src_dot_products_dot_components_dot_ProductMediaNavigation_dot_allMedia": {
|
||||||
"context": "section header",
|
"context": "section header",
|
||||||
"string": "All Media"
|
"string": "All Media"
|
||||||
|
|
132
schema.graphql
132
schema.graphql
|
@ -2152,18 +2152,31 @@ type GatewayConfigLine {
|
||||||
|
|
||||||
scalar GenericScalar
|
scalar GenericScalar
|
||||||
|
|
||||||
type GiftCard implements Node {
|
type GiftCard implements Node & ObjectWithMetadata {
|
||||||
code: String
|
code: String!
|
||||||
user: User
|
|
||||||
created: DateTime!
|
|
||||||
startDate: Date!
|
|
||||||
endDate: Date
|
|
||||||
lastUsedOn: DateTime
|
|
||||||
isActive: Boolean!
|
isActive: Boolean!
|
||||||
|
expiryDate: Date
|
||||||
|
expiryType: GiftCardExpiryTypeEnum!
|
||||||
|
tag: String
|
||||||
|
created: DateTime!
|
||||||
|
lastUsedOn: DateTime
|
||||||
initialBalance: Money
|
initialBalance: Money
|
||||||
currentBalance: Money
|
currentBalance: Money
|
||||||
id: ID!
|
id: ID!
|
||||||
displayCode: String
|
privateMetadata: [MetadataItem]!
|
||||||
|
metadata: [MetadataItem]!
|
||||||
|
displayCode: String!
|
||||||
|
createdBy: User
|
||||||
|
usedBy: User
|
||||||
|
createdByEmail: String
|
||||||
|
usedByEmail: String
|
||||||
|
app: App
|
||||||
|
expiryPeriod: TimePeriod
|
||||||
|
product: Product
|
||||||
|
events: [GiftCardEvent!]!
|
||||||
|
user: User @deprecated(reason: "Will be removed in Saleor 4.0. Use created_by field instead")
|
||||||
|
endDate: DateTime @deprecated(reason: "Will be removed in Saleor 4.0. Use expiry_date field instead.")
|
||||||
|
startDate: DateTime @deprecated(reason: "Will be removed in Saleor 4.0.")
|
||||||
}
|
}
|
||||||
|
|
||||||
type GiftCardActivate {
|
type GiftCardActivate {
|
||||||
|
@ -2190,11 +2203,14 @@ type GiftCardCreate {
|
||||||
}
|
}
|
||||||
|
|
||||||
input GiftCardCreateInput {
|
input GiftCardCreateInput {
|
||||||
|
tag: String
|
||||||
startDate: Date
|
startDate: Date
|
||||||
endDate: Date
|
endDate: Date
|
||||||
balance: PositiveDecimal
|
balance: PriceInput!
|
||||||
userEmail: String
|
userEmail: String
|
||||||
|
expirySettings: GiftCardExpirySettingsInput!
|
||||||
code: String
|
code: String
|
||||||
|
note: String
|
||||||
}
|
}
|
||||||
|
|
||||||
type GiftCardDeactivate {
|
type GiftCardDeactivate {
|
||||||
|
@ -2203,6 +2219,12 @@ type GiftCardDeactivate {
|
||||||
errors: [GiftCardError!]!
|
errors: [GiftCardError!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GiftCardDelete {
|
||||||
|
giftCardErrors: [GiftCardError!]! @deprecated(reason: "Use errors field instead. This field will be removed in Saleor 4.0.")
|
||||||
|
errors: [GiftCardError!]!
|
||||||
|
giftCard: GiftCard
|
||||||
|
}
|
||||||
|
|
||||||
type GiftCardError {
|
type GiftCardError {
|
||||||
field: String
|
field: String
|
||||||
message: String
|
message: String
|
||||||
|
@ -2218,6 +2240,66 @@ enum GiftCardErrorCode {
|
||||||
UNIQUE
|
UNIQUE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GiftCardEvent implements Node {
|
||||||
|
id: ID!
|
||||||
|
date: DateTime
|
||||||
|
type: GiftCardEventsEnum
|
||||||
|
user: User
|
||||||
|
app: App
|
||||||
|
message: String
|
||||||
|
email: String
|
||||||
|
orderId: ID
|
||||||
|
orderNumber: String
|
||||||
|
tag: String
|
||||||
|
oldTag: String
|
||||||
|
balance: GiftCardEventBalance
|
||||||
|
expiry: GiftCardEventExpiry
|
||||||
|
}
|
||||||
|
|
||||||
|
type GiftCardEventBalance {
|
||||||
|
initialBalance: Money!
|
||||||
|
currentBalance: Money!
|
||||||
|
oldInitialBalance: Money
|
||||||
|
oldCurrentBalance: Money
|
||||||
|
}
|
||||||
|
|
||||||
|
type GiftCardEventExpiry {
|
||||||
|
expiryType: GiftCardExpiryTypeEnum
|
||||||
|
expiryPeriod: TimePeriod
|
||||||
|
expiryDate: Date
|
||||||
|
oldExpiryType: GiftCardExpiryTypeEnum
|
||||||
|
oldExpiryPeriod: TimePeriod
|
||||||
|
oldExpiryDate: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GiftCardEventsEnum {
|
||||||
|
ISSUED
|
||||||
|
BOUGHT
|
||||||
|
UPDATED
|
||||||
|
ACTIVATED
|
||||||
|
DEACTIVATED
|
||||||
|
BALANCE_RESET
|
||||||
|
EXPIRY_SETTINGS_UPDATED
|
||||||
|
SENT_TO_CUSTOMER
|
||||||
|
RESENT
|
||||||
|
}
|
||||||
|
|
||||||
|
input GiftCardExpirySettingsInput {
|
||||||
|
expiryType: GiftCardExpiryTypeEnum!
|
||||||
|
expiryDate: Date
|
||||||
|
expiryPeriod: TimePeriodInputType
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GiftCardExpiryTypeEnum {
|
||||||
|
NEVER_EXPIRE
|
||||||
|
EXPIRY_PERIOD
|
||||||
|
EXPIRY_DATE
|
||||||
|
}
|
||||||
|
|
||||||
|
input GiftCardFilterInput {
|
||||||
|
tag: String
|
||||||
|
}
|
||||||
|
|
||||||
type GiftCardUpdate {
|
type GiftCardUpdate {
|
||||||
giftCardErrors: [GiftCardError!]! @deprecated(reason: "Use errors field instead. This field will be removed in Saleor 4.0.")
|
giftCardErrors: [GiftCardError!]! @deprecated(reason: "Use errors field instead. This field will be removed in Saleor 4.0.")
|
||||||
errors: [GiftCardError!]!
|
errors: [GiftCardError!]!
|
||||||
|
@ -2225,10 +2307,11 @@ type GiftCardUpdate {
|
||||||
}
|
}
|
||||||
|
|
||||||
input GiftCardUpdateInput {
|
input GiftCardUpdateInput {
|
||||||
|
tag: String
|
||||||
startDate: Date
|
startDate: Date
|
||||||
endDate: Date
|
endDate: Date
|
||||||
balance: PositiveDecimal
|
balanceAmount: PositiveDecimal
|
||||||
userEmail: String
|
expirySettings: GiftCardExpirySettingsInput
|
||||||
}
|
}
|
||||||
|
|
||||||
type Group implements Node {
|
type Group implements Node {
|
||||||
|
@ -2868,6 +2951,7 @@ type Mutation {
|
||||||
invoiceSendNotification(id: ID!): InvoiceSendNotification
|
invoiceSendNotification(id: ID!): InvoiceSendNotification
|
||||||
giftCardActivate(id: ID!): GiftCardActivate
|
giftCardActivate(id: ID!): GiftCardActivate
|
||||||
giftCardCreate(input: GiftCardCreateInput!): GiftCardCreate
|
giftCardCreate(input: GiftCardCreateInput!): GiftCardCreate
|
||||||
|
giftCardDelete(id: ID!): GiftCardDelete
|
||||||
giftCardDeactivate(id: ID!): GiftCardDeactivate
|
giftCardDeactivate(id: ID!): GiftCardDeactivate
|
||||||
giftCardUpdate(id: ID!, input: GiftCardUpdateInput!): GiftCardUpdate
|
giftCardUpdate(id: ID!, input: GiftCardUpdateInput!): GiftCardUpdate
|
||||||
pluginUpdate(channelId: ID, id: ID!, input: PluginUpdateInput!): PluginUpdate
|
pluginUpdate(channelId: ID, id: ID!, input: PluginUpdateInput!): PluginUpdate
|
||||||
|
@ -4102,6 +4186,11 @@ enum PostalCodeRuleInclusionTypeEnum {
|
||||||
EXCLUDE
|
EXCLUDE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input PriceInput {
|
||||||
|
currency: String!
|
||||||
|
amount: PositiveDecimal!
|
||||||
|
}
|
||||||
|
|
||||||
input PriceRangeInput {
|
input PriceRangeInput {
|
||||||
gte: Float
|
gte: Float
|
||||||
lte: Float
|
lte: Float
|
||||||
|
@ -4787,7 +4876,7 @@ type Query {
|
||||||
menuItem(id: ID!, channel: String): MenuItem
|
menuItem(id: ID!, channel: String): MenuItem
|
||||||
menuItems(channel: String, sortBy: MenuItemSortingInput, filter: MenuItemFilterInput, before: String, after: String, first: Int, last: Int): MenuItemCountableConnection
|
menuItems(channel: String, sortBy: MenuItemSortingInput, filter: MenuItemFilterInput, before: String, after: String, first: Int, last: Int): MenuItemCountableConnection
|
||||||
giftCard(id: ID!): GiftCard
|
giftCard(id: ID!): GiftCard
|
||||||
giftCards(before: String, after: String, first: Int, last: Int): GiftCardCountableConnection
|
giftCards(filter: GiftCardFilterInput, before: String, after: String, first: Int, last: Int): GiftCardCountableConnection
|
||||||
plugin(id: ID!): Plugin
|
plugin(id: ID!): Plugin
|
||||||
plugins(filter: PluginFilterInput, sortBy: PluginSortingInput, before: String, after: String, first: Int, last: Int): PluginCountableConnection
|
plugins(filter: PluginFilterInput, sortBy: PluginSortingInput, before: String, after: String, first: Int, last: Int): PluginCountableConnection
|
||||||
sale(id: ID!, channel: String): Sale
|
sale(id: ID!, channel: String): Sale
|
||||||
|
@ -5258,6 +5347,7 @@ type Shop {
|
||||||
availablePaymentGateways(currency: String, channel: String): [PaymentGateway!]!
|
availablePaymentGateways(currency: String, channel: String): [PaymentGateway!]!
|
||||||
availableExternalAuthentications: [ExternalAuthentication!]!
|
availableExternalAuthentications: [ExternalAuthentication!]!
|
||||||
availableShippingMethods(channel: String!, address: AddressInput): [ShippingMethod]
|
availableShippingMethods(channel: String!, address: AddressInput): [ShippingMethod]
|
||||||
|
channelCurrencies: [String!]!
|
||||||
countries(languageCode: LanguageCodeEnum): [CountryDisplay!]!
|
countries(languageCode: LanguageCodeEnum): [CountryDisplay!]!
|
||||||
defaultCountry: CountryDisplay
|
defaultCountry: CountryDisplay
|
||||||
defaultMailSenderName: String
|
defaultMailSenderName: String
|
||||||
|
@ -5525,6 +5615,22 @@ type TaxedMoneyRange {
|
||||||
stop: TaxedMoney
|
stop: TaxedMoney
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TimePeriod {
|
||||||
|
amount: Int!
|
||||||
|
type: TimePeriodTypeEnum!
|
||||||
|
}
|
||||||
|
|
||||||
|
input TimePeriodInputType {
|
||||||
|
amount: Int!
|
||||||
|
type: TimePeriodTypeEnum!
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TimePeriodTypeEnum {
|
||||||
|
DAY
|
||||||
|
MONTH
|
||||||
|
YEAR
|
||||||
|
}
|
||||||
|
|
||||||
type Transaction implements Node {
|
type Transaction implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
created: DateTime!
|
created: DateTime!
|
||||||
|
@ -6203,4 +6309,4 @@ union _Entity = App | Address | User | Group | ProductVariant | Product | Produc
|
||||||
|
|
||||||
type _Service {
|
type _Service {
|
||||||
sdl: String
|
sdl: String
|
||||||
}
|
}
|
23
src/apps/components/VerticalSpacer/VerticalSpacer.tsx
Normal file
23
src/apps/components/VerticalSpacer/VerticalSpacer.tsx
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export interface VerticalSpacerProps {
|
||||||
|
spacing?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
container: ({ spacing }: VerticalSpacerProps) => ({
|
||||||
|
height: theme.spacing(spacing)
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
{ name: "VerticalSpacer" }
|
||||||
|
);
|
||||||
|
|
||||||
|
const VerticalSpacer: React.FC<VerticalSpacerProps> = ({ spacing = 1 }) => {
|
||||||
|
const classes = useStyles({ spacing });
|
||||||
|
|
||||||
|
return <div className={classes.container} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VerticalSpacer;
|
2
src/apps/components/VerticalSpacer/index.tsx
Normal file
2
src/apps/components/VerticalSpacer/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./VerticalSpacer";
|
||||||
|
export { default } from "./VerticalSpacer";
|
|
@ -2,7 +2,7 @@ import { DEMO_MODE } from "@saleor/config";
|
||||||
import { User } from "@saleor/fragments/types/User";
|
import { User } from "@saleor/fragments/types/User";
|
||||||
import { SetLocalStorage } from "@saleor/hooks/useLocalStorage";
|
import { SetLocalStorage } from "@saleor/hooks/useLocalStorage";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { getMutationStatus } from "@saleor/misc";
|
import { getFullName, getMutationStatus } from "@saleor/misc";
|
||||||
import errorTracker from "@saleor/services/errorTracking";
|
import errorTracker from "@saleor/services/errorTracking";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useMutation } from "react-apollo";
|
import { useMutation } from "react-apollo";
|
||||||
|
@ -88,11 +88,11 @@ export function useExternalAuthProvider({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (authPlugin && userContext) {
|
if (authPlugin && userContext) {
|
||||||
const { id, email, firstName, lastName } = userContext;
|
const { id, email } = userContext;
|
||||||
errorTracker.setUserData({
|
errorTracker.setUserData({
|
||||||
email,
|
email,
|
||||||
id,
|
id,
|
||||||
username: `${firstName} ${lastName}`
|
username: getFullName(userContext)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!userContext.isStaff) {
|
if (!userContext.isStaff) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { DEMO_MODE } from "@saleor/config";
|
||||||
import { User } from "@saleor/fragments/types/User";
|
import { User } from "@saleor/fragments/types/User";
|
||||||
import { SetLocalStorage } from "@saleor/hooks/useLocalStorage";
|
import { SetLocalStorage } from "@saleor/hooks/useLocalStorage";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { getMutationStatus } from "@saleor/misc";
|
import { getFullName, getMutationStatus } from "@saleor/misc";
|
||||||
import errorTracker from "@saleor/services/errorTracking";
|
import errorTracker from "@saleor/services/errorTracking";
|
||||||
import {
|
import {
|
||||||
isSupported as isCredentialsManagementAPISupported,
|
isSupported as isCredentialsManagementAPISupported,
|
||||||
|
@ -66,11 +66,11 @@ export function useSaleorAuthProvider({
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!authPlugin && userContext) {
|
if (!authPlugin && userContext) {
|
||||||
const { id, email, firstName, lastName } = userContext;
|
const { id, email } = userContext;
|
||||||
errorTracker.setUserData({
|
errorTracker.setUserData({
|
||||||
email,
|
email,
|
||||||
id,
|
id,
|
||||||
username: `${firstName} ${lastName}`
|
username: getFullName(userContext)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!userContext.isStaff) {
|
if (!userContext.isStaff) {
|
||||||
|
|
|
@ -56,11 +56,11 @@ export function createFilterStructure(
|
||||||
...createOptionsField(
|
...createOptionsField(
|
||||||
CollectionFilterKeys.channel,
|
CollectionFilterKeys.channel,
|
||||||
intl.formatMessage(commonMessages.channel),
|
intl.formatMessage(commonMessages.channel),
|
||||||
[opts.channel.value],
|
[opts.channel?.value],
|
||||||
false,
|
false,
|
||||||
opts.channel.choices
|
opts.channel?.choices
|
||||||
),
|
),
|
||||||
active: opts.channel.active
|
active: opts.channel?.active
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,4 +65,5 @@ export interface CollectionListVariables {
|
||||||
before?: string | null;
|
before?: string | null;
|
||||||
filter?: CollectionFilterInput | null;
|
filter?: CollectionFilterInput | null;
|
||||||
sort?: CollectionSortingInput | null;
|
sort?: CollectionSortingInput | null;
|
||||||
|
channel?: string | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,6 @@ export const CollectionList: React.FC<CollectionListProps> = ({ params }) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const filterOpts = getFilterOpts(params, channelOpts);
|
const filterOpts = getFilterOpts(params, channelOpts);
|
||||||
const tabs = getFilterTabs();
|
const tabs = getFilterTabs();
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
exports[`Filtering URL params should not be empty if active filters are present 1`] = `
|
exports[`Filtering URL params should not be empty if active filters are present 1`] = `
|
||||||
Object {
|
Object {
|
||||||
|
"channel": undefined,
|
||||||
"status": "PUBLISHED",
|
"status": "PUBLISHED",
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -4,14 +4,14 @@ import React from "react";
|
||||||
|
|
||||||
import { ConfirmButtonTransitionState } from "../ConfirmButton";
|
import { ConfirmButtonTransitionState } from "../ConfirmButton";
|
||||||
import DialogButtons from "./DialogButtons";
|
import DialogButtons from "./DialogButtons";
|
||||||
import { ActionDialogVariant } from "./types";
|
import { ActionDialogVariant, Size } from "./types";
|
||||||
|
|
||||||
interface ActionDialogProps extends DialogProps {
|
interface ActionDialogProps extends DialogProps {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
confirmButtonLabel?: string;
|
confirmButtonLabel?: string;
|
||||||
confirmButtonState: ConfirmButtonTransitionState;
|
confirmButtonState: ConfirmButtonTransitionState;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
maxWidth?: "xs" | "sm" | "md" | "lg" | "xl" | false;
|
maxWidth?: Size | false;
|
||||||
title: string;
|
title: string;
|
||||||
variant?: ActionDialogVariant;
|
variant?: ActionDialogVariant;
|
||||||
onConfirm();
|
onConfirm();
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
export type ActionDialogVariant = "default" | "delete" | "info";
|
export type ActionDialogVariant = "default" | "delete" | "info";
|
||||||
|
|
||||||
|
export type Size = "xs" | "sm" | "md" | "lg" | "xl";
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
useSavebar,
|
useSavebar,
|
||||||
useTheme
|
useTheme
|
||||||
} from "@saleor/macaw-ui";
|
} from "@saleor/macaw-ui";
|
||||||
|
import { isDarkTheme } from "@saleor/misc";
|
||||||
import { staffMemberDetailsUrl } from "@saleor/staff/urls";
|
import { staffMemberDetailsUrl } from "@saleor/staff/urls";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
@ -154,8 +155,7 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const isDark = themeType === "dark";
|
const toggleTheme = () => setTheme(isDarkTheme(themeType) ? "light" : "dark");
|
||||||
const toggleTheme = () => setTheme(isDark ? "light" : "dark");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -203,7 +203,7 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<UserChip
|
<UserChip
|
||||||
isDarkThemeEnabled={isDark}
|
isDarkThemeEnabled={isDarkTheme(themeType)}
|
||||||
user={user}
|
user={user}
|
||||||
onLogout={logout}
|
onLogout={logout}
|
||||||
onProfileClick={() =>
|
onProfileClick={() =>
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
} from "@saleor/configuration";
|
} from "@saleor/configuration";
|
||||||
import { MenuItem } from "@saleor/configuration/ConfigurationPage";
|
import { MenuItem } from "@saleor/configuration/ConfigurationPage";
|
||||||
import { User } from "@saleor/fragments/types/User";
|
import { User } from "@saleor/fragments/types/User";
|
||||||
|
import { giftCardsListUrl } from "@saleor/giftCards/urls";
|
||||||
import { commonMessages, sectionNames } from "@saleor/intl";
|
import { commonMessages, sectionNames } from "@saleor/intl";
|
||||||
import { SidebarMenuItem } from "@saleor/macaw-ui";
|
import { SidebarMenuItem } from "@saleor/macaw-ui";
|
||||||
import { IntlShape } from "react-intl";
|
import { IntlShape } from "react-intl";
|
||||||
|
@ -62,6 +63,12 @@ function createMenuStructure(intl: IntlShape, user: User): SidebarMenuItem[] {
|
||||||
label: intl.formatMessage(sectionNames.collections),
|
label: intl.formatMessage(sectionNames.collections),
|
||||||
id: "collections",
|
id: "collections",
|
||||||
url: collectionListUrl()
|
url: collectionListUrl()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ariaLabel: "giftCards",
|
||||||
|
label: intl.formatMessage(sectionNames.giftCards),
|
||||||
|
id: "giftCards",
|
||||||
|
url: giftCardsListUrl()
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
iconSrc: catalogIcon,
|
iconSrc: catalogIcon,
|
||||||
|
|
11
src/components/DeleteIconButton/DeleteIconButton.tsx
Normal file
11
src/components/DeleteIconButton/DeleteIconButton.tsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { IconButton, IconButtonProps } from "@material-ui/core";
|
||||||
|
import TrashIcon from "@saleor/icons/Trash";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const DeleteIconButton: React.FC<IconButtonProps> = ({ onClick }) => (
|
||||||
|
<IconButton color="primary" onClick={onClick}>
|
||||||
|
<TrashIcon />
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default DeleteIconButton;
|
2
src/components/DeleteIconButton/index.tsx
Normal file
2
src/components/DeleteIconButton/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./DeleteIconButton";
|
||||||
|
export { default } from "./DeleteIconButton";
|
|
@ -1,35 +1,43 @@
|
||||||
|
import { makeStyles, Typography, TypographyProps } from "@material-ui/core";
|
||||||
|
import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { LocaleConsumer } from "../Locale";
|
|
||||||
|
|
||||||
export interface IMoney {
|
export interface IMoney {
|
||||||
amount: number;
|
amount: number;
|
||||||
currency: string;
|
currency: string;
|
||||||
}
|
}
|
||||||
export interface MoneyProps {
|
|
||||||
|
export interface MoneyProps extends TypographyProps {
|
||||||
money: IMoney | null;
|
money: IMoney | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const formatMoney = (money: IMoney, locale: string) => {
|
const useStyles = makeStyles(
|
||||||
try {
|
() => ({
|
||||||
const formattedMoney = money.amount.toLocaleString(locale, {
|
container: {
|
||||||
currency: money.currency,
|
display: "flex",
|
||||||
style: "currency"
|
alignItems: "baseline"
|
||||||
});
|
}
|
||||||
return formattedMoney;
|
}),
|
||||||
} catch (error) {
|
{ name: "Money" }
|
||||||
return `${money.amount} ${money.currency}`;
|
);
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Money: React.FC<MoneyProps> = ({ money }) =>
|
export const Money: React.FC<MoneyProps> = ({ money, ...rest }) => {
|
||||||
money ? (
|
const classes = useStyles({});
|
||||||
<LocaleConsumer>
|
|
||||||
{({ locale }) => formatMoney(money, locale)}
|
if (!money) {
|
||||||
</LocaleConsumer>
|
return null;
|
||||||
) : (
|
}
|
||||||
<>-</>
|
|
||||||
|
return (
|
||||||
|
<div className={classes.container}>
|
||||||
|
<Typography variant="caption" {...rest}>
|
||||||
|
{money.currency}
|
||||||
|
</Typography>
|
||||||
|
<HorizontalSpacer spacing={0.5} />
|
||||||
|
<Typography {...rest}>{money.amount.toFixed(2)}</Typography>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
Money.displayName = "Money";
|
Money.displayName = "Money";
|
||||||
export default Money;
|
export default Money;
|
||||||
|
|
|
@ -15,3 +15,15 @@ export function subtractMoney(init: IMoney, ...args: IMoney[]): IMoney {
|
||||||
currency: init.currency
|
currency: init.currency
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const formatMoney = (money: IMoney, locale: string) => {
|
||||||
|
try {
|
||||||
|
const formattedMoney = money.amount.toLocaleString(locale, {
|
||||||
|
currency: money.currency,
|
||||||
|
style: "currency"
|
||||||
|
});
|
||||||
|
return formattedMoney;
|
||||||
|
} catch (error) {
|
||||||
|
return `${money.amount} ${money.currency}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -30,9 +30,10 @@ const useStyles = makeStyles(
|
||||||
marginTop: theme.spacing(2),
|
marginTop: theme.spacing(2),
|
||||||
padding: 0
|
padding: 0
|
||||||
},
|
},
|
||||||
|
fontWeight: 700,
|
||||||
alignSelf: "flex-start",
|
alignSelf: "flex-start",
|
||||||
flex: 1,
|
flex: 1,
|
||||||
fontSize: 24
|
fontSize: 48
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
{ name: "PageHeader" }
|
{ name: "PageHeader" }
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
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";
|
||||||
|
|
||||||
|
export interface PageTitleWithStatusChipProps {
|
||||||
|
title: string;
|
||||||
|
statusLabel: string;
|
||||||
|
statusType: StatusType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
() => ({
|
||||||
|
container: {
|
||||||
|
alignItems: "center",
|
||||||
|
display: "flex"
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "OrderDetailsPageTitleWithStatusChip" }
|
||||||
|
);
|
||||||
|
|
||||||
|
const PageTitleWithStatusChip: React.FC<PageTitleWithStatusChipProps> = ({
|
||||||
|
title,
|
||||||
|
statusLabel,
|
||||||
|
statusType
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles({});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.container}>
|
||||||
|
{title}
|
||||||
|
<HorizontalSpacer spacing={2} />
|
||||||
|
<StatusChip label={statusLabel} status={statusType} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PageTitleWithStatusChip;
|
2
src/components/PageTitleWithStatusChip/index.tsx
Normal file
2
src/components/PageTitleWithStatusChip/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./PageTitleWithStatusChip";
|
||||||
|
export { default } from "./PageTitleWithStatusChip";
|
|
@ -13,6 +13,7 @@ const shopInfo = gql`
|
||||||
country
|
country
|
||||||
code
|
code
|
||||||
}
|
}
|
||||||
|
channelCurrencies
|
||||||
defaultCountry {
|
defaultCountry {
|
||||||
code
|
code
|
||||||
country
|
country
|
||||||
|
|
|
@ -42,6 +42,7 @@ export interface ShopInfo_shop_permissions {
|
||||||
export interface ShopInfo_shop {
|
export interface ShopInfo_shop {
|
||||||
__typename: "Shop";
|
__typename: "Shop";
|
||||||
countries: ShopInfo_shop_countries[];
|
countries: ShopInfo_shop_countries[];
|
||||||
|
channelCurrencies: string[];
|
||||||
defaultCountry: ShopInfo_shop_defaultCountry | null;
|
defaultCountry: ShopInfo_shop_defaultCountry | null;
|
||||||
defaultWeightUnit: WeightUnitsEnum | null;
|
defaultWeightUnit: WeightUnitsEnum | null;
|
||||||
displayGrossPrices: boolean;
|
displayGrossPrices: boolean;
|
||||||
|
|
|
@ -33,14 +33,17 @@ interface SkeletonProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
primary?: boolean;
|
primary?: boolean;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Skeleton: React.FC<SkeletonProps> = props => {
|
const Skeleton: React.FC<SkeletonProps> = props => {
|
||||||
const { className, primary, style } = props;
|
const { className, primary, style, children } = props;
|
||||||
|
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
|
||||||
return (
|
return children ? (
|
||||||
|
(children as React.ReactElement)
|
||||||
|
) : (
|
||||||
<span
|
<span
|
||||||
data-test-id="skeleton"
|
data-test-id="skeleton"
|
||||||
className={classNames(classes.skeleton, className, {
|
className={classNames(classes.skeleton, className, {
|
||||||
|
|
|
@ -7,7 +7,11 @@ import { StatusType } from "./types";
|
||||||
|
|
||||||
storiesOf("Generics / Status Chip", module)
|
storiesOf("Generics / Status Chip", module)
|
||||||
.addDecorator(Decorator)
|
.addDecorator(Decorator)
|
||||||
.add("neutral", () => <StatusChip label="label" type={StatusType.NEUTRAL} />)
|
.add("neutral", () => (
|
||||||
.add("error", () => <StatusChip label="label" type={StatusType.ERROR} />)
|
<StatusChip label="label" status={StatusType.NEUTRAL} />
|
||||||
.add("success", () => <StatusChip label="label" type={StatusType.SUCCESS} />)
|
))
|
||||||
.add("alert", () => <StatusChip label="label" type={StatusType.ALERT} />);
|
.add("error", () => <StatusChip label="label" status={StatusType.ERROR} />)
|
||||||
|
.add("success", () => (
|
||||||
|
<StatusChip label="label" status={StatusType.SUCCESS} />
|
||||||
|
))
|
||||||
|
.add("alert", () => <StatusChip label="label" status={StatusType.ALERT} />);
|
||||||
|
|
|
@ -3,14 +3,16 @@ import { makeStyles } from "@saleor/macaw-ui";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
import { Size } from "../ActionDialog/types";
|
||||||
import { StatusType } from "./types";
|
import { StatusType } from "./types";
|
||||||
|
|
||||||
export interface StatusChipProps {
|
export interface StatusChipProps {
|
||||||
type?: StatusType;
|
status?: StatusType;
|
||||||
|
size?: Size;
|
||||||
label?: string;
|
label?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StatusChipStyles = {
|
export const statusChipStyles = {
|
||||||
alert: {
|
alert: {
|
||||||
background: "#FFF4E4"
|
background: "#FFF4E4"
|
||||||
},
|
},
|
||||||
|
@ -34,28 +36,38 @@ const StatusChipStyles = {
|
||||||
},
|
},
|
||||||
successLabel: {
|
successLabel: {
|
||||||
color: "#5DC292"
|
color: "#5DC292"
|
||||||
|
},
|
||||||
|
lg: {
|
||||||
|
padding: "4px 16px"
|
||||||
|
},
|
||||||
|
lgLabel: {
|
||||||
|
fontSize: "1.5rem"
|
||||||
|
},
|
||||||
|
md: {
|
||||||
|
padding: "4px 16px"
|
||||||
|
},
|
||||||
|
mdLabel: {
|
||||||
|
fontSize: 16
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
theme => ({
|
theme => ({
|
||||||
label: {
|
label: {
|
||||||
fontSize: theme.typography.body1.fontSize,
|
|
||||||
fontWeight: theme.typography.fontWeightBold,
|
fontWeight: theme.typography.fontWeightBold,
|
||||||
textTransform: "uppercase"
|
textTransform: "uppercase"
|
||||||
},
|
},
|
||||||
root: {
|
root: {
|
||||||
borderRadius: 22,
|
borderRadius: 22,
|
||||||
display: "inline-block",
|
display: "inline-block"
|
||||||
padding: "8px 24px"
|
|
||||||
},
|
},
|
||||||
...StatusChipStyles
|
...statusChipStyles
|
||||||
}),
|
}),
|
||||||
{ name: "StatusChip" }
|
{ name: "StatusChip" }
|
||||||
);
|
);
|
||||||
|
|
||||||
const StatusChip: React.FC<StatusChipProps> = props => {
|
const StatusChip: React.FC<StatusChipProps> = props => {
|
||||||
const { type = StatusType.NEUTRAL, label } = props;
|
const { status = StatusType.NEUTRAL, size = "lg", label } = props;
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
|
||||||
if (!label) {
|
if (!label) {
|
||||||
|
@ -63,9 +75,13 @@ const StatusChip: React.FC<StatusChipProps> = props => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(classes.root, classes[type])}>
|
<div className={classNames(classes.root, classes[status], classes[size])}>
|
||||||
<Typography
|
<Typography
|
||||||
className={classNames(classes.label, classes[`${type}Label`])}
|
className={classNames(
|
||||||
|
classes.label,
|
||||||
|
classes[`${status}Label`],
|
||||||
|
classes[`${size}Label`]
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { fade } from "@material-ui/core/styles/colorManipulator";
|
||||||
import ArrowLeft from "@material-ui/icons/ArrowLeft";
|
import ArrowLeft from "@material-ui/icons/ArrowLeft";
|
||||||
import ArrowRight from "@material-ui/icons/ArrowRight";
|
import ArrowRight from "@material-ui/icons/ArrowRight";
|
||||||
import { makeStyles, useTheme } from "@saleor/macaw-ui";
|
import { makeStyles, useTheme } from "@saleor/macaw-ui";
|
||||||
|
import { isDarkTheme } from "@saleor/misc";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ export const TablePaginationActions: React.FC<TablePaginationActionsProps> = pro
|
||||||
|
|
||||||
const { direction, themeType } = useTheme();
|
const { direction, themeType } = useTheme();
|
||||||
|
|
||||||
const isDark = themeType === "dark";
|
const isDark = isDarkTheme(themeType);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(classes.root, className)} {...other}>
|
<div className={classNames(classes.root, className)} {...other}>
|
||||||
|
|
125
src/components/TextWithSelectField/TextWithSelectField.tsx
Normal file
125
src/components/TextWithSelectField/TextWithSelectField.tsx
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
import { TextField } from "@material-ui/core";
|
||||||
|
import SingleSelectField, {
|
||||||
|
Choices
|
||||||
|
} from "@saleor/components/SingleSelectField";
|
||||||
|
import { ChangeEvent, FormChange } from "@saleor/hooks/useForm";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { useStyles } from "./styles";
|
||||||
|
|
||||||
|
interface CommonFieldProps {
|
||||||
|
name: string;
|
||||||
|
type?: string;
|
||||||
|
className?: string;
|
||||||
|
label?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TextWithSelectFieldProps {
|
||||||
|
change: FormChange;
|
||||||
|
choices: Choices;
|
||||||
|
helperText?: string;
|
||||||
|
isError?: boolean;
|
||||||
|
textFieldProps: CommonFieldProps & {
|
||||||
|
value?: string | number;
|
||||||
|
minValue?: number;
|
||||||
|
};
|
||||||
|
selectFieldProps: CommonFieldProps & { value: string };
|
||||||
|
containerClassName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TextWithSelectField: React.FC<TextWithSelectFieldProps> = ({
|
||||||
|
change,
|
||||||
|
choices,
|
||||||
|
containerClassName,
|
||||||
|
textFieldProps,
|
||||||
|
selectFieldProps,
|
||||||
|
helperText,
|
||||||
|
isError
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
const {
|
||||||
|
name: textFieldName,
|
||||||
|
value: textFieldValue,
|
||||||
|
label: textFieldLabel,
|
||||||
|
type: textFieldType,
|
||||||
|
minValue: textFieldMinValue
|
||||||
|
} = textFieldProps;
|
||||||
|
|
||||||
|
const {
|
||||||
|
name: selectFieldName,
|
||||||
|
value: selectFieldValue,
|
||||||
|
className: selectFieldClassName
|
||||||
|
} = selectFieldProps;
|
||||||
|
|
||||||
|
const handleSelectChange = (event: ChangeEvent) => {
|
||||||
|
// in case one of the fields in the form is empty
|
||||||
|
// we need to save the other part of the field as well
|
||||||
|
const otherTarget = {
|
||||||
|
value: textFieldValue,
|
||||||
|
name: textFieldName
|
||||||
|
};
|
||||||
|
|
||||||
|
change(event);
|
||||||
|
change({ target: otherTarget });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTextChange = (event: ChangeEvent) => {
|
||||||
|
const { value } = event.target;
|
||||||
|
|
||||||
|
const otherTarget = {
|
||||||
|
value: selectFieldValue,
|
||||||
|
name: selectFieldName
|
||||||
|
};
|
||||||
|
|
||||||
|
// handle parsing in case of text field of type number
|
||||||
|
const parsedValue =
|
||||||
|
textFieldType === "number" && typeof value === "string"
|
||||||
|
? parseInt(value, 10)
|
||||||
|
: value;
|
||||||
|
|
||||||
|
change({
|
||||||
|
...event,
|
||||||
|
target: { ...event.target, value: parsedValue, name: event.target.name }
|
||||||
|
});
|
||||||
|
change({ target: otherTarget });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={containerClassName || classes.container}>
|
||||||
|
<TextField
|
||||||
|
error={isError}
|
||||||
|
helperText={helperText}
|
||||||
|
type="number"
|
||||||
|
className={classes.innerContainer}
|
||||||
|
name={textFieldName}
|
||||||
|
label={textFieldLabel}
|
||||||
|
inputProps={{
|
||||||
|
min: textFieldMinValue
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
className: classNames(classes.textField, {
|
||||||
|
[classes.textFieldCentered]: !textFieldLabel
|
||||||
|
}),
|
||||||
|
endAdornment: (
|
||||||
|
<SingleSelectField
|
||||||
|
name={selectFieldName}
|
||||||
|
onChange={handleSelectChange}
|
||||||
|
value={selectFieldValue}
|
||||||
|
className={classNames(
|
||||||
|
classes.autocompleteField,
|
||||||
|
selectFieldClassName
|
||||||
|
)}
|
||||||
|
choices={choices}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
onChange={handleTextChange}
|
||||||
|
value={textFieldValue}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TextWithSelectField;
|
2
src/components/TextWithSelectField/index.tsx
Normal file
2
src/components/TextWithSelectField/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./TextWithSelectField";
|
||||||
|
export { default } from "./TextWithSelectField";
|
36
src/components/TextWithSelectField/styles.ts
Normal file
36
src/components/TextWithSelectField/styles.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
|
export const useStyles = makeStyles(
|
||||||
|
() => ({
|
||||||
|
container: {
|
||||||
|
width: 400
|
||||||
|
},
|
||||||
|
innerContainer: {
|
||||||
|
width: "100%"
|
||||||
|
},
|
||||||
|
textField: {
|
||||||
|
width: "100%",
|
||||||
|
paddingRight: 0,
|
||||||
|
"& input": {
|
||||||
|
maxWidth: "100%"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
textFieldCentered: {
|
||||||
|
"& input": {
|
||||||
|
paddingTop: 16,
|
||||||
|
paddingBottom: 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
autocompleteField: {
|
||||||
|
height: 52,
|
||||||
|
border: "none",
|
||||||
|
"& *": {
|
||||||
|
border: "none"
|
||||||
|
},
|
||||||
|
"& *:focus": {
|
||||||
|
background: "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "TextWithSelectField" }
|
||||||
|
);
|
|
@ -22,6 +22,7 @@ export const PAGINATE_BY = 20;
|
||||||
export const VALUES_PAGINATE_BY = 10;
|
export const VALUES_PAGINATE_BY = 10;
|
||||||
|
|
||||||
export type ProductListColumns = "productType" | "availability" | "price";
|
export type ProductListColumns = "productType" | "availability" | "price";
|
||||||
|
|
||||||
export interface AppListViewSettings {
|
export interface AppListViewSettings {
|
||||||
[ListViews.APPS_LIST]: ListSettings;
|
[ListViews.APPS_LIST]: ListSettings;
|
||||||
[ListViews.ATTRIBUTE_VALUE_LIST]: ListSettings;
|
[ListViews.ATTRIBUTE_VALUE_LIST]: ListSettings;
|
||||||
|
@ -42,7 +43,9 @@ export interface AppListViewSettings {
|
||||||
[ListViews.WAREHOUSE_LIST]: ListSettings;
|
[ListViews.WAREHOUSE_LIST]: ListSettings;
|
||||||
[ListViews.WEBHOOK_LIST]: ListSettings;
|
[ListViews.WEBHOOK_LIST]: ListSettings;
|
||||||
[ListViews.TRANSLATION_ATTRIBUTE_VALUE_LIST]: ListSettings;
|
[ListViews.TRANSLATION_ATTRIBUTE_VALUE_LIST]: ListSettings;
|
||||||
|
[ListViews.GIFT_CARD_LIST]: ListSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultListSettings: AppListViewSettings = {
|
export const defaultListSettings: AppListViewSettings = {
|
||||||
[ListViews.APPS_LIST]: {
|
[ListViews.APPS_LIST]: {
|
||||||
rowNumber: 10
|
rowNumber: 10
|
||||||
|
@ -101,10 +104,14 @@ export const defaultListSettings: AppListViewSettings = {
|
||||||
},
|
},
|
||||||
[ListViews.TRANSLATION_ATTRIBUTE_VALUE_LIST]: {
|
[ListViews.TRANSLATION_ATTRIBUTE_VALUE_LIST]: {
|
||||||
rowNumber: 10
|
rowNumber: 10
|
||||||
|
},
|
||||||
|
[ListViews.GIFT_CARD_LIST]: {
|
||||||
|
rowNumber: PAGINATE_BY
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const APP_VERSION = packageInfo.version;
|
export const APP_VERSION = packageInfo.version;
|
||||||
|
|
||||||
export const DEMO_MODE = process.env.DEMO_MODE === "true";
|
export const DEMO_MODE = process.env.DEMO_MODE === "true";
|
||||||
export const GTM_ID = process.env.GTM_ID;
|
export const GTM_ID = process.env.GTM_ID;
|
||||||
|
|
||||||
|
|
|
@ -13,4 +13,4 @@ Object {
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Filtering URL params should not be empty if active filters are present 2`] = `"channel=default-channel&startedFrom=2019-12-09&startedTo=2019-12-38&status%5B0%5D=ACTIVE&status%5B1%5D=EXPIRED&type=FIXED"`;
|
exports[`Filtering URL params should not be empty if active filters are present 2`] = `"channel=default-channel&startedFrom=2019-12-09&startedTo=2019-12-38&status%5B%5D=ACTIVE&status%5B%5D=EXPIRED&type=FIXED"`;
|
||||||
|
|
|
@ -18,4 +18,4 @@ Object {
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Filtering URL params should not be empty if active filters are present 2`] = `"channel=default-channel&startedFrom=2019-12-09&startedTo=2019-12-38×UsedFrom=1×UsedTo=6&status%5B0%5D=ACTIVE&status%5B1%5D=EXPIRED&type%5B0%5D=FIXED&type%5B1%5D=SHIPPING"`;
|
exports[`Filtering URL params should not be empty if active filters are present 2`] = `"channel=default-channel&startedFrom=2019-12-09&startedTo=2019-12-38×UsedFrom=1×UsedTo=6&status%5B%5D=ACTIVE&status%5B%5D=EXPIRED&type%5B%5D=FIXED&type%5B%5D=SHIPPING"`;
|
||||||
|
|
|
@ -16,3 +16,11 @@ export const fragmentUser = gql`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const fragmentUserBase = gql`
|
||||||
|
fragment UserBase on User {
|
||||||
|
id
|
||||||
|
firstName
|
||||||
|
lastName
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
|
@ -215,3 +215,10 @@ export const uploadErrorFragment = gql`
|
||||||
field
|
field
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const giftCardErrorFragment = gql`
|
||||||
|
fragment GiftCardError on GiftCardError {
|
||||||
|
code
|
||||||
|
field
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
8
src/fragments/timePeriod.ts
Normal file
8
src/fragments/timePeriod.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
|
export const fragmentTimePeriod = gql`
|
||||||
|
fragment TimePeriod on TimePeriod {
|
||||||
|
amount
|
||||||
|
type
|
||||||
|
}
|
||||||
|
`;
|
16
src/fragments/types/GiftCardError.ts
Normal file
16
src/fragments/types/GiftCardError.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { GiftCardErrorCode } from "./../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL fragment: GiftCardError
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface GiftCardError {
|
||||||
|
__typename: "GiftCardError";
|
||||||
|
code: GiftCardErrorCode;
|
||||||
|
field: string | null;
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ export interface MetadataFragment_privateMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MetadataFragment {
|
export interface MetadataFragment {
|
||||||
__typename: "App" | "Warehouse" | "ShippingZone" | "ShippingMethod" | "Product" | "ProductType" | "Attribute" | "Category" | "ProductVariant" | "DigitalContent" | "Collection" | "Page" | "PageType" | "Sale" | "Voucher" | "MenuItem" | "Menu" | "User" | "Checkout" | "Order" | "Fulfillment" | "Invoice";
|
__typename: "App" | "Warehouse" | "ShippingZone" | "ShippingMethod" | "Product" | "ProductType" | "Attribute" | "Category" | "ProductVariant" | "DigitalContent" | "Collection" | "Page" | "PageType" | "Sale" | "Voucher" | "MenuItem" | "Menu" | "User" | "Checkout" | "GiftCard" | "Order" | "Fulfillment" | "Invoice";
|
||||||
metadata: (MetadataFragment_metadata | null)[];
|
metadata: (MetadataFragment_metadata | null)[];
|
||||||
privateMetadata: (MetadataFragment_privateMetadata | null)[];
|
privateMetadata: (MetadataFragment_privateMetadata | null)[];
|
||||||
}
|
}
|
||||||
|
|
16
src/fragments/types/TimePeriod.ts
Normal file
16
src/fragments/types/TimePeriod.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { TimePeriodTypeEnum } from "./../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL fragment: TimePeriod
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface TimePeriod {
|
||||||
|
__typename: "TimePeriod";
|
||||||
|
amount: number;
|
||||||
|
type: TimePeriodTypeEnum;
|
||||||
|
}
|
15
src/fragments/types/UserBase.ts
Normal file
15
src/fragments/types/UserBase.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL fragment: UserBase
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface UserBase {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
114
src/giftCards/GiftCardCreateDialog/GiftCardCreateDialog.tsx
Normal file
114
src/giftCards/GiftCardCreateDialog/GiftCardCreateDialog.tsx
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
import { Dialog, DialogTitle } from "@material-ui/core";
|
||||||
|
import { IMessage } from "@saleor/components/messages";
|
||||||
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import { GiftCardCreateInput } from "@saleor/types/globalTypes";
|
||||||
|
import commonErrorMessages from "@saleor/utils/errors/common";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import GiftCardCreateDialogCodeContent from "./GiftCardCreateDialogCodeContent";
|
||||||
|
import GiftCardCreateDialogForm, {
|
||||||
|
GiftCardCreateFormData
|
||||||
|
} from "./GiftCardCreateDialogForm";
|
||||||
|
import { giftCardCreateDialogMessages as messages } from "./messages";
|
||||||
|
import { useGiftCardCreateMutation } from "./mutations";
|
||||||
|
import { GiftCardCreate } from "./types/GiftCardCreate";
|
||||||
|
import { getGiftCardExpirySettingsInputData } from "./utils";
|
||||||
|
|
||||||
|
interface GiftCardCreateDialogProps {
|
||||||
|
onClose: () => void;
|
||||||
|
open: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GiftCardCreateDialog: React.FC<GiftCardCreateDialogProps> = ({
|
||||||
|
onClose,
|
||||||
|
open
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const notify = useNotifier();
|
||||||
|
|
||||||
|
const [cardCode, setCardCode] = useState(null);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!errors?.length) {
|
||||||
|
setCardCode(data?.giftCardCreate?.giftCard?.code);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getParsedSubmitInputData = (
|
||||||
|
formData: GiftCardCreateFormData
|
||||||
|
): GiftCardCreateInput => {
|
||||||
|
const {
|
||||||
|
balanceAmount,
|
||||||
|
balanceCurrency,
|
||||||
|
note,
|
||||||
|
tag,
|
||||||
|
selectedCustomer
|
||||||
|
} = formData;
|
||||||
|
|
||||||
|
return {
|
||||||
|
note: note || null,
|
||||||
|
tag: tag || null,
|
||||||
|
userEmail: selectedCustomer.email || null,
|
||||||
|
balance: {
|
||||||
|
amount: balanceAmount,
|
||||||
|
currency: balanceCurrency
|
||||||
|
},
|
||||||
|
expirySettings: getGiftCardExpirySettingsInputData(formData)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const [createGiftCard, createGiftCardOpts] = useGiftCardCreateMutation({
|
||||||
|
onCompleted
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSubmit = (data: GiftCardCreateFormData) => {
|
||||||
|
createGiftCard({
|
||||||
|
variables: {
|
||||||
|
input: getParsedSubmitInputData(data)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
onClose();
|
||||||
|
// 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);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} maxWidth="sm">
|
||||||
|
<DialogTitle>{intl.formatMessage(messages.title)}</DialogTitle>
|
||||||
|
{cardCode ? (
|
||||||
|
<GiftCardCreateDialogCodeContent
|
||||||
|
cardCode={cardCode}
|
||||||
|
onClose={handleClose}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<GiftCardCreateDialogForm
|
||||||
|
opts={createGiftCardOpts}
|
||||||
|
onClose={handleClose}
|
||||||
|
apiErrors={createGiftCardOpts?.data?.giftCardCreate?.errors}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardCreateDialog;
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { Button, DialogContent, Typography } from "@material-ui/core";
|
||||||
|
import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer";
|
||||||
|
import VerticalSpacer from "@saleor/apps/components/VerticalSpacer";
|
||||||
|
import useClipboard from "@saleor/hooks/useClipboard";
|
||||||
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import { buttonMessages } from "@saleor/intl";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { giftCardCreateDialogMessages as messages } from "./messages";
|
||||||
|
import { useGiftCardCreateDialogCodeContentStyles as useStyles } from "./styles";
|
||||||
|
|
||||||
|
interface GiftCardCreateDialogCodeContentProps {
|
||||||
|
cardCode: string;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GiftCardCreateDialogCodeContent: React.FC<GiftCardCreateDialogCodeContentProps> = ({
|
||||||
|
cardCode,
|
||||||
|
onClose
|
||||||
|
}) => {
|
||||||
|
const classes = useStyles({});
|
||||||
|
const intl = useIntl();
|
||||||
|
const notify = useNotifier();
|
||||||
|
const [, copy] = useClipboard();
|
||||||
|
|
||||||
|
const onCopyCode = () => {
|
||||||
|
copy(cardCode);
|
||||||
|
notify({
|
||||||
|
status: "success",
|
||||||
|
text: intl.formatMessage(messages.copiedToClipboardTitle)
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DialogContent>
|
||||||
|
<Typography>
|
||||||
|
{intl.formatMessage(messages.createdGiftCardLabel)}
|
||||||
|
</Typography>
|
||||||
|
<VerticalSpacer />
|
||||||
|
<Typography variant="h6" color="textSecondary">
|
||||||
|
{cardCode}
|
||||||
|
</Typography>
|
||||||
|
<VerticalSpacer spacing={2} />
|
||||||
|
<div className={classes.buttonsContainer}>
|
||||||
|
<Button onClick={onCopyCode}>
|
||||||
|
{intl.formatMessage(messages.copyCodeLabel)}
|
||||||
|
</Button>
|
||||||
|
<HorizontalSpacer spacing={2} />
|
||||||
|
<Button color="primary" variant="contained" onClick={onClose}>
|
||||||
|
{intl.formatMessage(buttonMessages.ok)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardCreateDialogCodeContent;
|
172
src/giftCards/GiftCardCreateDialog/GiftCardCreateDialogForm.tsx
Normal file
172
src/giftCards/GiftCardCreateDialog/GiftCardCreateDialogForm.tsx
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
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 TextWithSelectField from "@saleor/components/TextWithSelectField";
|
||||||
|
import { GiftCardError } from "@saleor/fragments/types/GiftCardError";
|
||||||
|
import GiftCardExpirySelect from "@saleor/giftCards/components/GiftCardExpirySelect";
|
||||||
|
import GiftCardTagInput from "@saleor/giftCards/components/GiftCardTagInput";
|
||||||
|
import useForm from "@saleor/hooks/useForm";
|
||||||
|
import useShop from "@saleor/hooks/useShop";
|
||||||
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
||||||
|
import Label from "@saleor/orders/components/OrderHistory/Label";
|
||||||
|
import {
|
||||||
|
GiftCardExpiryTypeEnum,
|
||||||
|
TimePeriodTypeEnum
|
||||||
|
} from "@saleor/types/globalTypes";
|
||||||
|
import { getFormErrors } from "@saleor/utils/errors";
|
||||||
|
import { mapSingleValueNodeToChoice } from "@saleor/utils/maps";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { getGiftCardErrorMessage } from "../GiftCardUpdate/messages";
|
||||||
|
import GiftCardCustomerSelectField from "./GiftCardCustomerSelectField";
|
||||||
|
import { giftCardCreateDialogMessages as messages } from "./messages";
|
||||||
|
import { useGiftCardCreateDialogFormStyles as useStyles } from "./styles";
|
||||||
|
import { GiftCardCommonFormData, GiftCardCreateFormCustomer } from "./types";
|
||||||
|
|
||||||
|
export interface GiftCardCreateFormData extends GiftCardCommonFormData {
|
||||||
|
note: string;
|
||||||
|
selectedCustomer?: GiftCardCreateFormCustomer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialCustomer = { email: "", name: "" };
|
||||||
|
|
||||||
|
export const initialData: GiftCardCreateFormData = {
|
||||||
|
tag: "",
|
||||||
|
balanceAmount: 1,
|
||||||
|
balanceCurrency: null,
|
||||||
|
note: "",
|
||||||
|
expiryDate: "",
|
||||||
|
expiryType: GiftCardExpiryTypeEnum.EXPIRY_PERIOD,
|
||||||
|
expiryPeriodType: TimePeriodTypeEnum.YEAR,
|
||||||
|
expiryPeriodAmount: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GiftCardCreateDialogFormProps {
|
||||||
|
opts: { status: ConfirmButtonTransitionState };
|
||||||
|
apiErrors: GiftCardError[];
|
||||||
|
onSubmit: (data: GiftCardCreateFormData) => void;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GiftCardCreateDialogForm: React.FC<GiftCardCreateDialogFormProps> = ({
|
||||||
|
onSubmit,
|
||||||
|
opts,
|
||||||
|
onClose,
|
||||||
|
apiErrors
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const classes = useStyles({});
|
||||||
|
const shop = useShop();
|
||||||
|
|
||||||
|
// TEMP
|
||||||
|
const initialCurrency = shop?.channelCurrencies?.[0];
|
||||||
|
|
||||||
|
const [selectedCustomer, setSelectedCustomer] = useState<
|
||||||
|
GiftCardCreateFormCustomer
|
||||||
|
>(initialCustomer);
|
||||||
|
|
||||||
|
const handleSubmit = (data: GiftCardCreateFormData) =>
|
||||||
|
onSubmit({ ...data, selectedCustomer });
|
||||||
|
|
||||||
|
const { submit, change, data } = useForm(
|
||||||
|
{ ...initialData, balanceCurrency: initialCurrency },
|
||||||
|
handleSubmit
|
||||||
|
);
|
||||||
|
|
||||||
|
const formErrors = getFormErrors(
|
||||||
|
[
|
||||||
|
"tag",
|
||||||
|
"expiryDate",
|
||||||
|
"expiryPeriod",
|
||||||
|
"customer",
|
||||||
|
"currency",
|
||||||
|
"amount",
|
||||||
|
"balance"
|
||||||
|
],
|
||||||
|
apiErrors
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
tag,
|
||||||
|
expiryPeriodAmount,
|
||||||
|
expiryPeriodType,
|
||||||
|
expiryType,
|
||||||
|
balanceAmount,
|
||||||
|
balanceCurrency
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DialogContent>
|
||||||
|
<TextWithSelectField
|
||||||
|
isError={!!formErrors?.balance}
|
||||||
|
helperText={getGiftCardErrorMessage(formErrors?.balance, intl)}
|
||||||
|
change={change}
|
||||||
|
choices={mapSingleValueNodeToChoice(shop?.channelCurrencies)}
|
||||||
|
containerClassName={classes.balanceContainer}
|
||||||
|
textFieldProps={{
|
||||||
|
type: "number",
|
||||||
|
label: intl.formatMessage(messages.amountLabel),
|
||||||
|
name: "balanceAmount",
|
||||||
|
value: balanceAmount,
|
||||||
|
minValue: 0
|
||||||
|
}}
|
||||||
|
selectFieldProps={{
|
||||||
|
name: "balanceCurrency",
|
||||||
|
value: balanceCurrency || initialCurrency,
|
||||||
|
className: classes.currencySelectField
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<GiftCardTagInput
|
||||||
|
error={formErrors?.tag}
|
||||||
|
name="tag"
|
||||||
|
value={tag}
|
||||||
|
change={change}
|
||||||
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<Divider />
|
||||||
|
<CardSpacer />
|
||||||
|
<GiftCardCustomerSelectField
|
||||||
|
selectedCustomer={selectedCustomer}
|
||||||
|
setSelectedCustomer={setSelectedCustomer}
|
||||||
|
/>
|
||||||
|
<VerticalSpacer />
|
||||||
|
<Label text={intl.formatMessage(messages.customerSubtitle)} />
|
||||||
|
<CardSpacer />
|
||||||
|
<Divider />
|
||||||
|
<CardSpacer />
|
||||||
|
<GiftCardExpirySelect
|
||||||
|
errors={formErrors}
|
||||||
|
change={change}
|
||||||
|
expiryType={expiryType}
|
||||||
|
expiryPeriodAmount={expiryPeriodAmount}
|
||||||
|
expiryPeriodType={expiryPeriodType}
|
||||||
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<TextField
|
||||||
|
name="note"
|
||||||
|
onChange={change}
|
||||||
|
multiline
|
||||||
|
className={classes.noteField}
|
||||||
|
label={`${intl.formatMessage(
|
||||||
|
messages.noteLabel
|
||||||
|
)} *${intl.formatMessage(commonMessages.optionalField)}`}
|
||||||
|
/>
|
||||||
|
<VerticalSpacer />
|
||||||
|
<Label text={intl.formatMessage(messages.noteSubtitle)} />
|
||||||
|
</DialogContent>
|
||||||
|
<DialogButtons
|
||||||
|
onConfirm={submit}
|
||||||
|
confirmButtonLabel={intl.formatMessage(messages.issueButtonLabel)}
|
||||||
|
confirmButtonState={opts?.status}
|
||||||
|
onClose={onClose}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardCreateDialogForm;
|
|
@ -0,0 +1,61 @@
|
||||||
|
import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
|
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
|
||||||
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { getFullName } from "@saleor/misc";
|
||||||
|
import useCustomerSearch from "@saleor/searches/useCustomerSearch";
|
||||||
|
import { mapEdgesToItems } from "@saleor/utils/maps";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { giftCardCreateDialogMessages as messages } from "./messages";
|
||||||
|
import { GiftCardCreateFormCustomer } from "./types";
|
||||||
|
|
||||||
|
export interface GiftCardCustomerSelectFieldProps {
|
||||||
|
selectedCustomer: GiftCardCreateFormCustomer;
|
||||||
|
setSelectedCustomer: (customer: GiftCardCreateFormCustomer) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GiftCardCustomerSelectField: React.FC<GiftCardCustomerSelectFieldProps> = ({
|
||||||
|
selectedCustomer,
|
||||||
|
setSelectedCustomer
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const { loadMore, search, result } = useCustomerSearch({
|
||||||
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
|
});
|
||||||
|
|
||||||
|
const customers = mapEdgesToItems(result?.data?.search);
|
||||||
|
|
||||||
|
const choices = customers?.map(({ email, firstName, lastName }) => ({
|
||||||
|
value: email,
|
||||||
|
label: getFullName({ firstName, lastName })
|
||||||
|
}));
|
||||||
|
|
||||||
|
const handleSelect = (event: React.ChangeEvent<any>) => {
|
||||||
|
const value = event.target.value;
|
||||||
|
const label = choices?.find(category => category.value === value)?.label;
|
||||||
|
|
||||||
|
setSelectedCustomer({ email: value, name: label });
|
||||||
|
};
|
||||||
|
|
||||||
|
const label = `${intl.formatMessage(
|
||||||
|
messages.customerLabel
|
||||||
|
)} *${intl.formatMessage(commonMessages.optionalField)}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SingleAutocompleteSelectField
|
||||||
|
name="customer"
|
||||||
|
label={label}
|
||||||
|
data-test-id="customer-field"
|
||||||
|
displayValue={selectedCustomer.name}
|
||||||
|
value={selectedCustomer.email}
|
||||||
|
choices={choices || []}
|
||||||
|
fetchChoices={search}
|
||||||
|
onChange={handleSelect}
|
||||||
|
onFetchMore={loadMore}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardCustomerSelectField;
|
2
src/giftCards/GiftCardCreateDialog/index.tsx
Normal file
2
src/giftCards/GiftCardCreateDialog/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardCreateDialog";
|
||||||
|
export { default } from "./GiftCardCreateDialog";
|
50
src/giftCards/GiftCardCreateDialog/messages.ts
Normal file
50
src/giftCards/GiftCardCreateDialog/messages.ts
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const giftCardCreateDialogMessages = defineMessages({
|
||||||
|
title: {
|
||||||
|
defaultMessage: "Issue gift card",
|
||||||
|
description: "GiftCardCreateDialog title"
|
||||||
|
},
|
||||||
|
amountLabel: {
|
||||||
|
defaultMessage: "Enter amount",
|
||||||
|
description: "GiftCardCreateDialog amount label"
|
||||||
|
},
|
||||||
|
issueButtonLabel: {
|
||||||
|
defaultMessage: "Issue",
|
||||||
|
description: "GiftCardCreateDialog issue button label"
|
||||||
|
},
|
||||||
|
customerLabel: {
|
||||||
|
defaultMessage: "Customer",
|
||||||
|
description: "GiftCardCreateDialog customer label"
|
||||||
|
},
|
||||||
|
customerSubtitle: {
|
||||||
|
defaultMessage:
|
||||||
|
"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.",
|
||||||
|
description: "GiftCardCreateDialog customer subtitle"
|
||||||
|
},
|
||||||
|
noteLabel: {
|
||||||
|
defaultMessage: "Note",
|
||||||
|
description: "GiftCardCreateDialog note 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"
|
||||||
|
},
|
||||||
|
createdGiftCardLabel: {
|
||||||
|
defaultMessage: "This is the code of a created gift card:",
|
||||||
|
description: "GiftCardCreateDialog created gift card label"
|
||||||
|
},
|
||||||
|
copyCodeLabel: {
|
||||||
|
defaultMessage: "Copy code",
|
||||||
|
description: "GiftCardCreateDialog copy code label"
|
||||||
|
},
|
||||||
|
copiedToClipboardTitle: {
|
||||||
|
defaultMessage: "Copied to clipboard",
|
||||||
|
description: "GiftCardCreateDialog copied to clipboard title"
|
||||||
|
},
|
||||||
|
createdSuccessAlertTitle: {
|
||||||
|
defaultMessage: "Successfully created gift card",
|
||||||
|
description: "GiftCardCreateDialog createdSuccessAlertTitle"
|
||||||
|
}
|
||||||
|
});
|
26
src/giftCards/GiftCardCreateDialog/mutations.ts
Normal file
26
src/giftCards/GiftCardCreateDialog/mutations.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import makeMutation from "@saleor/hooks/makeMutation";
|
||||||
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
|
import {
|
||||||
|
GiftCardCreate,
|
||||||
|
GiftCardCreateVariables
|
||||||
|
} from "./types/GiftCardCreate";
|
||||||
|
|
||||||
|
const giftCardCreate = gql`
|
||||||
|
mutation GiftCardCreate($input: GiftCardCreateInput!) {
|
||||||
|
giftCardCreate(input: $input) {
|
||||||
|
giftCard {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
errors {
|
||||||
|
code
|
||||||
|
field
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const useGiftCardCreateMutation = makeMutation<
|
||||||
|
GiftCardCreate,
|
||||||
|
GiftCardCreateVariables
|
||||||
|
>(giftCardCreate);
|
25
src/giftCards/GiftCardCreateDialog/styles.ts
Normal file
25
src/giftCards/GiftCardCreateDialog/styles.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
|
export const useGiftCardCreateDialogCodeContentStyles = makeStyles(
|
||||||
|
() => ({
|
||||||
|
buttonsContainer: {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
minWidth: 450
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "GiftCardCreateDialogCodeContent" }
|
||||||
|
);
|
||||||
|
|
||||||
|
export const useGiftCardCreateDialogFormStyles = makeStyles(
|
||||||
|
() => ({
|
||||||
|
noteField: {
|
||||||
|
width: "100%"
|
||||||
|
},
|
||||||
|
currencySelectField: {
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
balanceContainer: { width: "100%" }
|
||||||
|
}),
|
||||||
|
{ name: "GiftCardCreateDialogForm" }
|
||||||
|
);
|
32
src/giftCards/GiftCardCreateDialog/types.ts
Normal file
32
src/giftCards/GiftCardCreateDialog/types.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { GiftCardError } from "@saleor/fragments/types/GiftCardError";
|
||||||
|
import { FormChange } from "@saleor/hooks/useForm";
|
||||||
|
import {
|
||||||
|
GiftCardExpiryTypeEnum,
|
||||||
|
TimePeriodTypeEnum
|
||||||
|
} from "@saleor/types/globalTypes";
|
||||||
|
|
||||||
|
export interface GiftCardCreateFormCustomer {
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardCommonFormData {
|
||||||
|
tag: string;
|
||||||
|
balanceAmount: number;
|
||||||
|
balanceCurrency: string;
|
||||||
|
expiryDate: string;
|
||||||
|
expiryType: GiftCardExpiryTypeEnum;
|
||||||
|
expiryPeriodType: TimePeriodTypeEnum;
|
||||||
|
expiryPeriodAmount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GiftCardCreateFormErrors = Record<
|
||||||
|
"tag" | "expiryDate" | "expiryPeriod" | "customer" | "currency" | "amount",
|
||||||
|
GiftCardError
|
||||||
|
>;
|
||||||
|
|
||||||
|
export interface GiftCardCreateFormCommonProps {
|
||||||
|
change: FormChange;
|
||||||
|
errors: GiftCardCreateFormErrors;
|
||||||
|
data: GiftCardCommonFormData;
|
||||||
|
}
|
35
src/giftCards/GiftCardCreateDialog/types/GiftCardCreate.ts
Normal file
35
src/giftCards/GiftCardCreateDialog/types/GiftCardCreate.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { GiftCardCreateInput, GiftCardErrorCode } from "./../../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL mutation operation: GiftCardCreate
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface GiftCardCreate_giftCardCreate_giftCard {
|
||||||
|
__typename: "GiftCard";
|
||||||
|
code: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardCreate_giftCardCreate_errors {
|
||||||
|
__typename: "GiftCardError";
|
||||||
|
code: GiftCardErrorCode;
|
||||||
|
field: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardCreate_giftCardCreate {
|
||||||
|
__typename: "GiftCardCreate";
|
||||||
|
giftCard: GiftCardCreate_giftCardCreate_giftCard | null;
|
||||||
|
errors: GiftCardCreate_giftCardCreate_errors[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardCreate {
|
||||||
|
giftCardCreate: GiftCardCreate_giftCardCreate | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardCreateVariables {
|
||||||
|
input: GiftCardCreateInput;
|
||||||
|
}
|
41
src/giftCards/GiftCardCreateDialog/utils.ts
Normal file
41
src/giftCards/GiftCardCreateDialog/utils.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import {
|
||||||
|
GiftCardExpirySettingsInput,
|
||||||
|
GiftCardExpiryTypeEnum
|
||||||
|
} from "@saleor/types/globalTypes";
|
||||||
|
|
||||||
|
import { GiftCardCommonFormData } from "./types";
|
||||||
|
|
||||||
|
export const getGiftCardExpirySettingsInputData = ({
|
||||||
|
expiryType,
|
||||||
|
expiryDate,
|
||||||
|
expiryPeriodAmount,
|
||||||
|
expiryPeriodType
|
||||||
|
}: Pick<
|
||||||
|
GiftCardCommonFormData,
|
||||||
|
"expiryDate" | "expiryPeriodAmount" | "expiryPeriodType" | "expiryType"
|
||||||
|
>): GiftCardExpirySettingsInput => {
|
||||||
|
switch (expiryType) {
|
||||||
|
case GiftCardExpiryTypeEnum.EXPIRY_DATE: {
|
||||||
|
return {
|
||||||
|
expiryType,
|
||||||
|
expiryDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case GiftCardExpiryTypeEnum.EXPIRY_PERIOD: {
|
||||||
|
return {
|
||||||
|
expiryType,
|
||||||
|
expiryPeriod: {
|
||||||
|
amount: expiryPeriodAmount,
|
||||||
|
type: expiryPeriodType
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
return {
|
||||||
|
expiryType
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
24
src/giftCards/GiftCardUpdate/GiftCardUpdate.tsx
Normal file
24
src/giftCards/GiftCardUpdate/GiftCardUpdate.tsx
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import GiftCardUpdatePage from "./GiftCardUpdatePage";
|
||||||
|
import GiftCardDetailsProvider from "./providers/GiftCardDetailsProvider";
|
||||||
|
import GiftCardUpdateDialogsProvider from "./providers/GiftCardUpdateDialogsProvider";
|
||||||
|
import GiftCardUpdateFormProvider from "./providers/GiftCardUpdateFormProvider/GiftCardUpdateFormProvider";
|
||||||
|
import { GiftCardUpdatePageUrlQueryParams } from "./types";
|
||||||
|
|
||||||
|
interface GiftCardUpdateProps {
|
||||||
|
params: GiftCardUpdatePageUrlQueryParams;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GiftCardUpdate: React.FC<GiftCardUpdateProps> = ({ id, params }) => (
|
||||||
|
<GiftCardDetailsProvider id={id}>
|
||||||
|
<GiftCardUpdateFormProvider>
|
||||||
|
<GiftCardUpdateDialogsProvider id={id} params={params}>
|
||||||
|
<GiftCardUpdatePage />
|
||||||
|
</GiftCardUpdateDialogsProvider>
|
||||||
|
</GiftCardUpdateFormProvider>
|
||||||
|
</GiftCardDetailsProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default GiftCardUpdate;
|
|
@ -0,0 +1,137 @@
|
||||||
|
import { TextField, Typography } from "@material-ui/core";
|
||||||
|
import ActionDialog from "@saleor/components/ActionDialog";
|
||||||
|
import CardSpacer from "@saleor/components/CardSpacer";
|
||||||
|
import Form from "@saleor/components/Form";
|
||||||
|
import { IMessage } from "@saleor/components/messages";
|
||||||
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import { getFormErrors } from "@saleor/utils/errors";
|
||||||
|
import commonErrorMessages from "@saleor/utils/errors/common";
|
||||||
|
import { DialogActionHandlers } from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { giftCardsListTableMessages as tableMessages } from "../../GiftCardsList/messages";
|
||||||
|
import { getGiftCardErrorMessage } from "../messages";
|
||||||
|
import { useGiftCardUpdateMutation } from "../mutations";
|
||||||
|
import useGiftCardDetails from "../providers/GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||||
|
import { GiftCardUpdate } from "../types/GiftCardUpdate";
|
||||||
|
import { giftCardUpdateBalanceDialogMessages as messages } from "./messages";
|
||||||
|
import { useUpdateBalanceDialogStyles as useStyles } from "./styles";
|
||||||
|
|
||||||
|
export interface GiftCardBalanceUpdateFormData {
|
||||||
|
balanceAmount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GiftCardUpdateBalanceDialog: React.FC<DialogActionHandlers> = ({
|
||||||
|
open,
|
||||||
|
onClose
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const classes = useStyles({});
|
||||||
|
const notify = useNotifier();
|
||||||
|
|
||||||
|
const {
|
||||||
|
giftCard: {
|
||||||
|
id,
|
||||||
|
currentBalance: { amount, currency }
|
||||||
|
}
|
||||||
|
} = useGiftCardDetails();
|
||||||
|
|
||||||
|
const initialFormData: GiftCardBalanceUpdateFormData = {
|
||||||
|
balanceAmount: amount
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCompleted = (data: GiftCardUpdate) => {
|
||||||
|
const errors = data?.giftCardUpdate?.errors;
|
||||||
|
|
||||||
|
const notifierData: IMessage = !!errors?.length
|
||||||
|
? {
|
||||||
|
status: "error",
|
||||||
|
text: intl.formatMessage(commonErrorMessages.unknownError)
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
status: "success",
|
||||||
|
text: intl.formatMessage(messages.updatedSuccessAlertTitle)
|
||||||
|
};
|
||||||
|
|
||||||
|
notify(notifierData);
|
||||||
|
|
||||||
|
if (!errors.length) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const [
|
||||||
|
updateGiftCardBalance,
|
||||||
|
updateGiftCardBalanceOpts
|
||||||
|
] = useGiftCardUpdateMutation({
|
||||||
|
onCompleted
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSubmit = async ({
|
||||||
|
balanceAmount
|
||||||
|
}: GiftCardBalanceUpdateFormData) => {
|
||||||
|
const result = await updateGiftCardBalance({
|
||||||
|
variables: {
|
||||||
|
id,
|
||||||
|
input: {
|
||||||
|
balanceAmount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result?.data?.giftCardUpdate?.errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { loading, status, data } = updateGiftCardBalanceOpts;
|
||||||
|
|
||||||
|
const formErrors = getFormErrors(
|
||||||
|
["initialBalanceAmount"],
|
||||||
|
data?.giftCardUpdate?.errors
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form initial={initialFormData} onSubmit={handleSubmit}>
|
||||||
|
{({ data, change, submit, hasChanged }) => (
|
||||||
|
<ActionDialog
|
||||||
|
maxWidth="sm"
|
||||||
|
open={open}
|
||||||
|
onConfirm={submit}
|
||||||
|
confirmButtonLabel={intl.formatMessage(messages.changeButtonLabel)}
|
||||||
|
onClose={onClose}
|
||||||
|
title={intl.formatMessage(messages.title)}
|
||||||
|
confirmButtonState={status}
|
||||||
|
disabled={loading || !hasChanged}
|
||||||
|
>
|
||||||
|
<Typography>{intl.formatMessage(messages.subtitle)}</Typography>
|
||||||
|
<CardSpacer />
|
||||||
|
<TextField
|
||||||
|
inputProps={{ min: 0 }}
|
||||||
|
error={!!formErrors?.initialBalanceAmount}
|
||||||
|
helperText={getGiftCardErrorMessage(
|
||||||
|
formErrors?.initialBalanceAmount,
|
||||||
|
intl
|
||||||
|
)}
|
||||||
|
name="balanceAmount"
|
||||||
|
value={data.balanceAmount}
|
||||||
|
onChange={change}
|
||||||
|
className={classes.inputContainer}
|
||||||
|
label={intl.formatMessage(
|
||||||
|
tableMessages.giftCardsTableColumnBalanceTitle
|
||||||
|
)}
|
||||||
|
type="number"
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: (
|
||||||
|
<div className={classes.currencyCodeContainer}>
|
||||||
|
<Typography variant="caption">{currency}</Typography>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ActionDialog>
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardUpdateBalanceDialog;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardUpdateBalanceDialog";
|
||||||
|
export { default } from "./GiftCardUpdateBalanceDialog";
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const giftCardUpdateBalanceDialogMessages = defineMessages({
|
||||||
|
title: {
|
||||||
|
defaultMessage: "Set balance",
|
||||||
|
description: "GiftCardUpdateDetailsCard set balance button 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"
|
||||||
|
},
|
||||||
|
updatedSuccessAlertTitle: {
|
||||||
|
defaultMessage: "Successfully updated card balance",
|
||||||
|
description: "GiftCardUpdateDetailsCard update success alert title"
|
||||||
|
},
|
||||||
|
changeButtonLabel: {
|
||||||
|
defaultMessage: "Change",
|
||||||
|
description:
|
||||||
|
"GiftCardUpdateDetailsCard set balance dialog change button label"
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
|
export const useUpdateBalanceDialogStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
inputContainer: {
|
||||||
|
width: "100%"
|
||||||
|
},
|
||||||
|
currencyCodeContainer: {
|
||||||
|
height: 35,
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
marginRight: theme.spacing(1)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "GiftCardUpdateBalanceDialog" }
|
||||||
|
);
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { Typography } from "@material-ui/core";
|
||||||
|
import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer";
|
||||||
|
import CardSpacer from "@saleor/components/CardSpacer";
|
||||||
|
import Money from "@saleor/components/Money";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import useGiftCardDetails from "../providers/GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||||
|
import { giftCardUpdateDetailsCardMessages as messages } from "./messages";
|
||||||
|
import { useGiftCardDetailsBalanceStyles as useStyles } from "./styles";
|
||||||
|
|
||||||
|
const GiftCardUpdateDetailsBalanceSection: React.FC = () => {
|
||||||
|
const classes = useStyles({});
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const {
|
||||||
|
giftCard: { currentBalance, initialBalance }
|
||||||
|
} = useGiftCardDetails();
|
||||||
|
|
||||||
|
const progressBarWidth = !!currentBalance.amount
|
||||||
|
? Math.floor((currentBalance.amount / initialBalance.amount) * 100)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className={classNames(classes.labelsContainer, classes.wideContainer)}
|
||||||
|
>
|
||||||
|
<Typography>{intl.formatMessage(messages.cardBalanceLabel)}</Typography>
|
||||||
|
<div className={classes.labelsContainer}>
|
||||||
|
<Money money={currentBalance} />
|
||||||
|
<HorizontalSpacer />
|
||||||
|
/
|
||||||
|
<HorizontalSpacer />
|
||||||
|
<Money money={initialBalance} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<CardSpacer />
|
||||||
|
<div className={classes.balanceBar}>
|
||||||
|
<div
|
||||||
|
style={{ width: `${progressBarWidth}%` }}
|
||||||
|
className={classes.balanceBarProgress}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardUpdateDetailsBalanceSection;
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { Button, Card, CardContent, Divider } from "@material-ui/core";
|
||||||
|
import CardSpacer from "@saleor/components/CardSpacer";
|
||||||
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
|
import GiftCardExpirySelect from "@saleor/giftCards/components/GiftCardExpirySelect";
|
||||||
|
import GiftCardTagInput from "@saleor/giftCards/components/GiftCardTagInput";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import useGiftCardDetails from "../providers/GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||||
|
import useGiftCardUpdateDialogs from "../providers/GiftCardUpdateDialogsProvider/hooks/useGiftCardUpdateDialogs";
|
||||||
|
import useGiftCardUpdateForm from "../providers/GiftCardUpdateFormProvider/hooks/useGiftCardUpdateForm";
|
||||||
|
import GiftCardUpdateDetailsBalanceSection from "./GiftCardUpdateDetailsBalanceSection";
|
||||||
|
import { giftCardUpdateDetailsCardMessages as messages } from "./messages";
|
||||||
|
|
||||||
|
const GiftCardUpdateDetailsCard: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const { loading } = useGiftCardDetails();
|
||||||
|
const { openSetBalanceDialog } = useGiftCardUpdateDialogs();
|
||||||
|
|
||||||
|
const {
|
||||||
|
change,
|
||||||
|
data: { expiryType, expiryPeriodAmount, expiryPeriodType, tag, expiryDate },
|
||||||
|
formErrors
|
||||||
|
} = useGiftCardUpdateForm();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardTitle
|
||||||
|
title={intl.formatMessage(messages.title)}
|
||||||
|
toolbar={
|
||||||
|
<Button
|
||||||
|
data-test-id="set-balance-button"
|
||||||
|
color="primary"
|
||||||
|
onClick={openSetBalanceDialog}
|
||||||
|
>
|
||||||
|
{intl.formatMessage(messages.setBalanceButtonLabel)}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<CardContent>
|
||||||
|
<Skeleton>
|
||||||
|
{!loading && (
|
||||||
|
<>
|
||||||
|
<GiftCardUpdateDetailsBalanceSection />
|
||||||
|
<CardSpacer />
|
||||||
|
<Divider />
|
||||||
|
<CardSpacer />
|
||||||
|
<GiftCardTagInput
|
||||||
|
error={formErrors?.tag}
|
||||||
|
name="tag"
|
||||||
|
withTopLabel
|
||||||
|
value={tag}
|
||||||
|
change={change}
|
||||||
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<GiftCardExpirySelect
|
||||||
|
expiryDate={expiryDate}
|
||||||
|
errors={formErrors}
|
||||||
|
change={change}
|
||||||
|
expiryType={expiryType}
|
||||||
|
expiryPeriodAmount={expiryPeriodAmount}
|
||||||
|
expiryPeriodType={expiryPeriodType}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Skeleton>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardUpdateDetailsCard;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardUpdateDetailsCard";
|
||||||
|
export { default } from "./GiftCardUpdateDetailsCard";
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const giftCardUpdateDetailsCardMessages = defineMessages({
|
||||||
|
title: {
|
||||||
|
defaultMessage: "Details",
|
||||||
|
description: "GiftCardUpdateDetailsCard title"
|
||||||
|
},
|
||||||
|
setBalanceButtonLabel: {
|
||||||
|
defaultMessage: "set balance",
|
||||||
|
description: "GiftCardUpdateDetailsCard set balance button label"
|
||||||
|
},
|
||||||
|
cardBalanceLabel: {
|
||||||
|
defaultMessage: "Card Balance",
|
||||||
|
description: "GiftCardUpdateDetailsCard card balance label"
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
|
export const useGiftCardDetailsBalanceStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
labelsContainer: {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "baseline"
|
||||||
|
},
|
||||||
|
wideContainer: {
|
||||||
|
justifyContent: "space-between"
|
||||||
|
},
|
||||||
|
balanceBar: {
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
height: 36,
|
||||||
|
padding: "0 4px",
|
||||||
|
backgroundColor: theme.palette.background.default,
|
||||||
|
borderRadius: 18
|
||||||
|
},
|
||||||
|
balanceBarProgress: {
|
||||||
|
height: 28,
|
||||||
|
borderRadius: 14,
|
||||||
|
backgroundColor: theme.palette.primary.light
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "GiftCardUpdateDetailsBalanceSection" }
|
||||||
|
);
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Card, CardContent } from "@material-ui/core";
|
||||||
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import useGiftCardDetails from "../providers/GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||||
|
import GiftCardUpdateInfoCardContent from "./GiftCardUpdateInfoCardContent";
|
||||||
|
import { giftCardUpdateInfoCardMessages as messages } from "./messages";
|
||||||
|
|
||||||
|
const GiftCardUpdateInfoCard: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const { loading } = useGiftCardDetails();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardTitle title={intl.formatMessage(messages.title)} />
|
||||||
|
<CardContent>
|
||||||
|
<Skeleton>{!loading && <GiftCardUpdateInfoCardContent />}</Skeleton>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardUpdateInfoCard;
|
|
@ -0,0 +1,143 @@
|
||||||
|
import { Typography } from "@material-ui/core";
|
||||||
|
import { appUrl } from "@saleor/apps/urls";
|
||||||
|
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";
|
||||||
|
import { productUrl } from "@saleor/products/urls";
|
||||||
|
import { staffMemberDetailsUrl } from "@saleor/staff/urls";
|
||||||
|
import { GiftCardEventsEnum } from "@saleor/types/globalTypes";
|
||||||
|
import React from "react";
|
||||||
|
import { MessageDescriptor, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import useGiftCardDetails from "../providers/GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||||
|
import { giftCardUpdateInfoCardMessages as messages } from "./messages";
|
||||||
|
|
||||||
|
const PLACEHOLDER = "-";
|
||||||
|
|
||||||
|
const GiftCardUpdateInfoCardContent: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const localizeDate = useDateLocalize();
|
||||||
|
const navigate = useNavigator();
|
||||||
|
|
||||||
|
const { giftCard } = useGiftCardDetails();
|
||||||
|
|
||||||
|
const {
|
||||||
|
created,
|
||||||
|
createdByEmail,
|
||||||
|
createdBy,
|
||||||
|
usedByEmail,
|
||||||
|
usedBy,
|
||||||
|
app,
|
||||||
|
product,
|
||||||
|
events
|
||||||
|
} = giftCard;
|
||||||
|
|
||||||
|
const cardIssuedEvent = events.find(
|
||||||
|
({ type }) => type === GiftCardEventsEnum.ISSUED
|
||||||
|
);
|
||||||
|
|
||||||
|
const getBuyerFieldData = (): {
|
||||||
|
label: MessageDescriptor;
|
||||||
|
name: string;
|
||||||
|
url?: string;
|
||||||
|
} => {
|
||||||
|
// createdBy can be either customer or staff hence
|
||||||
|
// we check for issued event
|
||||||
|
if (cardIssuedEvent) {
|
||||||
|
const userName = getFullName(createdBy);
|
||||||
|
|
||||||
|
return {
|
||||||
|
label: messages.issuedByLabel,
|
||||||
|
name: userName || createdByEmail,
|
||||||
|
url: staffMemberDetailsUrl(createdBy.id)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createdByEmail) {
|
||||||
|
return {
|
||||||
|
label: messages.boughtByLabel,
|
||||||
|
name: createdByEmail
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app) {
|
||||||
|
return {
|
||||||
|
label: messages.issuedByAppLabel,
|
||||||
|
name: app.name,
|
||||||
|
url: appUrl(app.id)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
label: messages.boughtByLabel,
|
||||||
|
name: getFullName(createdBy),
|
||||||
|
url: customerUrl(createdBy?.id)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const orderData =
|
||||||
|
cardIssuedEvent && cardIssuedEvent.orderId
|
||||||
|
? getOrderNumberLinkObject({
|
||||||
|
id: cardIssuedEvent.orderId,
|
||||||
|
number: cardIssuedEvent.orderNumber
|
||||||
|
})
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const {
|
||||||
|
label: buyerLabelMessage,
|
||||||
|
name: buyerName,
|
||||||
|
url: buyerUrl
|
||||||
|
} = getBuyerFieldData();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Label text={intl.formatMessage(messages.creationLabel)} />
|
||||||
|
<Typography>{localizeDate(created, "DD MMMM YYYY")}</Typography>
|
||||||
|
<CardSpacer />
|
||||||
|
|
||||||
|
<Label text={intl.formatMessage(messages.orderNumberLabel)} />
|
||||||
|
{orderData ? (
|
||||||
|
<Link onClick={() => navigate(orderData.link)}>{orderData.text}</Link>
|
||||||
|
) : (
|
||||||
|
<Typography>{PLACEHOLDER}</Typography>
|
||||||
|
)}
|
||||||
|
<CardSpacer />
|
||||||
|
|
||||||
|
<Label text={intl.formatMessage(messages.productLabel)} />
|
||||||
|
{product ? (
|
||||||
|
<Link onClick={() => navigate(productUrl(product?.id))}>
|
||||||
|
{product?.name}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Typography>{PLACEHOLDER}</Typography>
|
||||||
|
)}
|
||||||
|
<CardSpacer />
|
||||||
|
|
||||||
|
<Label text={intl.formatMessage(buyerLabelMessage)} />
|
||||||
|
{buyerUrl ? (
|
||||||
|
<Link onClick={() => navigate(buyerUrl)}>{buyerName}</Link>
|
||||||
|
) : (
|
||||||
|
<Typography>{buyerName}</Typography>
|
||||||
|
)}
|
||||||
|
<CardSpacer />
|
||||||
|
|
||||||
|
<Label text={intl.formatMessage(messages.usedByLabel)} />
|
||||||
|
{usedBy ? (
|
||||||
|
<Link onClick={() => navigate(customerUrl(usedBy.id))}>
|
||||||
|
{getFullName(usedBy)}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Typography>
|
||||||
|
{getStringOrPlaceholder(usedByEmail, PLACEHOLDER)}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardUpdateInfoCardContent;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardUpdateInfoCard";
|
||||||
|
export { default } from "./GiftCardUpdateInfoCard";
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const giftCardUpdateInfoCardMessages = defineMessages({
|
||||||
|
title: {
|
||||||
|
defaultMessage: "Card information",
|
||||||
|
description: "GiftCardUpdateInfoCard title"
|
||||||
|
},
|
||||||
|
creationLabel: {
|
||||||
|
defaultMessage: "Creation",
|
||||||
|
description: "GiftCardUpdateInfoCard creation label"
|
||||||
|
},
|
||||||
|
orderNumberLabel: {
|
||||||
|
defaultMessage: "Order number",
|
||||||
|
description: "GiftCardUpdateInfoCard order number label"
|
||||||
|
},
|
||||||
|
productLabel: {
|
||||||
|
defaultMessage: "Product bought to get gift card",
|
||||||
|
description: "GiftCardUpdateInfoCard product label"
|
||||||
|
},
|
||||||
|
issuedByLabel: {
|
||||||
|
defaultMessage: "Issued by",
|
||||||
|
description: "GiftCardUpdateInfoCard issued by label"
|
||||||
|
},
|
||||||
|
issuedByAppLabel: {
|
||||||
|
defaultMessage: "Issued by app",
|
||||||
|
description: "GiftCardUpdateInfoCard issued by app label"
|
||||||
|
},
|
||||||
|
boughtByLabel: {
|
||||||
|
defaultMessage: "Bought by",
|
||||||
|
description: "GiftCardUpdateInfoCard bought by label"
|
||||||
|
},
|
||||||
|
usedByLabel: {
|
||||||
|
defaultMessage: "Used by",
|
||||||
|
description: "GiftCardUpdateInfoCard used by label"
|
||||||
|
}
|
||||||
|
});
|
52
src/giftCards/GiftCardUpdate/GiftCardUpdatePage.tsx
Normal file
52
src/giftCards/GiftCardUpdate/GiftCardUpdatePage.tsx
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import CardSpacer from "@saleor/components/CardSpacer";
|
||||||
|
import Container from "@saleor/components/Container";
|
||||||
|
import Grid from "@saleor/components/Grid";
|
||||||
|
import Metadata from "@saleor/components/Metadata";
|
||||||
|
import Savebar from "@saleor/components/Savebar";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import GiftCardUpdateDetailsCard from "./GiftCardUpdateDetailsCard";
|
||||||
|
import GiftCardUpdateInfoCard from "./GiftCardUpdateInfoCard";
|
||||||
|
import GiftCardUpdatePageHeader from "./GiftCardUpdatePageHeader";
|
||||||
|
import useGiftCardUpdateDialogs from "./providers/GiftCardUpdateDialogsProvider/hooks/useGiftCardUpdateDialogs";
|
||||||
|
import useGiftCardUpdate from "./providers/GiftCardUpdateFormProvider/hooks/useGiftCardUpdate";
|
||||||
|
import useGiftCardUpdateForm from "./providers/GiftCardUpdateFormProvider/hooks/useGiftCardUpdateForm";
|
||||||
|
|
||||||
|
const GiftCardUpdatePage: React.FC = () => {
|
||||||
|
const { navigateBack } = useGiftCardUpdateDialogs();
|
||||||
|
|
||||||
|
const {
|
||||||
|
hasChanged,
|
||||||
|
submit,
|
||||||
|
data,
|
||||||
|
handlers: { changeMetadata }
|
||||||
|
} = useGiftCardUpdateForm();
|
||||||
|
|
||||||
|
const {
|
||||||
|
opts: { loading: loadingUpdate, status }
|
||||||
|
} = useGiftCardUpdate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<GiftCardUpdatePageHeader />
|
||||||
|
<Grid>
|
||||||
|
<div>
|
||||||
|
<GiftCardUpdateDetailsCard />
|
||||||
|
<CardSpacer />
|
||||||
|
<Metadata data={data} onChange={changeMetadata} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<GiftCardUpdateInfoCard />
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
<Savebar
|
||||||
|
state={status}
|
||||||
|
disabled={loadingUpdate || !hasChanged}
|
||||||
|
onCancel={navigateBack}
|
||||||
|
onSubmit={submit}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardUpdatePage;
|
|
@ -0,0 +1,105 @@
|
||||||
|
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 classNames from "classnames";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import useGiftCardDetails from "../providers/GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||||
|
import { giftCardEnableDisableSectionMessages as messages } from "./messages";
|
||||||
|
import {
|
||||||
|
useGiftCardActivateMutation,
|
||||||
|
useGiftCardDeactivateMutation
|
||||||
|
} from "./mutations";
|
||||||
|
import { useGiftCardEnableDisableSectionStyles as useStyles } from "./styles";
|
||||||
|
import { GiftCardActivate } from "./types/GiftCardActivate";
|
||||||
|
import { GiftCardDeactivate } from "./types/GiftCardDeactivate";
|
||||||
|
|
||||||
|
const GiftCardEnableDisableSection: React.FC = () => {
|
||||||
|
const classes = useStyles({});
|
||||||
|
const notify = useNotifier();
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const {
|
||||||
|
giftCard: { id, isActive }
|
||||||
|
} = useGiftCardDetails();
|
||||||
|
|
||||||
|
const [showButtonGreen, setShowButtonGreen] = useState(!isActive);
|
||||||
|
|
||||||
|
useEffect(() => setShowButtonGreen(!isActive), [isActive]);
|
||||||
|
|
||||||
|
const onActivateCompleted = (data: GiftCardActivate) => {
|
||||||
|
const errors = data?.giftCardActivate?.errors;
|
||||||
|
|
||||||
|
if (!!errors?.length) {
|
||||||
|
notify({
|
||||||
|
status: "error",
|
||||||
|
text: intl.formatMessage(commonErrorMessages.unknownError)
|
||||||
|
});
|
||||||
|
|
||||||
|
setShowButtonGreen(false);
|
||||||
|
setTimeout(() => setShowButtonGreen(true), 3000);
|
||||||
|
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 [
|
||||||
|
giftCardDeactivate,
|
||||||
|
giftCardDeactivateOpts
|
||||||
|
] = useGiftCardDeactivateMutation({
|
||||||
|
onCompleted: onDeactivateCompleted
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClick = () =>
|
||||||
|
isActive
|
||||||
|
? giftCardDeactivate({ variables: { id } })
|
||||||
|
: giftCardActivate({ variables: { id } });
|
||||||
|
|
||||||
|
const buttonLabel = isActive ? messages.disableLabel : messages.enableLabel;
|
||||||
|
|
||||||
|
const currentOpts = isActive ? giftCardDeactivateOpts : giftCardActivateOpts;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmButton
|
||||||
|
className={classNames(classes.button, {
|
||||||
|
[classes.buttonRed]: isActive || currentOpts?.status === "error",
|
||||||
|
[classes.buttonGreen]: showButtonGreen
|
||||||
|
})}
|
||||||
|
onClick={handleClick}
|
||||||
|
transitionState={currentOpts?.status}
|
||||||
|
labels={{
|
||||||
|
confirm: intl.formatMessage(buttonLabel),
|
||||||
|
error: intl.formatMessage(commonMessages.error)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardEnableDisableSection;
|
|
@ -0,0 +1,56 @@
|
||||||
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
|
import PageTitleWithStatusChip from "@saleor/components/PageTitleWithStatusChip";
|
||||||
|
import { StatusType } from "@saleor/components/StatusChip/types";
|
||||||
|
import { sectionNames } from "@saleor/intl";
|
||||||
|
import { Backlink } from "@saleor/macaw-ui";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { giftCardsListTableMessages as tableMessages } from "../../GiftCardsList/messages";
|
||||||
|
import useGiftCardDetails from "../providers/GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||||
|
import useGiftCardUpdateDialogs from "../providers/GiftCardUpdateDialogsProvider/hooks/useGiftCardUpdateDialogs";
|
||||||
|
import GiftCardEnableDisableSection from "./GiftCardEnableDisableSection";
|
||||||
|
|
||||||
|
const GiftCardUpdatePageHeader: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const { giftCard } = useGiftCardDetails();
|
||||||
|
const { navigateBack } = useGiftCardUpdateDialogs();
|
||||||
|
|
||||||
|
if (!giftCard) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { displayCode, isActive } = giftCard;
|
||||||
|
|
||||||
|
const title = intl.formatMessage(tableMessages.codeEndingWithLabel, {
|
||||||
|
displayCode
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Backlink onClick={navigateBack}>
|
||||||
|
{intl.formatMessage(sectionNames.giftCards)}
|
||||||
|
</Backlink>
|
||||||
|
<PageHeader
|
||||||
|
inline
|
||||||
|
title={
|
||||||
|
isActive ? (
|
||||||
|
title
|
||||||
|
) : (
|
||||||
|
<PageTitleWithStatusChip
|
||||||
|
title={title}
|
||||||
|
statusLabel={intl.formatMessage(
|
||||||
|
tableMessages.giftCardDisabledLabel
|
||||||
|
)}
|
||||||
|
statusType={StatusType.ERROR}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<GiftCardEnableDisableSection />
|
||||||
|
</PageHeader>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardUpdatePageHeader;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardUpdatePageHeader";
|
||||||
|
export { default } from "./GiftCardUpdatePageHeader";
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const giftCardEnableDisableSectionMessages = defineMessages({
|
||||||
|
enableLabel: {
|
||||||
|
defaultMessage: "Enable",
|
||||||
|
description: "GiftCardEnableDisableSection enable label"
|
||||||
|
},
|
||||||
|
disableLabel: {
|
||||||
|
defaultMessage: "Disable",
|
||||||
|
description: "GiftCardEnableDisableSection enable label"
|
||||||
|
},
|
||||||
|
successfullyEnabledTitle: {
|
||||||
|
defaultMessage: "Successfully enabled gift card",
|
||||||
|
description: "GiftCardEnableDisableSection enable success"
|
||||||
|
},
|
||||||
|
successfullyDisabledTitle: {
|
||||||
|
defaultMessage: "Successfully disabled gift card",
|
||||||
|
description: "GiftCardEnableDisableSection disable success"
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { giftCardErrorFragment } from "@saleor/fragments/errors";
|
||||||
|
import makeMutation from "@saleor/hooks/makeMutation";
|
||||||
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
|
import { giftCardDataFragment } from "../queries";
|
||||||
|
import {
|
||||||
|
GiftCardActivate,
|
||||||
|
GiftCardActivateVariables
|
||||||
|
} from "./types/GiftCardActivate";
|
||||||
|
import {
|
||||||
|
GiftCardDeactivate,
|
||||||
|
GiftCardDeactivateVariables
|
||||||
|
} from "./types/GiftCardDeactivate";
|
||||||
|
|
||||||
|
const giftCardActivate = gql`
|
||||||
|
${giftCardDataFragment}
|
||||||
|
${giftCardErrorFragment}
|
||||||
|
mutation GiftCardActivate($id: ID!) {
|
||||||
|
giftCardActivate(id: $id) {
|
||||||
|
errors {
|
||||||
|
...GiftCardError
|
||||||
|
}
|
||||||
|
giftCard {
|
||||||
|
...GiftCardData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const useGiftCardActivateMutation = makeMutation<
|
||||||
|
GiftCardActivate,
|
||||||
|
GiftCardActivateVariables
|
||||||
|
>(giftCardActivate);
|
||||||
|
|
||||||
|
const giftCardDeactivate = gql`
|
||||||
|
${giftCardDataFragment}
|
||||||
|
${giftCardErrorFragment}
|
||||||
|
mutation GiftCardDeactivate($id: ID!) {
|
||||||
|
giftCardDeactivate(id: $id) {
|
||||||
|
errors {
|
||||||
|
...GiftCardError
|
||||||
|
}
|
||||||
|
giftCard {
|
||||||
|
...GiftCardData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const useGiftCardDeactivateMutation = makeMutation<
|
||||||
|
GiftCardDeactivate,
|
||||||
|
GiftCardDeactivateVariables
|
||||||
|
>(giftCardDeactivate);
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { darken } from "@material-ui/core";
|
||||||
|
import { statusChipStyles } from "@saleor/components/StatusChip/StatusChip";
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
|
export const useGiftCardEnableDisableSectionStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
button: {
|
||||||
|
transition: "backgroundColor 0ms"
|
||||||
|
},
|
||||||
|
buttonRed: {
|
||||||
|
backgroundColor: theme.palette.error.main,
|
||||||
|
color: "#ffffff",
|
||||||
|
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: darken(theme.palette.error.main, 0.1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buttonGreen: {
|
||||||
|
backgroundColor: statusChipStyles.successLabel.color,
|
||||||
|
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: darken(statusChipStyles.successLabel.color, 0.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "GiftCardEnableDisableSection" }
|
||||||
|
);
|
|
@ -0,0 +1,117 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { GiftCardErrorCode, GiftCardExpiryTypeEnum, TimePeriodTypeEnum } from "./../../../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL mutation operation: GiftCardActivate
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_errors {
|
||||||
|
__typename: "GiftCardError";
|
||||||
|
code: GiftCardErrorCode;
|
||||||
|
field: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard_metadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard_privateMetadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard_createdBy {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard_product {
|
||||||
|
__typename: "Product";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard_user {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard_usedBy {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard_app {
|
||||||
|
__typename: "App";
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard_expiryPeriod {
|
||||||
|
__typename: "TimePeriod";
|
||||||
|
amount: number;
|
||||||
|
type: TimePeriodTypeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard_initialBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard_currentBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate_giftCard {
|
||||||
|
__typename: "GiftCard";
|
||||||
|
metadata: (GiftCardActivate_giftCardActivate_giftCard_metadata | null)[];
|
||||||
|
privateMetadata: (GiftCardActivate_giftCardActivate_giftCard_privateMetadata | null)[];
|
||||||
|
displayCode: string;
|
||||||
|
createdBy: GiftCardActivate_giftCardActivate_giftCard_createdBy | null;
|
||||||
|
product: GiftCardActivate_giftCardActivate_giftCard_product | null;
|
||||||
|
user: GiftCardActivate_giftCardActivate_giftCard_user | null;
|
||||||
|
usedBy: GiftCardActivate_giftCardActivate_giftCard_usedBy | null;
|
||||||
|
usedByEmail: string | null;
|
||||||
|
createdByEmail: string | null;
|
||||||
|
app: GiftCardActivate_giftCardActivate_giftCard_app | null;
|
||||||
|
created: any;
|
||||||
|
expiryDate: any | null;
|
||||||
|
expiryType: GiftCardExpiryTypeEnum;
|
||||||
|
expiryPeriod: GiftCardActivate_giftCardActivate_giftCard_expiryPeriod | null;
|
||||||
|
lastUsedOn: any | null;
|
||||||
|
isActive: boolean;
|
||||||
|
initialBalance: GiftCardActivate_giftCardActivate_giftCard_initialBalance | null;
|
||||||
|
currentBalance: GiftCardActivate_giftCardActivate_giftCard_currentBalance | null;
|
||||||
|
id: string;
|
||||||
|
tag: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate_giftCardActivate {
|
||||||
|
__typename: "GiftCardActivate";
|
||||||
|
errors: GiftCardActivate_giftCardActivate_errors[];
|
||||||
|
giftCard: GiftCardActivate_giftCardActivate_giftCard | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivate {
|
||||||
|
giftCardActivate: GiftCardActivate_giftCardActivate | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardActivateVariables {
|
||||||
|
id: string;
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { GiftCardErrorCode, GiftCardExpiryTypeEnum, TimePeriodTypeEnum } from "./../../../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL mutation operation: GiftCardDeactivate
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_errors {
|
||||||
|
__typename: "GiftCardError";
|
||||||
|
code: GiftCardErrorCode;
|
||||||
|
field: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_metadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_privateMetadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_createdBy {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_product {
|
||||||
|
__typename: "Product";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_user {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_usedBy {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_app {
|
||||||
|
__typename: "App";
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_expiryPeriod {
|
||||||
|
__typename: "TimePeriod";
|
||||||
|
amount: number;
|
||||||
|
type: TimePeriodTypeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_initialBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard_currentBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate_giftCard {
|
||||||
|
__typename: "GiftCard";
|
||||||
|
metadata: (GiftCardDeactivate_giftCardDeactivate_giftCard_metadata | null)[];
|
||||||
|
privateMetadata: (GiftCardDeactivate_giftCardDeactivate_giftCard_privateMetadata | null)[];
|
||||||
|
displayCode: string;
|
||||||
|
createdBy: GiftCardDeactivate_giftCardDeactivate_giftCard_createdBy | null;
|
||||||
|
product: GiftCardDeactivate_giftCardDeactivate_giftCard_product | null;
|
||||||
|
user: GiftCardDeactivate_giftCardDeactivate_giftCard_user | null;
|
||||||
|
usedBy: GiftCardDeactivate_giftCardDeactivate_giftCard_usedBy | null;
|
||||||
|
usedByEmail: string | null;
|
||||||
|
createdByEmail: string | null;
|
||||||
|
app: GiftCardDeactivate_giftCardDeactivate_giftCard_app | null;
|
||||||
|
created: any;
|
||||||
|
expiryDate: any | null;
|
||||||
|
expiryType: GiftCardExpiryTypeEnum;
|
||||||
|
expiryPeriod: GiftCardDeactivate_giftCardDeactivate_giftCard_expiryPeriod | null;
|
||||||
|
lastUsedOn: any | null;
|
||||||
|
isActive: boolean;
|
||||||
|
initialBalance: GiftCardDeactivate_giftCardDeactivate_giftCard_initialBalance | null;
|
||||||
|
currentBalance: GiftCardDeactivate_giftCardDeactivate_giftCard_currentBalance | null;
|
||||||
|
id: string;
|
||||||
|
tag: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate_giftCardDeactivate {
|
||||||
|
__typename: "GiftCardDeactivate";
|
||||||
|
errors: GiftCardDeactivate_giftCardDeactivate_errors[];
|
||||||
|
giftCard: GiftCardDeactivate_giftCardDeactivate_giftCard | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivate {
|
||||||
|
giftCardDeactivate: GiftCardDeactivate_giftCardDeactivate | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDeactivateVariables {
|
||||||
|
id: string;
|
||||||
|
}
|
2
src/giftCards/GiftCardUpdate/index.tsx
Normal file
2
src/giftCards/GiftCardUpdate/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardUpdate";
|
||||||
|
export { default } from "./GiftCardUpdate";
|
34
src/giftCards/GiftCardUpdate/messages.ts
Normal file
34
src/giftCards/GiftCardUpdate/messages.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { GiftCardErrorCode } from "@saleor/types/globalTypes";
|
||||||
|
import commonErrorMessages from "@saleor/utils/errors/common";
|
||||||
|
import { defineMessages, IntlShape } from "react-intl";
|
||||||
|
|
||||||
|
import { GiftCardUpdate_giftCardUpdate_errors } from "./types/GiftCardUpdate";
|
||||||
|
|
||||||
|
export const giftCardUpdateDetailsCardMessages = defineMessages({
|
||||||
|
title: {
|
||||||
|
defaultMessage: "Details",
|
||||||
|
description: "GiftCardUpdateDetailsCard title"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export function getGiftCardErrorMessage(
|
||||||
|
error: Omit<GiftCardUpdate_giftCardUpdate_errors, "__typename"> | undefined,
|
||||||
|
intl: IntlShape
|
||||||
|
): string {
|
||||||
|
if (error) {
|
||||||
|
switch (error.code) {
|
||||||
|
case GiftCardErrorCode.GRAPHQL_ERROR:
|
||||||
|
return intl.formatMessage(commonErrorMessages.graphqlError);
|
||||||
|
case GiftCardErrorCode.REQUIRED:
|
||||||
|
return intl.formatMessage(commonMessages.requiredField);
|
||||||
|
case GiftCardErrorCode.INVALID:
|
||||||
|
return intl.formatMessage(commonErrorMessages.invalid);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return intl.formatMessage(commonErrorMessages.unknownError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
29
src/giftCards/GiftCardUpdate/mutations.ts
Normal file
29
src/giftCards/GiftCardUpdate/mutations.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { giftCardErrorFragment } from "@saleor/fragments/errors";
|
||||||
|
import makeMutation from "@saleor/hooks/makeMutation";
|
||||||
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
|
import { giftCardDataFragment } from "./queries";
|
||||||
|
import {
|
||||||
|
GiftCardUpdate,
|
||||||
|
GiftCardUpdateVariables
|
||||||
|
} from "./types/GiftCardUpdate";
|
||||||
|
|
||||||
|
const giftCardUpdate = gql`
|
||||||
|
${giftCardDataFragment}
|
||||||
|
${giftCardErrorFragment}
|
||||||
|
mutation GiftCardUpdate($id: ID!, $input: GiftCardUpdateInput!) {
|
||||||
|
giftCardUpdate(id: $id, input: $input) {
|
||||||
|
errors {
|
||||||
|
...GiftCardError
|
||||||
|
}
|
||||||
|
giftCard {
|
||||||
|
...GiftCardData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const useGiftCardUpdateMutation = makeMutation<
|
||||||
|
GiftCardUpdate,
|
||||||
|
GiftCardUpdateVariables
|
||||||
|
>(giftCardUpdate);
|
|
@ -0,0 +1,41 @@
|
||||||
|
import React, { createContext } from "react";
|
||||||
|
|
||||||
|
import { useGiftCardDetailsQuery } from "../../queries";
|
||||||
|
import { GiftCardDetails_giftCard } from "../../types/GiftCardDetails";
|
||||||
|
|
||||||
|
interface GiftCardDetailsProviderProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetailsConsumerProps {
|
||||||
|
giftCard: GiftCardDetails_giftCard;
|
||||||
|
loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GiftCardDetailsContext = createContext<
|
||||||
|
GiftCardDetailsConsumerProps
|
||||||
|
>(null);
|
||||||
|
|
||||||
|
const GiftCardDetailsProvider: React.FC<GiftCardDetailsProviderProps> = ({
|
||||||
|
children,
|
||||||
|
id
|
||||||
|
}) => {
|
||||||
|
const { data, loading } = useGiftCardDetailsQuery({
|
||||||
|
displayLoader: true,
|
||||||
|
variables: { id }
|
||||||
|
});
|
||||||
|
|
||||||
|
const providerValues: GiftCardDetailsConsumerProps = {
|
||||||
|
giftCard: data?.giftCard,
|
||||||
|
loading
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GiftCardDetailsContext.Provider value={providerValues}>
|
||||||
|
{children}
|
||||||
|
</GiftCardDetailsContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardDetailsProvider;
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { useContext } from "react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
GiftCardDetailsConsumerProps,
|
||||||
|
GiftCardDetailsContext
|
||||||
|
} from "../GiftCardDetailsProvider";
|
||||||
|
|
||||||
|
const useGiftCardDetails = (): GiftCardDetailsConsumerProps => {
|
||||||
|
const giftCardDetailsConsumerProps = useContext(GiftCardDetailsContext);
|
||||||
|
|
||||||
|
return giftCardDetailsConsumerProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useGiftCardDetails;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardDetailsProvider";
|
||||||
|
export { default } from "./GiftCardDetailsProvider";
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { giftCardsListPath, giftCardUrl } from "@saleor/giftCards/urls";
|
||||||
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
|
import React, { createContext } from "react";
|
||||||
|
|
||||||
|
import GiftCardUpdateBalanceDialog from "../../GiftCardUpdateBalanceDialog";
|
||||||
|
import {
|
||||||
|
GiftCardUpdatePageActionParamsEnum,
|
||||||
|
GiftCardUpdatePageUrlQueryParams
|
||||||
|
} from "../../types";
|
||||||
|
import useGiftCardDetails from "../GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||||
|
|
||||||
|
interface GiftCardUpdateDialogsProviderProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
params: GiftCardUpdatePageUrlQueryParams;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdateDialogsConsumerProps {
|
||||||
|
navigateBack: () => void;
|
||||||
|
openSetBalanceDialog: () => void;
|
||||||
|
closeDialog: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GiftCardUpdateDialogsContext = createContext<
|
||||||
|
GiftCardUpdateDialogsConsumerProps
|
||||||
|
>(null);
|
||||||
|
|
||||||
|
const GiftCardUpdateDialogsProvider: React.FC<GiftCardUpdateDialogsProviderProps> = ({
|
||||||
|
children,
|
||||||
|
params,
|
||||||
|
id
|
||||||
|
}) => {
|
||||||
|
const navigate = useNavigator();
|
||||||
|
|
||||||
|
const { loading: loadingGiftCard } = useGiftCardDetails();
|
||||||
|
|
||||||
|
const [openDialog, closeDialog] = createDialogActionHandlers<
|
||||||
|
GiftCardUpdatePageActionParamsEnum,
|
||||||
|
GiftCardUpdatePageUrlQueryParams
|
||||||
|
>(navigate, params => giftCardUrl(id, params), params);
|
||||||
|
|
||||||
|
const openSetBalanceDialog = () =>
|
||||||
|
openDialog(GiftCardUpdatePageActionParamsEnum.SET_BALANCE);
|
||||||
|
|
||||||
|
const isSetBalanceDialogOpen =
|
||||||
|
params?.action === GiftCardUpdatePageActionParamsEnum.SET_BALANCE;
|
||||||
|
|
||||||
|
const navigateBack = () => navigate(giftCardsListPath);
|
||||||
|
|
||||||
|
const providerValues: GiftCardUpdateDialogsConsumerProps = {
|
||||||
|
openSetBalanceDialog,
|
||||||
|
closeDialog,
|
||||||
|
navigateBack
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GiftCardUpdateDialogsContext.Provider value={providerValues}>
|
||||||
|
{children}
|
||||||
|
{!loadingGiftCard && (
|
||||||
|
<GiftCardUpdateBalanceDialog
|
||||||
|
onClose={closeDialog}
|
||||||
|
open={isSetBalanceDialogOpen}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</GiftCardUpdateDialogsContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardUpdateDialogsProvider;
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { useContext } from "react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
GiftCardUpdateDialogsConsumerProps,
|
||||||
|
GiftCardUpdateDialogsContext
|
||||||
|
} from "../GiftCardUpdateDialogsProvider";
|
||||||
|
|
||||||
|
const useGiftCardUpdateDialogs = (): GiftCardUpdateDialogsConsumerProps => {
|
||||||
|
const giftCardUpdateDialogsProps = useContext(GiftCardUpdateDialogsContext);
|
||||||
|
|
||||||
|
return giftCardUpdateDialogsProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useGiftCardUpdateDialogs;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardUpdateDialogsProvider";
|
||||||
|
export { default } from "./GiftCardUpdateDialogsProvider";
|
|
@ -0,0 +1,163 @@
|
||||||
|
import { MetadataFormData } from "@saleor/components/Metadata";
|
||||||
|
import { GiftCardError } from "@saleor/fragments/types/GiftCardError";
|
||||||
|
import { GiftCardCommonFormData } from "@saleor/giftCards/GiftCardCreateDialog/types";
|
||||||
|
import { getGiftCardExpirySettingsInputData } from "@saleor/giftCards/GiftCardCreateDialog/utils";
|
||||||
|
import { MutationResultWithOpts } from "@saleor/hooks/makeMutation";
|
||||||
|
import useForm, { FormChange, UseFormResult } from "@saleor/hooks/useForm";
|
||||||
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import { getDefaultNotifierSuccessErrorData } from "@saleor/hooks/useNotifier/utils";
|
||||||
|
import { TimePeriodTypeEnum } from "@saleor/types/globalTypes";
|
||||||
|
import { getFormErrors } from "@saleor/utils/errors";
|
||||||
|
import handleFormSubmit from "@saleor/utils/handlers/handleFormSubmit";
|
||||||
|
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
||||||
|
import { mapMetadataItemToInput } from "@saleor/utils/maps";
|
||||||
|
import getMetadata from "@saleor/utils/metadata/getMetadata";
|
||||||
|
import {
|
||||||
|
useMetadataUpdate,
|
||||||
|
usePrivateMetadataUpdate
|
||||||
|
} from "@saleor/utils/metadata/updateMetadata";
|
||||||
|
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||||
|
import React, { createContext } from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { initialData as emptyFormData } from "../../../GiftCardCreateDialog/GiftCardCreateDialogForm";
|
||||||
|
import { useGiftCardUpdateMutation } from "../../mutations";
|
||||||
|
import { GiftCardUpdate } from "../../types/GiftCardUpdate";
|
||||||
|
import useGiftCardDetails from "../GiftCardDetailsProvider/hooks/useGiftCardDetails";
|
||||||
|
|
||||||
|
interface GiftCardUpdateFormProviderProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GiftCardUpdateFormData = MetadataFormData &
|
||||||
|
Omit<GiftCardCommonFormData, "balanceAmount" | "balanceCurrency">;
|
||||||
|
|
||||||
|
export interface GiftCardUpdateFormConsumerData
|
||||||
|
extends GiftCardUpdateFormErrors {
|
||||||
|
opts: MutationResultWithOpts<GiftCardUpdate>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdateFormErrors {
|
||||||
|
formErrors: Record<"tag" | "expiryDate" | "expiryPeriod", GiftCardError>;
|
||||||
|
handlers: { changeMetadata: FormChange };
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GiftCardUpdateFormConsumerProps = UseFormResult<
|
||||||
|
GiftCardUpdateFormData
|
||||||
|
> &
|
||||||
|
GiftCardUpdateFormConsumerData;
|
||||||
|
|
||||||
|
export const GiftCardUpdateFormContext = createContext<
|
||||||
|
GiftCardUpdateFormConsumerProps
|
||||||
|
>(null);
|
||||||
|
|
||||||
|
const GiftCardUpdateFormProvider: React.FC<GiftCardUpdateFormProviderProps> = ({
|
||||||
|
children
|
||||||
|
}) => {
|
||||||
|
const notify = useNotifier();
|
||||||
|
const intl = useIntl();
|
||||||
|
const [updateMetadata] = useMetadataUpdate({});
|
||||||
|
const [updatePrivateMetadata] = usePrivateMetadataUpdate({});
|
||||||
|
|
||||||
|
const { loading: loadingGiftCard, giftCard } = useGiftCardDetails();
|
||||||
|
|
||||||
|
const getInitialData = (): GiftCardUpdateFormData => {
|
||||||
|
if (loadingGiftCard || !giftCard) {
|
||||||
|
return { ...emptyFormData, metadata: [], privateMetadata: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
tag,
|
||||||
|
expiryDate,
|
||||||
|
expiryType,
|
||||||
|
expiryPeriod,
|
||||||
|
privateMetadata,
|
||||||
|
metadata
|
||||||
|
} = giftCard;
|
||||||
|
|
||||||
|
return {
|
||||||
|
tag,
|
||||||
|
expiryDate,
|
||||||
|
expiryType,
|
||||||
|
expiryPeriodType: expiryPeriod?.type || TimePeriodTypeEnum.YEAR,
|
||||||
|
expiryPeriodAmount: expiryPeriod?.amount || 1,
|
||||||
|
privateMetadata: privateMetadata?.map(mapMetadataItemToInput),
|
||||||
|
metadata: metadata?.map(mapMetadataItemToInput)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = (data: GiftCardUpdate) => {
|
||||||
|
const errors = data.giftCardUpdate.errors;
|
||||||
|
|
||||||
|
notify(getDefaultNotifierSuccessErrorData(errors, intl));
|
||||||
|
};
|
||||||
|
|
||||||
|
const [updateGiftCard, updateGiftCardOpts] = useGiftCardUpdateMutation({
|
||||||
|
onCompleted: onSubmit
|
||||||
|
});
|
||||||
|
|
||||||
|
const submit = async (formData: GiftCardUpdateFormData) => {
|
||||||
|
const result = await updateGiftCard({
|
||||||
|
variables: {
|
||||||
|
id: giftCard?.id,
|
||||||
|
input: {
|
||||||
|
tag: formData.tag,
|
||||||
|
expirySettings: getGiftCardExpirySettingsInputData(formData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result?.data?.giftCardUpdate?.errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formProps = useForm<GiftCardUpdateFormData>(getInitialData());
|
||||||
|
|
||||||
|
const { data, change, setChanged, hasChanged } = formProps;
|
||||||
|
|
||||||
|
const {
|
||||||
|
isMetadataModified,
|
||||||
|
isPrivateMetadataModified,
|
||||||
|
makeChangeHandler: makeMetadataChangeHandler
|
||||||
|
} = useMetadataChangeTrigger();
|
||||||
|
|
||||||
|
const changeMetadata = makeMetadataChangeHandler(change);
|
||||||
|
|
||||||
|
const submitData: GiftCardUpdateFormData = {
|
||||||
|
...data,
|
||||||
|
...getMetadata(data, isMetadataModified, isPrivateMetadataModified)
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = createMetadataUpdateHandler(
|
||||||
|
giftCard,
|
||||||
|
submit,
|
||||||
|
variables => updateMetadata({ variables }),
|
||||||
|
variables => updatePrivateMetadata({ variables })
|
||||||
|
);
|
||||||
|
|
||||||
|
const formSubmit = () =>
|
||||||
|
handleFormSubmit(submitData, handleSubmit, setChanged);
|
||||||
|
|
||||||
|
const formErrors = getFormErrors(
|
||||||
|
["tag", "expiryDate", "expiryPeriod"],
|
||||||
|
updateGiftCardOpts?.data?.giftCardUpdate?.errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const providerValues = {
|
||||||
|
...formProps,
|
||||||
|
opts: updateGiftCardOpts,
|
||||||
|
hasChanged,
|
||||||
|
formErrors,
|
||||||
|
submit: formSubmit,
|
||||||
|
handlers: {
|
||||||
|
changeMetadata
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GiftCardUpdateFormContext.Provider value={providerValues}>
|
||||||
|
{children}
|
||||||
|
</GiftCardUpdateFormContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardUpdateFormProvider;
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { useContext } from "react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
GiftCardUpdateFormConsumerData,
|
||||||
|
GiftCardUpdateFormContext
|
||||||
|
} from "../GiftCardUpdateFormProvider";
|
||||||
|
|
||||||
|
const useGiftCardUpdate = (): Pick<GiftCardUpdateFormConsumerData, "opts"> => {
|
||||||
|
const { opts } = useContext(GiftCardUpdateFormContext);
|
||||||
|
|
||||||
|
return { opts };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useGiftCardUpdate;
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { UseFormResult } from "@saleor/hooks/useForm";
|
||||||
|
import omit from "lodash/omit";
|
||||||
|
import { useContext } from "react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
GiftCardUpdateFormContext,
|
||||||
|
GiftCardUpdateFormData,
|
||||||
|
GiftCardUpdateFormErrors
|
||||||
|
} from "../GiftCardUpdateFormProvider";
|
||||||
|
|
||||||
|
type UseGiftCardUpdateFormProps = UseFormResult<GiftCardUpdateFormData> &
|
||||||
|
GiftCardUpdateFormErrors;
|
||||||
|
|
||||||
|
const useGiftCardUpdate = (): UseGiftCardUpdateFormProps => {
|
||||||
|
const giftCardUpdateFormProviderProps = useContext(GiftCardUpdateFormContext);
|
||||||
|
|
||||||
|
return omit(giftCardUpdateFormProviderProps, ["opts"]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useGiftCardUpdate;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardUpdateFormProvider";
|
||||||
|
export { default } from "./GiftCardUpdateFormProvider";
|
116
src/giftCards/GiftCardUpdate/queries.ts
Normal file
116
src/giftCards/GiftCardUpdate/queries.ts
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
import { fragmentUserBase } from "@saleor/fragments/auth";
|
||||||
|
import { metadataFragment } from "@saleor/fragments/metadata";
|
||||||
|
import { fragmentMoney } from "@saleor/fragments/products";
|
||||||
|
import { fragmentTimePeriod } from "@saleor/fragments/timePeriod";
|
||||||
|
import makeQuery from "@saleor/hooks/makeQuery";
|
||||||
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
|
import {
|
||||||
|
GiftCardDetails,
|
||||||
|
GiftCardDetailsVariables
|
||||||
|
} from "./types/GiftCardDetails";
|
||||||
|
|
||||||
|
export const giftCardDataFragment = gql`
|
||||||
|
${fragmentMoney}
|
||||||
|
${metadataFragment}
|
||||||
|
${fragmentUserBase}
|
||||||
|
${fragmentTimePeriod}
|
||||||
|
fragment GiftCardData on GiftCard {
|
||||||
|
...MetadataFragment
|
||||||
|
displayCode
|
||||||
|
createdBy {
|
||||||
|
...UserBase
|
||||||
|
}
|
||||||
|
product {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
user {
|
||||||
|
...UserBase
|
||||||
|
}
|
||||||
|
usedBy {
|
||||||
|
...UserBase
|
||||||
|
}
|
||||||
|
usedByEmail
|
||||||
|
createdByEmail
|
||||||
|
app {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
created
|
||||||
|
expiryDate
|
||||||
|
expiryType
|
||||||
|
expiryPeriod {
|
||||||
|
...TimePeriod
|
||||||
|
}
|
||||||
|
lastUsedOn
|
||||||
|
isActive
|
||||||
|
initialBalance {
|
||||||
|
...Money
|
||||||
|
}
|
||||||
|
currentBalance {
|
||||||
|
...Money
|
||||||
|
}
|
||||||
|
|
||||||
|
id
|
||||||
|
tag
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const giftCardDetails = gql`
|
||||||
|
${giftCardDataFragment}
|
||||||
|
query GiftCardDetails($id: ID!) {
|
||||||
|
giftCard(id: $id) {
|
||||||
|
...GiftCardData
|
||||||
|
events {
|
||||||
|
expiry {
|
||||||
|
expiryType
|
||||||
|
expiryPeriod {
|
||||||
|
...TimePeriod
|
||||||
|
}
|
||||||
|
expiryDate
|
||||||
|
oldExpiryType
|
||||||
|
oldExpiryPeriod {
|
||||||
|
...TimePeriod
|
||||||
|
}
|
||||||
|
oldExpiryDate
|
||||||
|
}
|
||||||
|
id
|
||||||
|
date
|
||||||
|
type
|
||||||
|
user {
|
||||||
|
...UserBase
|
||||||
|
}
|
||||||
|
app {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
message
|
||||||
|
email
|
||||||
|
orderId
|
||||||
|
orderNumber
|
||||||
|
tag
|
||||||
|
oldTag
|
||||||
|
balance {
|
||||||
|
initialBalance {
|
||||||
|
...Money
|
||||||
|
}
|
||||||
|
currentBalance {
|
||||||
|
...Money
|
||||||
|
}
|
||||||
|
oldInitialBalance {
|
||||||
|
...Money
|
||||||
|
}
|
||||||
|
oldCurrentBalance {
|
||||||
|
...Money
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const useGiftCardDetailsQuery = makeQuery<
|
||||||
|
GiftCardDetails,
|
||||||
|
GiftCardDetailsVariables
|
||||||
|
>(giftCardDetails);
|
9
src/giftCards/GiftCardUpdate/types.ts
Normal file
9
src/giftCards/GiftCardUpdate/types.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { Dialog } from "@saleor/types";
|
||||||
|
|
||||||
|
export enum GiftCardUpdatePageActionParamsEnum {
|
||||||
|
SET_BALANCE = "set-balance"
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GiftCardUpdatePageUrlQueryParams = Dialog<
|
||||||
|
GiftCardUpdatePageActionParamsEnum
|
||||||
|
>;
|
97
src/giftCards/GiftCardUpdate/types/GiftCardData.ts
Normal file
97
src/giftCards/GiftCardUpdate/types/GiftCardData.ts
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { GiftCardExpiryTypeEnum, TimePeriodTypeEnum } from "./../../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL fragment: GiftCardData
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface GiftCardData_metadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardData_privateMetadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardData_createdBy {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardData_product {
|
||||||
|
__typename: "Product";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardData_user {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardData_usedBy {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardData_app {
|
||||||
|
__typename: "App";
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardData_expiryPeriod {
|
||||||
|
__typename: "TimePeriod";
|
||||||
|
amount: number;
|
||||||
|
type: TimePeriodTypeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardData_initialBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardData_currentBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardData {
|
||||||
|
__typename: "GiftCard";
|
||||||
|
metadata: (GiftCardData_metadata | null)[];
|
||||||
|
privateMetadata: (GiftCardData_privateMetadata | null)[];
|
||||||
|
displayCode: string;
|
||||||
|
createdBy: GiftCardData_createdBy | null;
|
||||||
|
product: GiftCardData_product | null;
|
||||||
|
user: GiftCardData_user | null;
|
||||||
|
usedBy: GiftCardData_usedBy | null;
|
||||||
|
usedByEmail: string | null;
|
||||||
|
createdByEmail: string | null;
|
||||||
|
app: GiftCardData_app | null;
|
||||||
|
created: any;
|
||||||
|
expiryDate: any | null;
|
||||||
|
expiryType: GiftCardExpiryTypeEnum;
|
||||||
|
expiryPeriod: GiftCardData_expiryPeriod | null;
|
||||||
|
lastUsedOn: any | null;
|
||||||
|
isActive: boolean;
|
||||||
|
initialBalance: GiftCardData_initialBalance | null;
|
||||||
|
currentBalance: GiftCardData_currentBalance | null;
|
||||||
|
id: string;
|
||||||
|
tag: string | null;
|
||||||
|
}
|
190
src/giftCards/GiftCardUpdate/types/GiftCardDetails.ts
Normal file
190
src/giftCards/GiftCardUpdate/types/GiftCardDetails.ts
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { GiftCardExpiryTypeEnum, TimePeriodTypeEnum, GiftCardEventsEnum } from "./../../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL query operation: GiftCardDetails
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_metadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_privateMetadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_createdBy {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_product {
|
||||||
|
__typename: "Product";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_user {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_usedBy {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_app {
|
||||||
|
__typename: "App";
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_expiryPeriod {
|
||||||
|
__typename: "TimePeriod";
|
||||||
|
amount: number;
|
||||||
|
type: TimePeriodTypeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_initialBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_currentBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events_expiry_expiryPeriod {
|
||||||
|
__typename: "TimePeriod";
|
||||||
|
amount: number;
|
||||||
|
type: TimePeriodTypeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events_expiry_oldExpiryPeriod {
|
||||||
|
__typename: "TimePeriod";
|
||||||
|
amount: number;
|
||||||
|
type: TimePeriodTypeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events_expiry {
|
||||||
|
__typename: "GiftCardEventExpiry";
|
||||||
|
expiryType: GiftCardExpiryTypeEnum | null;
|
||||||
|
expiryPeriod: GiftCardDetails_giftCard_events_expiry_expiryPeriod | null;
|
||||||
|
expiryDate: any | null;
|
||||||
|
oldExpiryType: GiftCardExpiryTypeEnum | null;
|
||||||
|
oldExpiryPeriod: GiftCardDetails_giftCard_events_expiry_oldExpiryPeriod | null;
|
||||||
|
oldExpiryDate: any | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events_user {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events_app {
|
||||||
|
__typename: "App";
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events_balance_initialBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events_balance_currentBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events_balance_oldInitialBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events_balance_oldCurrentBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events_balance {
|
||||||
|
__typename: "GiftCardEventBalance";
|
||||||
|
initialBalance: GiftCardDetails_giftCard_events_balance_initialBalance;
|
||||||
|
currentBalance: GiftCardDetails_giftCard_events_balance_currentBalance;
|
||||||
|
oldInitialBalance: GiftCardDetails_giftCard_events_balance_oldInitialBalance | null;
|
||||||
|
oldCurrentBalance: GiftCardDetails_giftCard_events_balance_oldCurrentBalance | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard_events {
|
||||||
|
__typename: "GiftCardEvent";
|
||||||
|
expiry: GiftCardDetails_giftCard_events_expiry | null;
|
||||||
|
id: string;
|
||||||
|
date: any | null;
|
||||||
|
type: GiftCardEventsEnum | null;
|
||||||
|
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;
|
||||||
|
balance: GiftCardDetails_giftCard_events_balance | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails_giftCard {
|
||||||
|
__typename: "GiftCard";
|
||||||
|
metadata: (GiftCardDetails_giftCard_metadata | null)[];
|
||||||
|
privateMetadata: (GiftCardDetails_giftCard_privateMetadata | null)[];
|
||||||
|
displayCode: string;
|
||||||
|
createdBy: GiftCardDetails_giftCard_createdBy | null;
|
||||||
|
product: GiftCardDetails_giftCard_product | null;
|
||||||
|
user: GiftCardDetails_giftCard_user | null;
|
||||||
|
usedBy: GiftCardDetails_giftCard_usedBy | null;
|
||||||
|
usedByEmail: string | null;
|
||||||
|
createdByEmail: string | null;
|
||||||
|
app: GiftCardDetails_giftCard_app | null;
|
||||||
|
created: any;
|
||||||
|
expiryDate: any | null;
|
||||||
|
expiryType: GiftCardExpiryTypeEnum;
|
||||||
|
expiryPeriod: GiftCardDetails_giftCard_expiryPeriod | null;
|
||||||
|
lastUsedOn: any | null;
|
||||||
|
isActive: boolean;
|
||||||
|
initialBalance: GiftCardDetails_giftCard_initialBalance | null;
|
||||||
|
currentBalance: GiftCardDetails_giftCard_currentBalance | null;
|
||||||
|
id: string;
|
||||||
|
tag: string | null;
|
||||||
|
events: GiftCardDetails_giftCard_events[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetails {
|
||||||
|
giftCard: GiftCardDetails_giftCard | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardDetailsVariables {
|
||||||
|
id: string;
|
||||||
|
}
|
118
src/giftCards/GiftCardUpdate/types/GiftCardUpdate.ts
Normal file
118
src/giftCards/GiftCardUpdate/types/GiftCardUpdate.ts
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @generated
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { GiftCardUpdateInput, GiftCardErrorCode, GiftCardExpiryTypeEnum, TimePeriodTypeEnum } from "./../../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL mutation operation: GiftCardUpdate
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_errors {
|
||||||
|
__typename: "GiftCardError";
|
||||||
|
code: GiftCardErrorCode;
|
||||||
|
field: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard_metadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard_privateMetadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard_createdBy {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard_product {
|
||||||
|
__typename: "Product";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard_user {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard_usedBy {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard_app {
|
||||||
|
__typename: "App";
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard_expiryPeriod {
|
||||||
|
__typename: "TimePeriod";
|
||||||
|
amount: number;
|
||||||
|
type: TimePeriodTypeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard_initialBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard_currentBalance {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate_giftCard {
|
||||||
|
__typename: "GiftCard";
|
||||||
|
metadata: (GiftCardUpdate_giftCardUpdate_giftCard_metadata | null)[];
|
||||||
|
privateMetadata: (GiftCardUpdate_giftCardUpdate_giftCard_privateMetadata | null)[];
|
||||||
|
displayCode: string;
|
||||||
|
createdBy: GiftCardUpdate_giftCardUpdate_giftCard_createdBy | null;
|
||||||
|
product: GiftCardUpdate_giftCardUpdate_giftCard_product | null;
|
||||||
|
user: GiftCardUpdate_giftCardUpdate_giftCard_user | null;
|
||||||
|
usedBy: GiftCardUpdate_giftCardUpdate_giftCard_usedBy | null;
|
||||||
|
usedByEmail: string | null;
|
||||||
|
createdByEmail: string | null;
|
||||||
|
app: GiftCardUpdate_giftCardUpdate_giftCard_app | null;
|
||||||
|
created: any;
|
||||||
|
expiryDate: any | null;
|
||||||
|
expiryType: GiftCardExpiryTypeEnum;
|
||||||
|
expiryPeriod: GiftCardUpdate_giftCardUpdate_giftCard_expiryPeriod | null;
|
||||||
|
lastUsedOn: any | null;
|
||||||
|
isActive: boolean;
|
||||||
|
initialBalance: GiftCardUpdate_giftCardUpdate_giftCard_initialBalance | null;
|
||||||
|
currentBalance: GiftCardUpdate_giftCardUpdate_giftCard_currentBalance | null;
|
||||||
|
id: string;
|
||||||
|
tag: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate_giftCardUpdate {
|
||||||
|
__typename: "GiftCardUpdate";
|
||||||
|
errors: GiftCardUpdate_giftCardUpdate_errors[];
|
||||||
|
giftCard: GiftCardUpdate_giftCardUpdate_giftCard | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdate {
|
||||||
|
giftCardUpdate: GiftCardUpdate_giftCardUpdate | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GiftCardUpdateVariables {
|
||||||
|
id: string;
|
||||||
|
input: GiftCardUpdateInput;
|
||||||
|
}
|
46
src/giftCards/GiftCardsList/GiftCardsList.tsx
Normal file
46
src/giftCards/GiftCardsList/GiftCardsList.tsx
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import Container from "@saleor/components/Container";
|
||||||
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import GiftCardCreateDialog from "../GiftCardCreateDialog";
|
||||||
|
import { giftCardsListUrl } from "../urls";
|
||||||
|
import GiftCardsListHeader from "./GiftCardsListHeader";
|
||||||
|
import GiftCardsListTable from "./GiftCardsListTable";
|
||||||
|
import { GiftCardsListProvider } from "./providers/GiftCardsListProvider";
|
||||||
|
import {
|
||||||
|
GiftCardListActionParamsEnum,
|
||||||
|
GiftCardListUrlQueryParams
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
|
interface GiftCardsListProps {
|
||||||
|
params: GiftCardListUrlQueryParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GiftCardsList: React.FC<GiftCardsListProps> = ({ params }) => {
|
||||||
|
const navigate = useNavigator();
|
||||||
|
|
||||||
|
const [openModal, closeModal] = createDialogActionHandlers<
|
||||||
|
GiftCardListActionParamsEnum,
|
||||||
|
GiftCardListUrlQueryParams
|
||||||
|
>(navigate, giftCardsListUrl, params);
|
||||||
|
|
||||||
|
const openCreateModal = () => openModal(GiftCardListActionParamsEnum.CREATE);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<GiftCardsListProvider params={params}>
|
||||||
|
<Container>
|
||||||
|
<GiftCardsListHeader onIssueButtonClick={openCreateModal} />
|
||||||
|
<GiftCardsListTable />
|
||||||
|
</Container>
|
||||||
|
</GiftCardsListProvider>
|
||||||
|
<GiftCardCreateDialog
|
||||||
|
open={params?.action === GiftCardListActionParamsEnum.CREATE}
|
||||||
|
onClose={closeModal}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardsList;
|
49
src/giftCards/GiftCardsList/GiftCardsListHeader.tsx
Normal file
49
src/giftCards/GiftCardsList/GiftCardsListHeader.tsx
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import { Button } from "@material-ui/core";
|
||||||
|
import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer";
|
||||||
|
// import CardMenu, { CardMenuItem } from "@saleor/components/CardMenu";
|
||||||
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
|
import { sectionNames } from "@saleor/intl";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { giftCardsListHeaderMenuItemsMessages as messages } from "./messages";
|
||||||
|
|
||||||
|
interface GiftCardsListHeaderProps {
|
||||||
|
onIssueButtonClick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GiftCardsListHeader: React.FC<GiftCardsListHeaderProps> = ({
|
||||||
|
onIssueButtonClick
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
// const menuItems: CardMenuItem[] = [
|
||||||
|
// {
|
||||||
|
// label: intl.formatMessage(messages.settings),
|
||||||
|
// testId: "settingsMenuItem"
|
||||||
|
// // onSelect:
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// label: intl.formatMessage(messages.bulkIssue),
|
||||||
|
// testId: "bulkIssueMenuItem"
|
||||||
|
// // onSelect:
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// label: intl.formatMessage(messages.exportCodes),
|
||||||
|
// testId: "exportCodesMenuItem"
|
||||||
|
// // onSelect:
|
||||||
|
// }
|
||||||
|
// ];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageHeader title={intl.formatMessage(sectionNames.giftCards)}>
|
||||||
|
{/* <CardMenu menuItems={menuItems} data-test="menu" /> */}
|
||||||
|
<HorizontalSpacer spacing={2} />
|
||||||
|
<Button color="primary" variant="contained" onClick={onIssueButtonClick}>
|
||||||
|
{intl.formatMessage(messages.issueButtonLabel)}
|
||||||
|
</Button>
|
||||||
|
</PageHeader>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardsListHeader;
|
|
@ -0,0 +1,147 @@
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableRow,
|
||||||
|
Typography
|
||||||
|
} from "@material-ui/core";
|
||||||
|
import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer";
|
||||||
|
import Checkbox from "@saleor/components/Checkbox";
|
||||||
|
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 { 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 { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { giftCardsListTableMessages as messages } from "../messages";
|
||||||
|
import useGiftCardList from "../providers/hooks/useGiftCardList";
|
||||||
|
import useGiftCardListBulkActions from "../providers/hooks/useGiftCardListBulkActions";
|
||||||
|
import { useTableStyles as useStyles } from "../styles";
|
||||||
|
import GiftCardsListTableFooter from "./GiftCardsListTableFooter";
|
||||||
|
import GiftCardsListTableHeader from "./GiftCardsListTableHeader";
|
||||||
|
|
||||||
|
const PLACEHOLDER = "-";
|
||||||
|
|
||||||
|
const GiftCardsListTable: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const classes = useStyles({});
|
||||||
|
const navigate = useNavigator();
|
||||||
|
const { giftCards, numberOfColumns, loading } = useGiftCardList();
|
||||||
|
const { toggle, isSelected } = useGiftCardListBulkActions();
|
||||||
|
|
||||||
|
const redirectToGiftCardUpdate = (id: string) => () =>
|
||||||
|
navigate(giftCardUrl(id));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<ResponsiveTable>
|
||||||
|
<GiftCardsListTableHeader />
|
||||||
|
<GiftCardsListTableFooter />
|
||||||
|
<TableBody>
|
||||||
|
{renderCollection(
|
||||||
|
giftCards,
|
||||||
|
({
|
||||||
|
id,
|
||||||
|
displayCode,
|
||||||
|
usedBy,
|
||||||
|
usedByEmail,
|
||||||
|
tag,
|
||||||
|
isActive,
|
||||||
|
product,
|
||||||
|
currentBalance
|
||||||
|
}) => (
|
||||||
|
<TableRow
|
||||||
|
onClick={redirectToGiftCardUpdate(id)}
|
||||||
|
className={classes.row}
|
||||||
|
key={id}
|
||||||
|
>
|
||||||
|
<TableCell padding="checkbox">
|
||||||
|
<Checkbox
|
||||||
|
disableClickPropagation
|
||||||
|
checked={isSelected(id)}
|
||||||
|
onChange={() => toggle(id)}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className={classes.colCardCode}>
|
||||||
|
<div className={classes.cardCodeContainer}>
|
||||||
|
<Typography>
|
||||||
|
{intl.formatMessage(messages.codeEndingWithLabel, {
|
||||||
|
displayCode
|
||||||
|
})}
|
||||||
|
</Typography>
|
||||||
|
{!isActive && (
|
||||||
|
<>
|
||||||
|
<HorizontalSpacer spacing={2} />
|
||||||
|
<StatusChip
|
||||||
|
size="md"
|
||||||
|
status={StatusType.ERROR}
|
||||||
|
label={intl.formatMessage(
|
||||||
|
messages.giftCardDisabledLabel
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Typography>{tag || PLACEHOLDER}</Typography>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{product ? (
|
||||||
|
<Link onClick={() => navigate(productUrl(product?.id))}>
|
||||||
|
{product?.name}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
PLACEHOLDER
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{usedBy ? (
|
||||||
|
<Link onClick={() => navigate(customerUrl(usedBy?.id))}>
|
||||||
|
{`${usedBy?.firstName} ${usedBy?.lastName}`}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Typography noWrap>{usedByEmail || PLACEHOLDER}</Typography>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="right" className={classes.colBalance}>
|
||||||
|
<div className={classes.moneyContainer}>
|
||||||
|
<Typography variant="caption">
|
||||||
|
{currentBalance.currency}
|
||||||
|
</Typography>
|
||||||
|
<HorizontalSpacer spacing={0.5} />
|
||||||
|
<Typography>{currentBalance.amount}</Typography>
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className={classes.colDelete}>
|
||||||
|
<DeleteIconButton />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
),
|
||||||
|
() => (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={numberOfColumns}>
|
||||||
|
<Skeleton>
|
||||||
|
{!loading && (
|
||||||
|
<FormattedMessage {...messages.noGiftCardsFound} />
|
||||||
|
)}
|
||||||
|
</Skeleton>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</ResponsiveTable>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardsListTable;
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { TableFooter, TableRow } from "@material-ui/core";
|
||||||
|
import TablePagination from "@saleor/components/TablePagination";
|
||||||
|
import usePaginator from "@saleor/hooks/usePaginator";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import useGiftCardList from "../providers/hooks/useGiftCardList";
|
||||||
|
|
||||||
|
const GiftCardsListTableFooter: React.FC = () => {
|
||||||
|
const paginate = usePaginator();
|
||||||
|
|
||||||
|
const {
|
||||||
|
settings,
|
||||||
|
updateListSettings,
|
||||||
|
pageInfo: apiPageInfo,
|
||||||
|
paginationState,
|
||||||
|
params,
|
||||||
|
numberOfColumns
|
||||||
|
} = useGiftCardList();
|
||||||
|
|
||||||
|
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
||||||
|
apiPageInfo,
|
||||||
|
paginationState,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableFooter>
|
||||||
|
<TableRow>
|
||||||
|
<TablePagination
|
||||||
|
settings={settings}
|
||||||
|
colSpan={numberOfColumns}
|
||||||
|
hasNextPage={pageInfo ? pageInfo.hasNextPage : false}
|
||||||
|
onNextPage={loadNextPage}
|
||||||
|
onUpdateListSettings={updateListSettings}
|
||||||
|
onPreviousPage={loadPreviousPage}
|
||||||
|
hasPreviousPage={pageInfo ? pageInfo.hasPreviousPage : false}
|
||||||
|
/>
|
||||||
|
</TableRow>
|
||||||
|
</TableFooter>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardsListTableFooter;
|
|
@ -0,0 +1,83 @@
|
||||||
|
import { TableCell } from "@material-ui/core";
|
||||||
|
import TableCellHeader, {
|
||||||
|
TableCellHeaderProps
|
||||||
|
} from "@saleor/components/TableCellHeader";
|
||||||
|
import TableHead from "@saleor/components/TableHead";
|
||||||
|
import Label, {
|
||||||
|
LabelSizes
|
||||||
|
} from "@saleor/orders/components/OrderHistory/Label";
|
||||||
|
import React from "react";
|
||||||
|
import { MessageDescriptor, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { giftCardsListTableMessages as messages } from "../messages";
|
||||||
|
import useGiftCardList from "../providers/hooks/useGiftCardList";
|
||||||
|
import useGiftCardListBulkActions from "../providers/hooks/useGiftCardListBulkActions";
|
||||||
|
import { useTableStyles as useStyles } from "../styles";
|
||||||
|
|
||||||
|
interface HeaderItem {
|
||||||
|
title?: MessageDescriptor;
|
||||||
|
options?: TableCellHeaderProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GiftCardsListTableHeader: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const classes = useStyles({});
|
||||||
|
const { giftCards, numberOfColumns, loading } = useGiftCardList();
|
||||||
|
const { toggleAll, listElements } = useGiftCardListBulkActions();
|
||||||
|
|
||||||
|
const headerItems: HeaderItem[] = [
|
||||||
|
{
|
||||||
|
title: messages.giftCardsTableColumnGiftCardTitle,
|
||||||
|
options: {
|
||||||
|
className: classes.colCardCode,
|
||||||
|
textAlign: "left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: messages.giftCardsTableColumnTagTitle
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: messages.giftCardsTableColumnProductTitle
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: messages.giftCardsTableColumnCustomerTitle
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: messages.giftCardsTableColumnBalanceTitle,
|
||||||
|
options: {
|
||||||
|
className: classes.colBalance,
|
||||||
|
textAlign: "right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<colgroup>
|
||||||
|
<col />
|
||||||
|
<col className={classes.colCardCode} />
|
||||||
|
<col className={classes.colBase} />
|
||||||
|
<col className={classes.colBase} />
|
||||||
|
<col className={classes.colBase} />
|
||||||
|
<col className={classes.colBalance} />
|
||||||
|
<col className={classes.colDelete} />
|
||||||
|
</colgroup>
|
||||||
|
<TableHead
|
||||||
|
disabled={loading}
|
||||||
|
colSpan={numberOfColumns}
|
||||||
|
selected={listElements.length}
|
||||||
|
items={giftCards}
|
||||||
|
toggleAll={toggleAll}
|
||||||
|
>
|
||||||
|
{headerItems.map(({ title, options }) => (
|
||||||
|
<TableCellHeader {...options}>
|
||||||
|
<Label text={intl.formatMessage(title)} size={LabelSizes.md} />
|
||||||
|
</TableCellHeader>
|
||||||
|
))}
|
||||||
|
<TableCell className={classes.colDelete} />
|
||||||
|
</TableHead>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GiftCardsListTableHeader;
|
2
src/giftCards/GiftCardsList/GiftCardsListTable/index.tsx
Normal file
2
src/giftCards/GiftCardsList/GiftCardsListTable/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardsListTable";
|
||||||
|
export { default } from "./GiftCardsListTable";
|
2
src/giftCards/GiftCardsList/index.tsx
Normal file
2
src/giftCards/GiftCardsList/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./GiftCardsList";
|
||||||
|
export { default } from "./GiftCardsList";
|
55
src/giftCards/GiftCardsList/messages.ts
Normal file
55
src/giftCards/GiftCardsList/messages.ts
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const giftCardsListHeaderMenuItemsMessages = defineMessages({
|
||||||
|
settings: {
|
||||||
|
defaultMessage: "Settings",
|
||||||
|
description: "GiftCardsListHeader menu item settings"
|
||||||
|
},
|
||||||
|
bulkIssue: {
|
||||||
|
defaultMessage: "Bulk Issue",
|
||||||
|
description: "GiftCardsListHeader menu item settings"
|
||||||
|
},
|
||||||
|
exportCodes: {
|
||||||
|
defaultMessage: "Export card codes",
|
||||||
|
description: "GiftCardsListHeader menu item settings"
|
||||||
|
},
|
||||||
|
issueButtonLabel: {
|
||||||
|
defaultMessage: "Issue card",
|
||||||
|
description: "GiftCardsListHeader issue button label"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const giftCardsListTableMessages = defineMessages({
|
||||||
|
giftCardsTableColumnGiftCardTitle: {
|
||||||
|
defaultMessage: "Gift Card",
|
||||||
|
description: "GiftCardsListTable column title gift card"
|
||||||
|
},
|
||||||
|
giftCardsTableColumnTagTitle: {
|
||||||
|
defaultMessage: "Tag",
|
||||||
|
description: "GiftCardsListTable column title tag"
|
||||||
|
},
|
||||||
|
giftCardsTableColumnProductTitle: {
|
||||||
|
defaultMessage: "Product",
|
||||||
|
description: "GiftCardsListTable column title product"
|
||||||
|
},
|
||||||
|
giftCardsTableColumnCustomerTitle: {
|
||||||
|
defaultMessage: "Used by",
|
||||||
|
description: "GiftCardsListTable column title customer"
|
||||||
|
},
|
||||||
|
giftCardsTableColumnBalanceTitle: {
|
||||||
|
defaultMessage: "Balance",
|
||||||
|
description: "GiftCardsListTable column title balance"
|
||||||
|
},
|
||||||
|
codeEndingWithLabel: {
|
||||||
|
defaultMessage: "Code ending with {displayCode}",
|
||||||
|
description: "GiftCardsListTable code ending with label"
|
||||||
|
},
|
||||||
|
giftCardDisabledLabel: {
|
||||||
|
defaultMessage: "Disabled",
|
||||||
|
description: "GiftCardsListTable disabled label"
|
||||||
|
},
|
||||||
|
noGiftCardsFound: {
|
||||||
|
defaultMessage: "No gift cards found",
|
||||||
|
description: "GiftCardsListTable no cards found title"
|
||||||
|
}
|
||||||
|
});
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue