Add zip code exclusion (#877)
* Clean up stories * Add missing props * Add zip codes section (#861) * Add zip code listing * Add list wrapping * Update snapshots * Set up API data * Fix lgtm warning * Update snapshots * Run Actions on all PR * Checks on PR * Test envs on PR * Cleanup action on PR * Update messages Co-authored-by: Krzysztof Wolski <krzysztof.k.wolski@gmail.com> * Add zip code range dialog * Fix path management * Use query params to handle modal actions * Allow zip codes to be assigned to shipping method * Make params optional * Fix types * Add zip code deletion (#871) * Add zip code range dialog * Fix path management * Use query params to handle modal actions * Allow zip codes to be assigned to shipping method * Make params optional * Fix types * Clean up urls * Add zip code range delete action * Update snapshots and messages * Update testing and changelog * Update schema * Simplify code * Refresh zip code list after assigning them * Update view after zip code deletion * Update types and snapshots * Update snapshots * Fix error message, checkbox default value (#880) * Fix error message, checkbox default value * Update snapshots * Use price instead of weight variant * Update schema and types * Hide exclude/include zip codes section * Update stories Co-authored-by: Krzysztof Wolski <krzysztof.k.wolski@gmail.com> Co-authored-by: Tomasz Szymański <lime129@gmail.com>
This commit is contained in:
parent
eb351b396a
commit
e55805a79d
41 changed files with 6588 additions and 2979 deletions
1
.github/workflows/test-env-cleanup.yml
vendored
1
.github/workflows/test-env-cleanup.yml
vendored
|
@ -4,7 +4,6 @@ name: TEST-ENV-CLEANUP
|
|||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
branches: ["*"]
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
|
|
6
.github/workflows/test-env-deploy.yml
vendored
6
.github/workflows/test-env-deploy.yml
vendored
|
@ -1,11 +1,7 @@
|
|||
name: TEST-ENV-DEPLOYMENT
|
||||
# Build and deploy test instance for every pull request
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
# trigger on "edited" to update instance when configuration changes in PR description
|
||||
types: [opened, reopened, synchronize]
|
||||
branches: ["*"]
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
|
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
|
@ -1,8 +1,6 @@
|
|||
name: QA
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ["*"]
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
check-lock:
|
||||
|
|
|
@ -8,6 +8,7 @@ All notable, unreleased changes to this project will be documented in this file.
|
|||
- Add Page Types - #807 by @orzechdev
|
||||
- Add shipping methods to translation section - #864 by @marekchoinski
|
||||
- New Miscellaneous and Product refunds - #870 by @orzechdev
|
||||
- Add zip code exclusion - #877 by @dominik-zeglen
|
||||
|
||||
# 2.11.1
|
||||
|
||||
|
|
|
@ -5292,9 +5292,9 @@
|
|||
"context": "channels discount info",
|
||||
"string": "Channels that don’t have assigned discounts will use their parent channel to define the price. Price will be converted to channel’s currency"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_OrderValue_dot_2946165345": {
|
||||
"src_dot_shipping_dot_components_dot_OrderValue_dot_3989471564": {
|
||||
"context": "card title",
|
||||
"string": "Order value"
|
||||
"string": "Order Value"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_OrderValue_dot_4226393146": {
|
||||
"context": "price rates info",
|
||||
|
@ -5319,13 +5319,13 @@
|
|||
"context": "info text",
|
||||
"string": "This rate will apply to all orders"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_OrderWeight_dot_2211490913": {
|
||||
"context": "card title",
|
||||
"string": "Order Weight"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_OrderWeight_dot_2935375344": {
|
||||
"string": "Min. Order Weight"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_OrderWeight_dot_3721863048": {
|
||||
"context": "card title",
|
||||
"string": "Order weight"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_OrderWeight_dot_882649212": {
|
||||
"context": "checkbox label",
|
||||
"string": "There are no value limits"
|
||||
|
@ -5349,6 +5349,13 @@
|
|||
"context": "column title",
|
||||
"string": "Channel name"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingRateZipCodeRangeRemoveDialog_dot_1083561409": {
|
||||
"string": "Are you sure you want to remove this ZIP-code rule?"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingRateZipCodeRangeRemoveDialog_dot_2944856644": {
|
||||
"context": "header",
|
||||
"string": "Remove ZIP-codes from Shipping Rate"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingWeightUnitForm_dot_2863708228": {
|
||||
"string": "This unit will be used as default shipping weight"
|
||||
},
|
||||
|
@ -5477,6 +5484,54 @@
|
|||
"context": "input placeholder",
|
||||
"string": "Select Warehouse"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodeRangeDialog_dot_1938537617": {
|
||||
"string": "Please provide range of ZIP codes you want to add to the include/exclude list."
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodeRangeDialog_dot_3099331554": {
|
||||
"context": "add zip code range, button",
|
||||
"string": "Add"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodeRangeDialog_dot_3529644799": {
|
||||
"context": "range input label",
|
||||
"string": "Zip Codes (Start)"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodeRangeDialog_dot_4196919717": {
|
||||
"context": "dialog header",
|
||||
"string": "Add ZIP-Codes"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodeRangeDialog_dot_551327109": {
|
||||
"context": "range input label",
|
||||
"string": "Zip Codes (End)"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodes_dot_1462092303": {
|
||||
"string": "Added ZIP-codes will be excluded from using this delivery methods. If none are added all ZIP-Codes will be able to use that shipping rate"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodes_dot_1605967697": {
|
||||
"context": "action",
|
||||
"string": "Exclude ZIP-codes"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodes_dot_2728850129": {
|
||||
"string": "Only added ZIP-codes will be able to use this shipping rate"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodes_dot_2850315665": {
|
||||
"context": "number of zip code ranges",
|
||||
"string": "{number} ZIP-Code ranges"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodes_dot_3795380518": {
|
||||
"context": "button",
|
||||
"string": "Add ZIP-Code range"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodes_dot_4288715411": {
|
||||
"string": "This shipping rate has no ZIP-codes assigned"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodes_dot_529495587": {
|
||||
"context": "postal codes, header",
|
||||
"string": "ZIP-Codes"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZoneZipCodes_dot_671838332": {
|
||||
"context": "action",
|
||||
"string": "Include ZIP-codes"
|
||||
},
|
||||
"src_dot_shipping_dot_components_dot_ShippingZonesListPage_dot_1325966144": {
|
||||
"context": "header",
|
||||
"string": "Shipping"
|
||||
|
@ -5525,6 +5580,10 @@
|
|||
"src_dot_shipping_dot_views_dot_PriceRatesCreate_dot_3823295269": {
|
||||
"string": "Manage Channel Availability"
|
||||
},
|
||||
"src_dot_shipping_dot_views_dot_PriceRatesUpdate_dot_2710215007": {
|
||||
"context": "zip code range add error text",
|
||||
"string": "Cannot add specified zip codes range."
|
||||
},
|
||||
"src_dot_shipping_dot_views_dot_PriceRatesUpdate_dot_3823295269": {
|
||||
"string": "Manage Channel Availability"
|
||||
},
|
||||
|
@ -5543,6 +5602,10 @@
|
|||
"src_dot_shipping_dot_views_dot_WeightRatesCreate_dot_3014453080": {
|
||||
"string": "Manage Channels Availability"
|
||||
},
|
||||
"src_dot_shipping_dot_views_dot_WeightRatesUpdate_dot_2710215007": {
|
||||
"context": "zip code range add error text",
|
||||
"string": "Cannot add specified zip codes range."
|
||||
},
|
||||
"src_dot_shipping_dot_views_dot_WeightRatesUpdate_dot_3014453080": {
|
||||
"string": "Manage Channels Availability"
|
||||
},
|
||||
|
|
|
@ -2565,11 +2565,15 @@ type Mutation {
|
|||
shopAddressUpdate(input: AddressInput): ShopAddressUpdate
|
||||
orderSettingsUpdate(input: OrderSettingsUpdateInput!): OrderSettingsUpdate
|
||||
shippingMethodChannelListingUpdate(id: ID!, input: ShippingMethodChannelListingInput!): ShippingMethodChannelListingUpdate
|
||||
shippingMethodZipCodeRulesCreate(input: ShippingZipCodeRulesCreateInput!, shippingMethodId: ID!): ShippingZipCodeRulesCreate
|
||||
shippingMethodZipCodeRulesDelete(id: ID!): ShippingZipCodeRulesDelete
|
||||
shippingPriceCreate(input: ShippingPriceInput!): ShippingPriceCreate
|
||||
shippingPriceDelete(id: ID!): ShippingPriceDelete
|
||||
shippingPriceBulkDelete(ids: [ID]!): ShippingPriceBulkDelete
|
||||
shippingPriceUpdate(id: ID!, input: ShippingPriceInput!): ShippingPriceUpdate
|
||||
shippingPriceTranslate(id: ID!, input: NameTranslationInput!, languageCode: LanguageCodeEnum!): ShippingPriceTranslate
|
||||
shippingPriceExcludeProducts(id: ID!, input: ShippingPriceExcludeProductsInput!): ShippingPriceExcludeProducts
|
||||
shippingPriceRemoveProductFromExclude(id: ID!, products: [ID]!): ShippingPriceRemoveProductFromExclude
|
||||
shippingZoneCreate(input: ShippingZoneCreateInput!): ShippingZoneCreate
|
||||
shippingZoneDelete(id: ID!): ShippingZoneDelete
|
||||
shippingZoneBulkDelete(ids: [ID]!): ShippingZoneBulkDelete
|
||||
|
@ -2856,7 +2860,6 @@ type Order implements Node & ObjectWithMetadata {
|
|||
totalBalance: Money!
|
||||
userEmail: String
|
||||
isShippingRequired: Boolean!
|
||||
linesAvailableForRefund: [OrderLineAvailableForRefund]!
|
||||
}
|
||||
|
||||
enum OrderAction {
|
||||
|
@ -3097,11 +3100,6 @@ type OrderLine implements Node {
|
|||
allocations: [Allocation!]
|
||||
}
|
||||
|
||||
type OrderLineAvailableForRefund {
|
||||
quantity: Int
|
||||
orderLine: OrderLine
|
||||
}
|
||||
|
||||
input OrderLineCreateInput {
|
||||
quantity: Int!
|
||||
variantId: ID!
|
||||
|
@ -3124,19 +3122,18 @@ type OrderRefund {
|
|||
}
|
||||
|
||||
input OrderRefundFulfillmentLineInput {
|
||||
fulfillmentLineId: ID
|
||||
fulfillmentLineId: ID!
|
||||
quantity: Int!
|
||||
}
|
||||
|
||||
input OrderRefundLineInput {
|
||||
orderLineId: ID
|
||||
orderLineId: ID!
|
||||
quantity: Int!
|
||||
}
|
||||
|
||||
input OrderRefundProductsInput {
|
||||
orderLines: [OrderRefundLineInput!]
|
||||
fulfillmentLines: [OrderRefundFulfillmentLineInput!]
|
||||
notifyCustomer: Boolean
|
||||
amountToRefund: PositiveDecimal
|
||||
includeShippingCosts: Boolean = false
|
||||
}
|
||||
|
@ -4656,6 +4653,8 @@ type ShippingMethod implements Node & ObjectWithMetadata {
|
|||
price: Money
|
||||
maximumOrderPrice: Money
|
||||
minimumOrderPrice: Money
|
||||
zipCodeRules: [ShippingMethodZipCodeRule]
|
||||
excludedProducts(before: String, after: String, first: Int, last: Int): ProductCountableConnection
|
||||
}
|
||||
|
||||
type ShippingMethodChannelListing implements Node {
|
||||
|
@ -4702,6 +4701,12 @@ enum ShippingMethodTypeEnum {
|
|||
WEIGHT
|
||||
}
|
||||
|
||||
type ShippingMethodZipCodeRule implements Node {
|
||||
start: String
|
||||
end: String
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type ShippingPriceBulkDelete {
|
||||
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
|
||||
count: Int!
|
||||
|
@ -4722,6 +4727,16 @@ type ShippingPriceDelete {
|
|||
shippingErrors: [ShippingError!]!
|
||||
}
|
||||
|
||||
type ShippingPriceExcludeProducts {
|
||||
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
|
||||
shippingMethod: ShippingMethod
|
||||
shippingErrors: [ShippingError!]!
|
||||
}
|
||||
|
||||
input ShippingPriceExcludeProductsInput {
|
||||
products: [ID]!
|
||||
}
|
||||
|
||||
input ShippingPriceInput {
|
||||
name: String
|
||||
minimumOrderWeight: WeightScalar
|
||||
|
@ -4730,6 +4745,12 @@ input ShippingPriceInput {
|
|||
shippingZone: ID
|
||||
}
|
||||
|
||||
type ShippingPriceRemoveProductFromExclude {
|
||||
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
|
||||
shippingMethod: ShippingMethod
|
||||
shippingErrors: [ShippingError!]!
|
||||
}
|
||||
|
||||
type ShippingPriceTranslate {
|
||||
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
|
||||
translationErrors: [TranslationError!]!
|
||||
|
@ -4743,6 +4764,29 @@ type ShippingPriceUpdate {
|
|||
shippingErrors: [ShippingError!]!
|
||||
}
|
||||
|
||||
type ShippingZipCodeRulesCreate {
|
||||
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
|
||||
zipCodeRules: [ShippingMethodZipCodeRule]
|
||||
shippingMethod: ShippingMethod
|
||||
shippingErrors: [ShippingError!]!
|
||||
}
|
||||
|
||||
input ShippingZipCodeRulesCreateInput {
|
||||
zipCodeRules: [ShippingZipCodeRulesCreateInputRange]!
|
||||
}
|
||||
|
||||
input ShippingZipCodeRulesCreateInputRange {
|
||||
start: String!
|
||||
end: String
|
||||
}
|
||||
|
||||
type ShippingZipCodeRulesDelete {
|
||||
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
|
||||
shippingMethod: ShippingMethod
|
||||
shippingErrors: [ShippingError!]!
|
||||
shippingMethodZipCodeRule: ShippingMethodZipCodeRule
|
||||
}
|
||||
|
||||
type ShippingZone implements Node & ObjectWithMetadata {
|
||||
id: ID!
|
||||
name: String!
|
||||
|
@ -4807,6 +4851,7 @@ input ShippingZoneUpdateInput {
|
|||
|
||||
type Shop {
|
||||
availablePaymentGateways(currency: String): [PaymentGateway!]!
|
||||
availableShippingMethods(channel: String!, address: AddressInput): [ShippingMethod]
|
||||
geolocalization: Geolocalization
|
||||
authorizationKeys: [AuthorizationKey]!
|
||||
countries(languageCode: LanguageCodeEnum): [CountryDisplay!]!
|
||||
|
|
|
@ -12,6 +12,11 @@ import { FormattedMessage } from "react-intl";
|
|||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
alignTop: {
|
||||
alignSelf: "baseline",
|
||||
position: "relative",
|
||||
top: -6
|
||||
},
|
||||
formLabel: {
|
||||
marginBottom: theme.spacing(1)
|
||||
},
|
||||
|
@ -51,6 +56,7 @@ export interface RadioGroupFieldChoice<
|
|||
}
|
||||
|
||||
interface RadioGroupFieldProps {
|
||||
alignTop?: boolean;
|
||||
choices: RadioGroupFieldChoice[];
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
|
@ -65,6 +71,7 @@ interface RadioGroupFieldProps {
|
|||
|
||||
export const RadioGroupField: React.FC<RadioGroupFieldProps> = props => {
|
||||
const {
|
||||
alignTop,
|
||||
className,
|
||||
disabled,
|
||||
error,
|
||||
|
@ -107,7 +114,14 @@ export const RadioGroupField: React.FC<RadioGroupFieldProps> = props => {
|
|||
[classes.radioLabel]: variant !== "inline",
|
||||
[classes.radioLabelInline]: variant === "inline"
|
||||
})}
|
||||
control={<Radio color="primary" />}
|
||||
control={
|
||||
<Radio
|
||||
className={classNames({
|
||||
[classes.alignTop]: alignTop
|
||||
})}
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label={choice.label}
|
||||
key={choice.value}
|
||||
/>
|
||||
|
|
|
@ -11,10 +11,22 @@ export const shippingZoneFragment = gql`
|
|||
name
|
||||
}
|
||||
`;
|
||||
|
||||
export const shippingMethodWithZipCodesFragment = gql`
|
||||
fragment ShippingMethodWithZipCodesFragment on ShippingMethod {
|
||||
id
|
||||
zipCodeRules {
|
||||
id
|
||||
start
|
||||
end
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const shippingMethodFragment = gql`
|
||||
${fragmentMoney}
|
||||
${shippingMethodWithZipCodesFragment}
|
||||
fragment ShippingMethodFragment on ShippingMethod {
|
||||
id
|
||||
...ShippingMethodWithZipCodesFragment
|
||||
minimumOrderWeight {
|
||||
unit
|
||||
value
|
||||
|
|
|
@ -8,6 +8,13 @@ import { WeightUnitsEnum, ShippingMethodTypeEnum } from "./../../types/globalTyp
|
|||
// GraphQL fragment: ShippingMethodFragment
|
||||
// ====================================================
|
||||
|
||||
export interface ShippingMethodFragment_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodFragment_minimumOrderWeight {
|
||||
__typename: "Weight";
|
||||
unit: WeightUnitsEnum;
|
||||
|
@ -57,6 +64,7 @@ export interface ShippingMethodFragment_channelListings {
|
|||
export interface ShippingMethodFragment {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (ShippingMethodFragment_zipCodeRules | null)[] | null;
|
||||
minimumOrderWeight: ShippingMethodFragment_minimumOrderWeight | null;
|
||||
maximumOrderWeight: ShippingMethodFragment_maximumOrderWeight | null;
|
||||
name: string;
|
||||
|
|
20
src/fragments/types/ShippingMethodWithZipCodesFragment.ts
Normal file
20
src/fragments/types/ShippingMethodWithZipCodesFragment.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
// ====================================================
|
||||
// GraphQL fragment: ShippingMethodWithZipCodesFragment
|
||||
// ====================================================
|
||||
|
||||
export interface ShippingMethodWithZipCodesFragment_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodWithZipCodesFragment {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (ShippingMethodWithZipCodesFragment_zipCodeRules | null)[] | null;
|
||||
}
|
|
@ -14,6 +14,13 @@ export interface ShippingZoneDetailsFragment_countries {
|
|||
country: string;
|
||||
}
|
||||
|
||||
export interface ShippingZoneDetailsFragment_shippingMethods_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface ShippingZoneDetailsFragment_shippingMethods_minimumOrderWeight {
|
||||
__typename: "Weight";
|
||||
unit: WeightUnitsEnum;
|
||||
|
@ -63,6 +70,7 @@ export interface ShippingZoneDetailsFragment_shippingMethods_channelListings {
|
|||
export interface ShippingZoneDetailsFragment_shippingMethods {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (ShippingZoneDetailsFragment_shippingMethods_zipCodeRules | null)[] | null;
|
||||
minimumOrderWeight: ShippingZoneDetailsFragment_shippingMethods_minimumOrderWeight | null;
|
||||
maximumOrderWeight: ShippingZoneDetailsFragment_shippingMethods_maximumOrderWeight | null;
|
||||
name: string;
|
||||
|
|
15
src/misc.ts
15
src/misc.ts
|
@ -264,15 +264,18 @@ export function getMutationState(
|
|||
interface SaleorMutationResult {
|
||||
errors?: UserError[];
|
||||
}
|
||||
export function getMutationErrors<
|
||||
TData extends Record<string, SaleorMutationResult>
|
||||
>(data: TData): UserError[] {
|
||||
return Object.values(data).reduce(
|
||||
(acc: UserError[], mut) => [...acc, ...maybe(() => mut.errors, [])],
|
||||
[]
|
||||
);
|
||||
}
|
||||
export function getMutationStatus<
|
||||
TData extends Record<string, SaleorMutationResult | any>
|
||||
>(opts: MutationResult<TData>): ConfirmButtonTransitionState {
|
||||
const errors = opts.data
|
||||
? Object.values(opts.data).reduce(
|
||||
(acc: UserError[], mut) => [...acc, ...maybe(() => mut.errors, [])],
|
||||
[]
|
||||
)
|
||||
: [];
|
||||
const errors = opts.data ? getMutationErrors(opts.data) : [];
|
||||
|
||||
return getMutationState(opts.called, opts.loading, errors);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ export const OrderValue: React.FC<OrderValueProps> = ({
|
|||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Order value",
|
||||
defaultMessage: "Order Value",
|
||||
description: "card title"
|
||||
})}
|
||||
/>
|
||||
|
|
|
@ -40,7 +40,7 @@ export const OrderWeight: React.FC<OrderWeightProps> = ({
|
|||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Order weight",
|
||||
defaultMessage: "Order Weight",
|
||||
description: "card title"
|
||||
})}
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import ActionDialog from "@saleor/components/ActionDialog";
|
||||
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
|
||||
import { DialogProps } from "@saleor/types";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
export interface ShippingRateZipCodeRangeRemoveDialogProps extends DialogProps {
|
||||
confirmButtonState: ConfirmButtonTransitionState;
|
||||
onConfirm: () => void;
|
||||
}
|
||||
|
||||
const ShippingRateZipCodeRangeRemoveDialog: React.FC<ShippingRateZipCodeRangeRemoveDialogProps> = ({
|
||||
confirmButtonState,
|
||||
open,
|
||||
onClose,
|
||||
onConfirm
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<ActionDialog
|
||||
confirmButtonState={confirmButtonState}
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
onConfirm={onConfirm}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Remove ZIP-codes from Shipping Rate",
|
||||
description: "header"
|
||||
})}
|
||||
variant="delete"
|
||||
>
|
||||
<DialogContentText>
|
||||
<FormattedMessage defaultMessage="Are you sure you want to remove this ZIP-code rule?" />
|
||||
</DialogContentText>
|
||||
</ActionDialog>
|
||||
);
|
||||
};
|
||||
|
||||
ShippingRateZipCodeRangeRemoveDialog.displayName =
|
||||
"ShippingRateZipCodeRangeRemoveDialog";
|
||||
export default ShippingRateZipCodeRangeRemoveDialog;
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./ShippingRateZipCodeRangeRemoveDialog";
|
||||
export { default } from "./ShippingRateZipCodeRangeRemoveDialog";
|
|
@ -47,37 +47,58 @@ const props: ShippingZoneRatesPageProps = {
|
|||
onChannelsChange: () => undefined,
|
||||
onDelete: () => undefined,
|
||||
onSubmit: () => undefined,
|
||||
onZipCodeAssign: () => undefined,
|
||||
onZipCodeUnassign: () => undefined,
|
||||
openChannelsModal: () => undefined,
|
||||
rate: null,
|
||||
saveButtonBarState: "default",
|
||||
shippingChannels: defaultChannels,
|
||||
variant: ShippingMethodTypeEnum.PRICE
|
||||
variant: ShippingMethodTypeEnum.PRICE,
|
||||
zipCodes: [
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: "51-200",
|
||||
id: "1",
|
||||
start: "51-220"
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: "31-101",
|
||||
id: "1",
|
||||
start: "44-205"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
storiesOf("Shipping / ShippingZoneRates page", module)
|
||||
storiesOf("Views / Shipping / Shipping rate", module)
|
||||
.addDecorator(Decorator)
|
||||
.add("default price", () => <ShippingZoneRatesPage {...props} />)
|
||||
.add("create price rate", () => <ShippingZoneRatesPage {...props} />)
|
||||
.add("create weight rate", () => (
|
||||
<ShippingZoneRatesPage {...props} variant={ShippingMethodTypeEnum.WEIGHT} />
|
||||
))
|
||||
.add("loading", () => (
|
||||
<ShippingZoneRatesPage
|
||||
{...props}
|
||||
disabled={true}
|
||||
rate={undefined}
|
||||
saveButtonBarState={"loading"}
|
||||
/>
|
||||
))
|
||||
.add("update price", () => (
|
||||
.add("update price rate", () => (
|
||||
<ShippingZoneRatesPage
|
||||
{...props}
|
||||
shippingChannels={channels}
|
||||
rate={shippingZone.shippingMethods[2]}
|
||||
/>
|
||||
))
|
||||
.add("default weight", () => (
|
||||
<ShippingZoneRatesPage {...props} variant={ShippingMethodTypeEnum.WEIGHT} />
|
||||
))
|
||||
.add("update weight", () => (
|
||||
.add("update weight rate", () => (
|
||||
<ShippingZoneRatesPage
|
||||
{...props}
|
||||
shippingChannels={channels}
|
||||
rate={shippingZone.shippingMethods[0]}
|
||||
variant={ShippingMethodTypeEnum.WEIGHT}
|
||||
/>
|
||||
))
|
||||
.add("no zip codes", () => (
|
||||
<ShippingZoneRatesPage {...props} zipCodes={[]} />
|
||||
));
|
||||
|
|
|
@ -10,19 +10,27 @@ import PageHeader from "@saleor/components/PageHeader";
|
|||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||
import { ShippingChannelsErrorFragment } from "@saleor/fragments/types/ShippingChannelsErrorFragment";
|
||||
import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment";
|
||||
import {
|
||||
ShippingMethodFragment,
|
||||
ShippingMethodFragment_zipCodeRules
|
||||
} from "@saleor/fragments/types/ShippingMethodFragment";
|
||||
import { validatePrice } from "@saleor/products/utils/validation";
|
||||
import OrderValue from "@saleor/shipping/components/OrderValue";
|
||||
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
||||
import PricingCard from "@saleor/shipping/components/PricingCard";
|
||||
import ShippingZoneInfo from "@saleor/shipping/components/ShippingZoneInfo";
|
||||
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
||||
import { ShippingZone_shippingZone_shippingMethods } from "@saleor/shipping/types/ShippingZone";
|
||||
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import ShippingZoneZipCodes, {
|
||||
ZipCodeInclusion
|
||||
} from "../ShippingZoneZipCodes";
|
||||
|
||||
export interface FormData {
|
||||
channelListings: ChannelShippingData[];
|
||||
includeZipCodes: ZipCodeInclusion;
|
||||
name: string;
|
||||
noLimits: boolean;
|
||||
minValue: string;
|
||||
|
@ -35,13 +43,16 @@ export interface ShippingZoneRatesPageProps {
|
|||
shippingChannels: ChannelShippingData[];
|
||||
disabled: boolean;
|
||||
hasChannelChanged?: boolean;
|
||||
rate?: ShippingZone_shippingZone_shippingMethods;
|
||||
rate: ShippingMethodFragment | null;
|
||||
zipCodes?: ShippingMethodFragment_zipCodeRules[];
|
||||
channelErrors: ShippingChannelsErrorFragment[];
|
||||
errors: ShippingErrorFragment[];
|
||||
saveButtonBarState: ConfirmButtonTransitionState;
|
||||
onBack: () => void;
|
||||
onDelete?: () => void;
|
||||
onSubmit: (data: FormData) => void;
|
||||
onZipCodeAssign: () => void;
|
||||
onZipCodeUnassign: (id: string) => void;
|
||||
onChannelsChange: (data: ChannelShippingData[]) => void;
|
||||
openChannelsModal: () => void;
|
||||
variant: ShippingMethodTypeEnum;
|
||||
|
@ -58,15 +69,19 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
|||
onDelete,
|
||||
onSubmit,
|
||||
onChannelsChange,
|
||||
onZipCodeAssign,
|
||||
onZipCodeUnassign,
|
||||
openChannelsModal,
|
||||
rate,
|
||||
saveButtonBarState,
|
||||
variant
|
||||
variant,
|
||||
zipCodes
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const isPriceVariant = variant === ShippingMethodTypeEnum.PRICE;
|
||||
const initialForm: FormData = {
|
||||
channelListings: shippingChannels,
|
||||
includeZipCodes: ZipCodeInclusion.Exclude,
|
||||
maxValue: rate?.maximumOrderWeight?.value.toString() || "",
|
||||
minValue: rate?.minimumOrderWeight?.value.toString() || "",
|
||||
name: rate?.name || "",
|
||||
|
@ -74,6 +89,8 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
|||
type: rate?.type || null
|
||||
};
|
||||
|
||||
const rateExists = rate !== null;
|
||||
|
||||
return (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged, submit, triggerChange }) => {
|
||||
|
@ -141,6 +158,14 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
|||
errors={channelErrors}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<ShippingZoneZipCodes
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
onZipCodeDelete={onZipCodeUnassign}
|
||||
onZipCodeInclusionChange={() => undefined}
|
||||
onZipCodeRangeAdd={onZipCodeAssign}
|
||||
zipCodes={rateExists ? rate?.zipCodeRules : zipCodes}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<ChannelsAvailability
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import Decorator from "@saleor/storybook/Decorator";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import React from "react";
|
||||
|
||||
import ShippingZoneZipCodeRangeDialog from "./ShippingZoneZipCodeRangeDialog";
|
||||
|
||||
storiesOf("Shipping / Add zip code range", module)
|
||||
.addDecorator(Decorator)
|
||||
.add("default", () => (
|
||||
<ShippingZoneZipCodeRangeDialog
|
||||
confirmButtonState="default"
|
||||
open={true}
|
||||
onClose={() => undefined}
|
||||
onSubmit={() => undefined}
|
||||
/>
|
||||
));
|
|
@ -0,0 +1,109 @@
|
|||
import Button from "@material-ui/core/Button";
|
||||
import Dialog from "@material-ui/core/Dialog";
|
||||
import DialogActions from "@material-ui/core/DialogActions";
|
||||
import DialogContent from "@material-ui/core/DialogContent";
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import ConfirmButton, {
|
||||
ConfirmButtonTransitionState
|
||||
} from "@saleor/components/ConfirmButton";
|
||||
import Form from "@saleor/components/Form";
|
||||
import Grid from "@saleor/components/Grid";
|
||||
import { buttonMessages, commonMessages } from "@saleor/intl";
|
||||
import { DialogProps, MinMax } from "@saleor/types";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
export interface ShippingZoneZipCodeRangeDialogProps extends DialogProps {
|
||||
confirmButtonState: ConfirmButtonTransitionState;
|
||||
onSubmit: (range: MinMax) => void;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
info: {
|
||||
marginBottom: theme.spacing(2)
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: "ShippingZoneZipCodeRangeDialog"
|
||||
}
|
||||
);
|
||||
|
||||
const ShippingZoneZipCodeRangeDialog: React.FC<ShippingZoneZipCodeRangeDialogProps> = ({
|
||||
confirmButtonState,
|
||||
open,
|
||||
onClose,
|
||||
onSubmit
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
const intl = useIntl();
|
||||
|
||||
const initial: MinMax = {
|
||||
max: "",
|
||||
min: ""
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open}>
|
||||
<DialogTitle>
|
||||
<FormattedMessage
|
||||
defaultMessage="Add ZIP-Codes"
|
||||
description="dialog header"
|
||||
/>
|
||||
</DialogTitle>
|
||||
<Form initial={initial} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged }) => (
|
||||
<>
|
||||
<DialogContent>
|
||||
<Typography className={classes.info}>
|
||||
<FormattedMessage defaultMessage="Please provide range of ZIP codes you want to add to the include/exclude list." />
|
||||
</Typography>
|
||||
<Grid variant="uniform">
|
||||
<TextField
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Zip Codes (Start)",
|
||||
description: "range input label"
|
||||
})}
|
||||
name="min"
|
||||
value={data.min}
|
||||
onChange={change}
|
||||
/>
|
||||
<TextField
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Zip Codes (End)",
|
||||
description: "range input label"
|
||||
})}
|
||||
name="max"
|
||||
helperText={intl.formatMessage(commonMessages.optionalField)}
|
||||
value={data.max}
|
||||
onChange={change}
|
||||
/>
|
||||
</Grid>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onClose}>
|
||||
<FormattedMessage {...buttonMessages.back} />
|
||||
</Button>
|
||||
<ConfirmButton
|
||||
disabled={!hasChanged || !data.min}
|
||||
transitionState={confirmButtonState}
|
||||
type="submit"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Add"
|
||||
description="add zip code range, button"
|
||||
/>
|
||||
</ConfirmButton>
|
||||
</DialogActions>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
ShippingZoneZipCodeRangeDialog.displayName = "ShippingZoneZipCodeRangeDialog";
|
||||
export default ShippingZoneZipCodeRangeDialog;
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./ShippingZoneZipCodeRangeDialog";
|
||||
export { default } from "./ShippingZoneZipCodeRangeDialog";
|
|
@ -0,0 +1,233 @@
|
|||
import Button from "@material-ui/core/Button";
|
||||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||
import TableBody from "@material-ui/core/TableBody";
|
||||
import TableCell from "@material-ui/core/TableCell";
|
||||
import TableHead from "@material-ui/core/TableHead";
|
||||
import TableRow from "@material-ui/core/TableRow";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import RadioGroupField from "@saleor/components/RadioGroupField";
|
||||
import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
||||
import Skeleton from "@saleor/components/Skeleton";
|
||||
import { ShippingMethodFragment_zipCodeRules } from "@saleor/fragments/types/ShippingMethodFragment";
|
||||
import { FormChange } from "@saleor/hooks/useForm";
|
||||
import ArrowDropdown from "@saleor/icons/ArrowDropdown";
|
||||
import { renderCollection } from "@saleor/misc";
|
||||
import classNames from "classnames";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
export enum ZipCodeInclusion {
|
||||
Include,
|
||||
Exclude
|
||||
}
|
||||
|
||||
export interface ShippingZoneZipCodesProps {
|
||||
data: Record<"includeZipCodes", ZipCodeInclusion>;
|
||||
disabled: boolean;
|
||||
initialExpanded?: boolean;
|
||||
zipCodes: ShippingMethodFragment_zipCodeRules[] | undefined;
|
||||
onZipCodeInclusionChange: FormChange;
|
||||
onZipCodeDelete: (id: string) => void;
|
||||
onZipCodeRangeAdd: () => void;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
arrow: {
|
||||
transition: theme.transitions.create("transform")
|
||||
},
|
||||
arrowRotate: {
|
||||
transform: "scale(-1)"
|
||||
},
|
||||
colAction: {
|
||||
width: 80
|
||||
},
|
||||
colCode: {},
|
||||
hide: {
|
||||
display: "none"
|
||||
},
|
||||
option: {
|
||||
marginBottom: theme.spacing(2),
|
||||
width: 400
|
||||
},
|
||||
radioContainer: {
|
||||
paddingBottom: 0
|
||||
},
|
||||
skeleton: {
|
||||
width: 80
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: "ShippingZoneZipCodes"
|
||||
}
|
||||
);
|
||||
|
||||
const ShippingZoneZipCodes: React.FC<ShippingZoneZipCodesProps> = ({
|
||||
data,
|
||||
disabled,
|
||||
initialExpanded,
|
||||
zipCodes,
|
||||
onZipCodeDelete,
|
||||
onZipCodeInclusionChange,
|
||||
onZipCodeRangeAdd
|
||||
}) => {
|
||||
const [expanded, setExpanded] = React.useState(initialExpanded);
|
||||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "ZIP-Codes",
|
||||
description: "postal codes, header"
|
||||
})}
|
||||
toolbar={
|
||||
<Button
|
||||
color="primary"
|
||||
onClick={onZipCodeRangeAdd}
|
||||
data-test="add-zip-code-range"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Add ZIP-Code range"
|
||||
description="button"
|
||||
/>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<CardContent className={classNames(classes.radioContainer, classes.hide)}>
|
||||
<RadioGroupField
|
||||
alignTop
|
||||
choices={[
|
||||
{
|
||||
disabled: true,
|
||||
label: (
|
||||
<div className={classes.option}>
|
||||
<Typography color="textSecondary" variant="body1">
|
||||
<FormattedMessage
|
||||
defaultMessage="Exclude ZIP-codes"
|
||||
description="action"
|
||||
/>
|
||||
</Typography>
|
||||
<Typography color="textSecondary" variant="caption">
|
||||
<FormattedMessage defaultMessage="Added ZIP-codes will be excluded from using this delivery methods. If none are added all ZIP-Codes will be able to use that shipping rate" />
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
value: ZipCodeInclusion.Exclude
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<div className={classes.option}>
|
||||
<Typography variant="body1">
|
||||
<FormattedMessage
|
||||
defaultMessage="Include ZIP-codes"
|
||||
description="action"
|
||||
/>
|
||||
</Typography>
|
||||
<Typography color="textSecondary" variant="caption">
|
||||
<FormattedMessage defaultMessage="Only added ZIP-codes will be able to use this shipping rate" />
|
||||
</Typography>
|
||||
</div>
|
||||
),
|
||||
value: ZipCodeInclusion.Include
|
||||
}
|
||||
]}
|
||||
name="includeZipCodes"
|
||||
value={data.includeZipCodes}
|
||||
onChange={onZipCodeInclusionChange}
|
||||
/>
|
||||
</CardContent>
|
||||
<ResponsiveTable>
|
||||
<colgroup>
|
||||
<col />
|
||||
<col className={classes.colAction} />
|
||||
</colgroup>
|
||||
{zipCodes === undefined ||
|
||||
(zipCodes.length > 0 && (
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
{zipCodes === undefined ? (
|
||||
<Skeleton className={classes.skeleton} />
|
||||
) : (
|
||||
<Typography variant="caption">
|
||||
<FormattedMessage
|
||||
defaultMessage="{number} ZIP-Code ranges"
|
||||
description="number of zip code ranges"
|
||||
values={{
|
||||
number: zipCodes.length
|
||||
}}
|
||||
/>
|
||||
</Typography>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<IconButton onClick={() => setExpanded(!expanded)}>
|
||||
<ArrowDropdown
|
||||
className={classNames(classes.arrow, {
|
||||
[classes.arrowRotate]: expanded
|
||||
})}
|
||||
/>
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
))}
|
||||
{expanded && (
|
||||
<TableBody>
|
||||
{renderCollection(
|
||||
zipCodes,
|
||||
zipCodeRange => (
|
||||
<TableRow key={zipCodeRange?.id}>
|
||||
<TableCell>
|
||||
{zipCodeRange?.start ? (
|
||||
zipCodeRange?.end ? (
|
||||
`${zipCodeRange.start} - ${zipCodeRange.end}`
|
||||
) : (
|
||||
zipCodeRange.start
|
||||
)
|
||||
) : (
|
||||
<Skeleton />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<IconButton
|
||||
disabled={disabled}
|
||||
color="primary"
|
||||
onClick={() => onZipCodeDelete(zipCodeRange.id)}
|
||||
data-test="delete-zip-code"
|
||||
data-test-id={zipCodeRange?.id}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
),
|
||||
() => (
|
||||
<TableRow>
|
||||
<TableCell colSpan={2}>
|
||||
<Typography color="textSecondary">
|
||||
<FormattedMessage defaultMessage="This shipping rate has no ZIP-codes assigned" />
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
)}
|
||||
</TableBody>
|
||||
)}
|
||||
</ResponsiveTable>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
ShippingZoneZipCodes.displayName = "ShippingZoneZipCodes";
|
||||
ShippingZoneZipCodes.defaultProps = {
|
||||
initialExpanded: true
|
||||
};
|
||||
export default ShippingZoneZipCodes;
|
2
src/shipping/components/ShippingZoneZipCodes/index.ts
Normal file
2
src/shipping/components/ShippingZoneZipCodes/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export * from "./ShippingZoneZipCodes";
|
||||
export { default } from "./ShippingZoneZipCodes";
|
|
@ -1589,7 +1589,27 @@ export const shippingZone: ShippingZoneDetailsFragment = {
|
|||
value: 0
|
||||
},
|
||||
name: "DB Schenker",
|
||||
type: ShippingMethodTypeEnum.WEIGHT
|
||||
type: ShippingMethodTypeEnum.WEIGHT,
|
||||
zipCodeRules: [
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: "51-220",
|
||||
id: "1",
|
||||
start: "51-210"
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: "51-240",
|
||||
id: "2",
|
||||
start: "51-235"
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: null,
|
||||
id: "2",
|
||||
start: "51-274"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethod",
|
||||
|
@ -1602,7 +1622,27 @@ export const shippingZone: ShippingZoneDetailsFragment = {
|
|||
value: 0
|
||||
},
|
||||
name: "Registred priority",
|
||||
type: ShippingMethodTypeEnum.WEIGHT
|
||||
type: ShippingMethodTypeEnum.WEIGHT,
|
||||
zipCodeRules: [
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: "51-220",
|
||||
id: "1",
|
||||
start: "51-210"
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: "51-240",
|
||||
id: "2",
|
||||
start: "51-235"
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: null,
|
||||
id: "2",
|
||||
start: "51-274"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethod",
|
||||
|
@ -1614,9 +1654,28 @@ export const shippingZone: ShippingZoneDetailsFragment = {
|
|||
unit: WeightUnitsEnum.KG,
|
||||
value: 0
|
||||
},
|
||||
|
||||
name: "UPS",
|
||||
type: ShippingMethodTypeEnum.PRICE
|
||||
type: ShippingMethodTypeEnum.PRICE,
|
||||
zipCodeRules: [
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: "51-220",
|
||||
id: "1",
|
||||
start: "51-210"
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: "51-240",
|
||||
id: "2",
|
||||
start: "51-235"
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: null,
|
||||
id: "2",
|
||||
start: "51-274"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethod",
|
||||
|
@ -1629,7 +1688,27 @@ export const shippingZone: ShippingZoneDetailsFragment = {
|
|||
value: 0
|
||||
},
|
||||
name: "DHL",
|
||||
type: ShippingMethodTypeEnum.PRICE
|
||||
type: ShippingMethodTypeEnum.PRICE,
|
||||
zipCodeRules: [
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: "51-220",
|
||||
id: "1",
|
||||
start: "51-210"
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: "51-240",
|
||||
id: "2",
|
||||
start: "51-235"
|
||||
},
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: null,
|
||||
id: "2",
|
||||
start: "51-274"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
warehouses: [
|
||||
|
|
|
@ -1,10 +1,24 @@
|
|||
import { ChannelShippingData } from "@saleor/channels/utils";
|
||||
import { ShippingMethodFragment_zipCodeRules } from "@saleor/fragments/types/ShippingMethodFragment";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { getMutationErrors, getMutationState } from "@saleor/misc";
|
||||
import { FormData as ShippingZoneRatesPageFormData } from "@saleor/shipping/components/ShippingZoneRatesPage";
|
||||
import { CreateShippingRateVariables } from "@saleor/shipping/types/CreateShippingRate";
|
||||
import { ShippingMethodChannelListingUpdateVariables } from "@saleor/shipping/types/ShippingMethodChannelListingUpdate";
|
||||
import { UpdateShippingRateVariables } from "@saleor/shipping/types/UpdateShippingRate";
|
||||
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||
import { diff } from "fast-array-diff";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import {
|
||||
useShippingMethodChannelListingUpdate,
|
||||
useShippingMethodZipCodeRangeAssign,
|
||||
useShippingRateCreate,
|
||||
useShippingRateDelete
|
||||
} from "./mutations";
|
||||
import { shippingPriceRatesEditUrl, shippingWeightRatesEditUrl } from "./urls";
|
||||
|
||||
export const createChannelsChangeHandler = (
|
||||
selectedChannels: ChannelShippingData[],
|
||||
|
@ -122,3 +136,109 @@ export function getShippingMethodChannelVariables(
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function useShippingRateCreator(
|
||||
shippingZoneId: string,
|
||||
type: ShippingMethodTypeEnum,
|
||||
zipCodes: ShippingMethodFragment_zipCodeRules[]
|
||||
) {
|
||||
const intl = useIntl();
|
||||
const notify = useNotifier();
|
||||
const navigate = useNavigator();
|
||||
const [
|
||||
createBaseShippingRate,
|
||||
createBaseShippingRateOpts
|
||||
] = useShippingRateCreate({});
|
||||
const [
|
||||
assignZipCodeRules,
|
||||
assignZipCodeRulesOpts
|
||||
] = useShippingMethodZipCodeRangeAssign({});
|
||||
const [
|
||||
updateShippingMethodChannelListing,
|
||||
updateShippingMethodChannelListingOpts
|
||||
] = useShippingMethodChannelListingUpdate({});
|
||||
const [deleteShippingRate] = useShippingRateDelete({});
|
||||
|
||||
const getVariables =
|
||||
type === ShippingMethodTypeEnum.PRICE
|
||||
? getCreateShippingPriceRateVariables
|
||||
: getCreateShippingWeightRateVariables;
|
||||
const getUrl =
|
||||
type === ShippingMethodTypeEnum.PRICE
|
||||
? shippingPriceRatesEditUrl
|
||||
: shippingWeightRatesEditUrl;
|
||||
|
||||
const createShippingRate = async (data: ShippingZoneRatesPageFormData) => {
|
||||
const response = await createBaseShippingRate({
|
||||
variables: getVariables(data, shippingZoneId)
|
||||
});
|
||||
|
||||
const createErrors = response.data.shippingPriceCreate.errors;
|
||||
if (createErrors.length === 0) {
|
||||
const rateId = response.data.shippingPriceCreate.shippingMethod.id;
|
||||
|
||||
const mutationResults = await Promise.all([
|
||||
updateShippingMethodChannelListing({
|
||||
variables: getShippingMethodChannelVariables(
|
||||
rateId,
|
||||
data.noLimits,
|
||||
data.channelListings
|
||||
)
|
||||
}),
|
||||
assignZipCodeRules({
|
||||
variables: {
|
||||
id: rateId,
|
||||
input: {
|
||||
zipCodeRules: zipCodes.map(zipCodeRule => ({
|
||||
end: zipCodeRule.end || null,
|
||||
start: zipCodeRule.start
|
||||
}))
|
||||
}
|
||||
}
|
||||
})
|
||||
]);
|
||||
|
||||
if (
|
||||
mutationResults.find(
|
||||
result => getMutationErrors(result.data as any).length > 0
|
||||
)
|
||||
) {
|
||||
deleteShippingRate({
|
||||
variables: {
|
||||
id: rateId
|
||||
}
|
||||
});
|
||||
} else {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
});
|
||||
navigate(getUrl(shippingZoneId, rateId));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const called =
|
||||
createBaseShippingRateOpts.called ||
|
||||
updateShippingMethodChannelListingOpts.called ||
|
||||
assignZipCodeRulesOpts.called;
|
||||
const loading =
|
||||
createBaseShippingRateOpts.loading ||
|
||||
updateShippingMethodChannelListingOpts.loading ||
|
||||
assignZipCodeRulesOpts.loading;
|
||||
const errors = [
|
||||
...(createBaseShippingRateOpts.data?.shippingPriceCreate.errors || []),
|
||||
...(assignZipCodeRulesOpts.data?.shippingMethodZipCodeRulesCreate.errors ||
|
||||
[])
|
||||
];
|
||||
const channelErrors =
|
||||
updateShippingMethodChannelListingOpts.data
|
||||
?.shippingMethodChannelListingUpdate.errors || [];
|
||||
|
||||
return {
|
||||
channelErrors,
|
||||
createShippingRate,
|
||||
errors,
|
||||
status: getMutationState(called, loading, [...errors, ...channelErrors])
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,10 +6,12 @@ import { Route, RouteComponentProps, Switch } from "react-router-dom";
|
|||
|
||||
import { WindowTitle } from "../components/WindowTitle";
|
||||
import {
|
||||
shippingPriceRatesEditUrl,
|
||||
shippingPriceRatesUrl,
|
||||
shippingWeightRatesEditUrl,
|
||||
shippingWeightRatesUrl,
|
||||
shippingPriceRatesEditPath,
|
||||
shippingPriceRatesPath,
|
||||
ShippingRateCreateUrlQueryParams,
|
||||
ShippingRateUrlQueryParams,
|
||||
shippingWeightRatesEditPath,
|
||||
shippingWeightRatesPath,
|
||||
shippingZoneAddPath,
|
||||
shippingZonePath,
|
||||
shippingZonesListPath,
|
||||
|
@ -48,31 +50,63 @@ const ShippingZoneDetails: React.FC<RouteComponentProps<
|
|||
|
||||
const PriceRatesCreate: React.FC<RouteComponentProps<{ id: string }>> = ({
|
||||
match
|
||||
}) => <PriceRatesCreateComponent id={decodeURIComponent(match.params.id)} />;
|
||||
}) => {
|
||||
const qs = parseQs(location.search.substr(1));
|
||||
const params: ShippingRateCreateUrlQueryParams = qs;
|
||||
|
||||
return (
|
||||
<PriceRatesCreateComponent
|
||||
id={decodeURIComponent(match.params.id)}
|
||||
params={params}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const WeightRatesCreate: React.FC<RouteComponentProps<{ id: string }>> = ({
|
||||
match
|
||||
}) => <WeightRatesCreateComponent id={decodeURIComponent(match.params.id)} />;
|
||||
}) => {
|
||||
const qs = parseQs(location.search.substr(1));
|
||||
const params: ShippingRateCreateUrlQueryParams = qs;
|
||||
|
||||
return (
|
||||
<WeightRatesCreateComponent
|
||||
id={decodeURIComponent(match.params.id)}
|
||||
params={params}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const WeightRatesUpdate: React.FC<RouteComponentProps<{
|
||||
id: string;
|
||||
rateId: string;
|
||||
}>> = ({ match }) => (
|
||||
}>> = ({ match }) => {
|
||||
const qs = parseQs(location.search.substr(1));
|
||||
const params: ShippingRateUrlQueryParams = qs;
|
||||
|
||||
return (
|
||||
<WeightRatesUpdateComponent
|
||||
id={decodeURIComponent(match.params.id)}
|
||||
rateId={decodeURIComponent(match.params.rateId)}
|
||||
params={params}
|
||||
/>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
const PriceRatesUpdate: React.FC<RouteComponentProps<{
|
||||
id: string;
|
||||
rateId: string;
|
||||
}>> = ({ match }) => (
|
||||
}>> = ({ match }) => {
|
||||
const qs = parseQs(location.search.substr(1));
|
||||
const params: ShippingRateUrlQueryParams = qs;
|
||||
|
||||
return (
|
||||
<PriceRatesUpdateComponent
|
||||
id={decodeURIComponent(match.params.id)}
|
||||
rateId={decodeURIComponent(match.params.rateId)}
|
||||
params={params}
|
||||
/>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
export const ShippingRouter: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
|
@ -97,19 +131,19 @@ export const ShippingRouter: React.FC = () => {
|
|||
component={ShippingZoneDetails}
|
||||
/>
|
||||
<Route
|
||||
path={shippingPriceRatesUrl(":id")}
|
||||
path={shippingPriceRatesPath(":id")}
|
||||
component={PriceRatesCreate}
|
||||
/>
|
||||
<Route
|
||||
path={shippingWeightRatesUrl(":id")}
|
||||
path={shippingWeightRatesPath(":id")}
|
||||
component={WeightRatesCreate}
|
||||
/>
|
||||
<Route
|
||||
path={shippingWeightRatesEditUrl(":id", ":rateId")}
|
||||
path={shippingWeightRatesEditPath(":id", ":rateId")}
|
||||
component={WeightRatesUpdate}
|
||||
/>
|
||||
<Route
|
||||
path={shippingPriceRatesEditUrl(":id", ":rateId")}
|
||||
path={shippingPriceRatesEditPath(":id", ":rateId")}
|
||||
component={PriceRatesUpdate}
|
||||
/>
|
||||
</Switch>
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
} from "@saleor/fragments/errors";
|
||||
import {
|
||||
shippingMethodFragment,
|
||||
shippingMethodWithZipCodesFragment,
|
||||
shippingZoneDetailsFragment
|
||||
} from "@saleor/fragments/shipping";
|
||||
import { countryFragment } from "@saleor/fragments/taxes";
|
||||
|
@ -38,6 +39,14 @@ import {
|
|||
ShippingMethodChannelListingUpdate,
|
||||
ShippingMethodChannelListingUpdateVariables
|
||||
} from "./types/ShippingMethodChannelListingUpdate";
|
||||
import {
|
||||
ShippingMethodZipCodeRangeAssign,
|
||||
ShippingMethodZipCodeRangeAssignVariables
|
||||
} from "./types/ShippingMethodZipCodeRangeAssign";
|
||||
import {
|
||||
ShippingMethodZipCodeRangeUnassign,
|
||||
ShippingMethodZipCodeRangeUnassignVariables
|
||||
} from "./types/ShippingMethodZipCodeRangeUnassign";
|
||||
import {
|
||||
UpdateDefaultWeightUnit,
|
||||
UpdateDefaultWeightUnitVariables
|
||||
|
@ -245,3 +254,46 @@ export const useShippingMethodChannelListingUpdate = makeMutation<
|
|||
ShippingMethodChannelListingUpdate,
|
||||
ShippingMethodChannelListingUpdateVariables
|
||||
>(shippingMethodChannelListingUpdate);
|
||||
|
||||
export const shippingMethodZipCodeRangeAssign = gql`
|
||||
${shippingChannelsErrorFragment}
|
||||
${shippingMethodWithZipCodesFragment}
|
||||
mutation ShippingMethodZipCodeRangeAssign(
|
||||
$id: ID!
|
||||
$input: ShippingZipCodeRulesCreateInput!
|
||||
) {
|
||||
shippingMethodZipCodeRulesCreate(shippingMethodId: $id, input: $input) {
|
||||
errors: shippingErrors {
|
||||
...ShippingChannelsErrorFragment
|
||||
}
|
||||
shippingMethod {
|
||||
...ShippingMethodWithZipCodesFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const useShippingMethodZipCodeRangeAssign = makeMutation<
|
||||
ShippingMethodZipCodeRangeAssign,
|
||||
ShippingMethodZipCodeRangeAssignVariables
|
||||
>(shippingMethodZipCodeRangeAssign);
|
||||
|
||||
export const shippingMethodZipCodeRulesDelete = gql`
|
||||
${shippingChannelsErrorFragment}
|
||||
${shippingMethodWithZipCodesFragment}
|
||||
mutation ShippingMethodZipCodeRangeUnassign($id: ID!) {
|
||||
shippingMethodZipCodeRulesDelete(id: $id) {
|
||||
errors: shippingErrors {
|
||||
...ShippingChannelsErrorFragment
|
||||
}
|
||||
shippingMethod {
|
||||
...ShippingMethodWithZipCodesFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const useShippingMethodZipCodeRangeUnassign = makeMutation<
|
||||
ShippingMethodZipCodeRangeUnassign,
|
||||
ShippingMethodZipCodeRangeUnassignVariables
|
||||
>(shippingMethodZipCodeRulesDelete);
|
||||
|
|
|
@ -20,6 +20,13 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone_countries {
|
|||
country: string;
|
||||
}
|
||||
|
||||
export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_minimumOrderWeight {
|
||||
__typename: "Weight";
|
||||
unit: WeightUnitsEnum;
|
||||
|
@ -69,6 +76,7 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMet
|
|||
export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_zipCodeRules | null)[] | null;
|
||||
minimumOrderWeight: CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_minimumOrderWeight | null;
|
||||
maximumOrderWeight: CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_maximumOrderWeight | null;
|
||||
name: string;
|
||||
|
@ -92,6 +100,13 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone {
|
|||
warehouses: (CreateShippingRate_shippingPriceCreate_shippingZone_warehouses | null)[] | null;
|
||||
}
|
||||
|
||||
export interface CreateShippingRate_shippingPriceCreate_shippingMethod_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface CreateShippingRate_shippingPriceCreate_shippingMethod_minimumOrderWeight {
|
||||
__typename: "Weight";
|
||||
unit: WeightUnitsEnum;
|
||||
|
@ -141,6 +156,7 @@ export interface CreateShippingRate_shippingPriceCreate_shippingMethod_channelLi
|
|||
export interface CreateShippingRate_shippingPriceCreate_shippingMethod {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (CreateShippingRate_shippingPriceCreate_shippingMethod_zipCodeRules | null)[] | null;
|
||||
minimumOrderWeight: CreateShippingRate_shippingPriceCreate_shippingMethod_minimumOrderWeight | null;
|
||||
maximumOrderWeight: CreateShippingRate_shippingPriceCreate_shippingMethod_maximumOrderWeight | null;
|
||||
name: string;
|
||||
|
|
|
@ -20,6 +20,13 @@ export interface DeleteShippingRate_shippingPriceDelete_shippingZone_countries {
|
|||
country: string;
|
||||
}
|
||||
|
||||
export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_minimumOrderWeight {
|
||||
__typename: "Weight";
|
||||
unit: WeightUnitsEnum;
|
||||
|
@ -69,6 +76,7 @@ export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMet
|
|||
export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_zipCodeRules | null)[] | null;
|
||||
minimumOrderWeight: DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_minimumOrderWeight | null;
|
||||
maximumOrderWeight: DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_maximumOrderWeight | null;
|
||||
name: string;
|
||||
|
|
|
@ -8,6 +8,13 @@ import { ShippingMethodChannelListingInput, WeightUnitsEnum, ShippingMethodTypeE
|
|||
// GraphQL mutation operation: ShippingMethodChannelListingUpdate
|
||||
// ====================================================
|
||||
|
||||
export interface ShippingMethodChannelListingUpdate_shippingMethodChannelListingUpdate_shippingMethod_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodChannelListingUpdate_shippingMethodChannelListingUpdate_shippingMethod_minimumOrderWeight {
|
||||
__typename: "Weight";
|
||||
unit: WeightUnitsEnum;
|
||||
|
@ -57,6 +64,7 @@ export interface ShippingMethodChannelListingUpdate_shippingMethodChannelListing
|
|||
export interface ShippingMethodChannelListingUpdate_shippingMethodChannelListingUpdate_shippingMethod {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (ShippingMethodChannelListingUpdate_shippingMethodChannelListingUpdate_shippingMethod_zipCodeRules | null)[] | null;
|
||||
minimumOrderWeight: ShippingMethodChannelListingUpdate_shippingMethodChannelListingUpdate_shippingMethod_minimumOrderWeight | null;
|
||||
maximumOrderWeight: ShippingMethodChannelListingUpdate_shippingMethodChannelListingUpdate_shippingMethod_maximumOrderWeight | null;
|
||||
name: string;
|
||||
|
|
44
src/shipping/types/ShippingMethodZipCodeRangeAssign.ts
Normal file
44
src/shipping/types/ShippingMethodZipCodeRangeAssign.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { ShippingZipCodeRulesCreateInput, ShippingErrorCode } from "./../../types/globalTypes";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL mutation operation: ShippingMethodZipCodeRangeAssign
|
||||
// ====================================================
|
||||
|
||||
export interface ShippingMethodZipCodeRangeAssign_shippingMethodZipCodeRulesCreate_errors {
|
||||
__typename: "ShippingError";
|
||||
code: ShippingErrorCode;
|
||||
field: string | null;
|
||||
channels: string[] | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodZipCodeRangeAssign_shippingMethodZipCodeRulesCreate_shippingMethod_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodZipCodeRangeAssign_shippingMethodZipCodeRulesCreate_shippingMethod {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (ShippingMethodZipCodeRangeAssign_shippingMethodZipCodeRulesCreate_shippingMethod_zipCodeRules | null)[] | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodZipCodeRangeAssign_shippingMethodZipCodeRulesCreate {
|
||||
__typename: "ShippingZipCodeRulesCreate";
|
||||
errors: ShippingMethodZipCodeRangeAssign_shippingMethodZipCodeRulesCreate_errors[];
|
||||
shippingMethod: ShippingMethodZipCodeRangeAssign_shippingMethodZipCodeRulesCreate_shippingMethod | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodZipCodeRangeAssign {
|
||||
shippingMethodZipCodeRulesCreate: ShippingMethodZipCodeRangeAssign_shippingMethodZipCodeRulesCreate | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodZipCodeRangeAssignVariables {
|
||||
id: string;
|
||||
input: ShippingZipCodeRulesCreateInput;
|
||||
}
|
43
src/shipping/types/ShippingMethodZipCodeRangeUnassign.ts
Normal file
43
src/shipping/types/ShippingMethodZipCodeRangeUnassign.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { ShippingErrorCode } from "./../../types/globalTypes";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL mutation operation: ShippingMethodZipCodeRangeUnassign
|
||||
// ====================================================
|
||||
|
||||
export interface ShippingMethodZipCodeRangeUnassign_shippingMethodZipCodeRulesDelete_errors {
|
||||
__typename: "ShippingError";
|
||||
code: ShippingErrorCode;
|
||||
field: string | null;
|
||||
channels: string[] | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodZipCodeRangeUnassign_shippingMethodZipCodeRulesDelete_shippingMethod_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodZipCodeRangeUnassign_shippingMethodZipCodeRulesDelete_shippingMethod {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (ShippingMethodZipCodeRangeUnassign_shippingMethodZipCodeRulesDelete_shippingMethod_zipCodeRules | null)[] | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodZipCodeRangeUnassign_shippingMethodZipCodeRulesDelete {
|
||||
__typename: "ShippingZipCodeRulesDelete";
|
||||
errors: ShippingMethodZipCodeRangeUnassign_shippingMethodZipCodeRulesDelete_errors[];
|
||||
shippingMethod: ShippingMethodZipCodeRangeUnassign_shippingMethodZipCodeRulesDelete_shippingMethod | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodZipCodeRangeUnassign {
|
||||
shippingMethodZipCodeRulesDelete: ShippingMethodZipCodeRangeUnassign_shippingMethodZipCodeRulesDelete | null;
|
||||
}
|
||||
|
||||
export interface ShippingMethodZipCodeRangeUnassignVariables {
|
||||
id: string;
|
||||
}
|
|
@ -14,6 +14,13 @@ export interface ShippingZone_shippingZone_countries {
|
|||
country: string;
|
||||
}
|
||||
|
||||
export interface ShippingZone_shippingZone_shippingMethods_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface ShippingZone_shippingZone_shippingMethods_minimumOrderWeight {
|
||||
__typename: "Weight";
|
||||
unit: WeightUnitsEnum;
|
||||
|
@ -63,6 +70,7 @@ export interface ShippingZone_shippingZone_shippingMethods_channelListings {
|
|||
export interface ShippingZone_shippingZone_shippingMethods {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (ShippingZone_shippingZone_shippingMethods_zipCodeRules | null)[] | null;
|
||||
minimumOrderWeight: ShippingZone_shippingZone_shippingMethods_minimumOrderWeight | null;
|
||||
maximumOrderWeight: ShippingZone_shippingZone_shippingMethods_maximumOrderWeight | null;
|
||||
name: string;
|
||||
|
|
|
@ -14,6 +14,13 @@ export interface UpdateShippingRate_shippingPriceUpdate_errors {
|
|||
field: string | null;
|
||||
}
|
||||
|
||||
export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_zipCodeRules {
|
||||
__typename: "ShippingMethodZipCodeRule";
|
||||
id: string;
|
||||
start: string | null;
|
||||
end: string | null;
|
||||
}
|
||||
|
||||
export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_minimumOrderWeight {
|
||||
__typename: "Weight";
|
||||
unit: WeightUnitsEnum;
|
||||
|
@ -63,6 +70,7 @@ export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod_channelLi
|
|||
export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod {
|
||||
__typename: "ShippingMethod";
|
||||
id: string;
|
||||
zipCodeRules: (UpdateShippingRate_shippingPriceUpdate_shippingMethod_zipCodeRules | null)[] | null;
|
||||
minimumOrderWeight: UpdateShippingRate_shippingPriceUpdate_shippingMethod_minimumOrderWeight | null;
|
||||
maximumOrderWeight: UpdateShippingRate_shippingPriceUpdate_shippingMethod_maximumOrderWeight | null;
|
||||
name: string;
|
||||
|
|
|
@ -36,22 +36,58 @@ export const shippingZoneUrl = (
|
|||
params?: ShippingZoneUrlQueryParams
|
||||
) => shippingZonePath(encodeURIComponent(id)) + "?" + stringifyQs(params);
|
||||
|
||||
export const shippingPriceRatesUrl = (id: string) =>
|
||||
type ZipCodeRangeActions = "add-range" | "remove-range";
|
||||
export type ShippingRateUrlDialog = ZipCodeRangeActions | "remove";
|
||||
export type ShippingRateUrlQueryParams = Dialog<ShippingRateUrlDialog> &
|
||||
SingleAction;
|
||||
export type ShippingRateCreateUrlDialog = ZipCodeRangeActions;
|
||||
export type ShippingRateCreateUrlQueryParams = Dialog<
|
||||
ShippingRateCreateUrlDialog
|
||||
> &
|
||||
SingleAction;
|
||||
|
||||
export const shippingPriceRatesPath = (id: string) =>
|
||||
urlJoin(shippingZonePath(id), "price", "add");
|
||||
export const shippingPriceRatesUrl = (
|
||||
id: string,
|
||||
params?: ShippingRateCreateUrlQueryParams
|
||||
) => shippingPriceRatesPath(encodeURIComponent(id)) + "?" + stringifyQs(params);
|
||||
|
||||
export const shippingWeightRatesUrl = (id: string) =>
|
||||
export const shippingWeightRatesPath = (id: string) =>
|
||||
urlJoin(shippingZonePath(id), "weight", "add");
|
||||
export const shippingWeightRatesUrl = (
|
||||
id: string,
|
||||
params?: ShippingRateCreateUrlQueryParams
|
||||
) =>
|
||||
shippingWeightRatesPath(encodeURIComponent(id)) + "?" + stringifyQs(params);
|
||||
|
||||
export const shippingWeightRatesEditUrl = (id: string, rateId: string) =>
|
||||
urlJoin(shippingZonePath(id), "weight", rateId);
|
||||
|
||||
export const shippingPriceRatesEditUrl = (id: string, rateId: string) =>
|
||||
export const shippingPriceRatesEditPath = (id: string, rateId: string) =>
|
||||
urlJoin(shippingZonePath(id), "price", rateId);
|
||||
export const shippingPriceRatesEditUrl = (
|
||||
id: string,
|
||||
rateId: string,
|
||||
params?: ShippingRateUrlQueryParams
|
||||
) =>
|
||||
shippingPriceRatesEditPath(
|
||||
encodeURIComponent(id),
|
||||
encodeURIComponent(rateId)
|
||||
) +
|
||||
"?" +
|
||||
stringifyQs(params);
|
||||
|
||||
export const shippingWeightRatesEditPath = (id: string, rateId: string) =>
|
||||
urlJoin(shippingZonePath(id), "weight", rateId);
|
||||
export const shippingWeightRatesEditUrl = (
|
||||
id: string,
|
||||
rateId: string,
|
||||
params?: ShippingRateUrlQueryParams
|
||||
) =>
|
||||
shippingWeightRatesEditPath(
|
||||
encodeURIComponent(id),
|
||||
encodeURIComponent(rateId)
|
||||
) +
|
||||
"?" +
|
||||
stringifyQs(params);
|
||||
|
||||
export const shippingZoneAddPath = urlJoin(shippingZonesListPath, "add");
|
||||
export const shippingZoneAddUrl = shippingZoneAddPath;
|
||||
export const shippingPriceRatesAddPath = urlJoin(
|
||||
shippingZonesListPath,
|
||||
"price",
|
||||
"add"
|
||||
);
|
||||
export const shippingZoneAddUrl = shippingZoneAddPath + "?";
|
||||
|
|
|
@ -2,57 +2,49 @@ import { useChannelsList } from "@saleor/channels/queries";
|
|||
import { createSortedShippingChannels } from "@saleor/channels/utils";
|
||||
import ChannelsAvailabilityDialog from "@saleor/components/ChannelsAvailabilityDialog";
|
||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||
import { ShippingMethodFragment_zipCodeRules } from "@saleor/fragments/types/ShippingMethodFragment";
|
||||
import useChannels from "@saleor/hooks/useChannels";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { commonMessages, sectionNames } from "@saleor/intl";
|
||||
import { FormData } from "@saleor/shipping/components/ShippingZoneRatesPage";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
||||
import ShippingZoneRatesPage from "@saleor/shipping/components/ShippingZoneRatesPage";
|
||||
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
||||
import { useShippingRateCreator } from "@saleor/shipping/handlers";
|
||||
import {
|
||||
getCreateShippingPriceRateVariables,
|
||||
getShippingMethodChannelVariables
|
||||
} from "@saleor/shipping/handlers";
|
||||
import { useShippingMethodChannelListingUpdate } from "@saleor/shipping/mutations";
|
||||
import { useShippingRateCreate } from "@saleor/shipping/mutations";
|
||||
import {
|
||||
shippingPriceRatesEditUrl,
|
||||
shippingPriceRatesUrl,
|
||||
ShippingRateCreateUrlDialog,
|
||||
ShippingRateCreateUrlQueryParams,
|
||||
shippingZoneUrl
|
||||
} from "@saleor/shipping/urls";
|
||||
import { MinMax } from "@saleor/types";
|
||||
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import { remove } from "@saleor/utils/lists";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
export interface PriceRatesCreateProps {
|
||||
id: string;
|
||||
params: ShippingRateCreateUrlQueryParams;
|
||||
}
|
||||
|
||||
export const PriceRatesCreate: React.FC<PriceRatesCreateProps> = ({ id }) => {
|
||||
export const PriceRatesCreate: React.FC<PriceRatesCreateProps> = ({
|
||||
id,
|
||||
params
|
||||
}) => {
|
||||
const navigate = useNavigator();
|
||||
const notify = useNotifier();
|
||||
const intl = useIntl();
|
||||
|
||||
const [zipCodes, setZipCodes] = React.useState<
|
||||
ShippingMethodFragment_zipCodeRules[]
|
||||
>([]);
|
||||
|
||||
const { data: channelsData, loading: channelsLoading } = useChannelsList({});
|
||||
|
||||
const [
|
||||
updateShippingMethodChannelListing,
|
||||
updateShippingMethodChannelListingOpts
|
||||
] = useShippingMethodChannelListingUpdate({
|
||||
onCompleted: data => {
|
||||
const errors = data.shippingMethodChannelListingUpdate.errors;
|
||||
if (errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
});
|
||||
navigate(
|
||||
shippingPriceRatesEditUrl(
|
||||
id,
|
||||
data.shippingMethodChannelListingUpdate.shippingMethod.id
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
const [openModal, closeModal] = createDialogActionHandlers<
|
||||
ShippingRateCreateUrlDialog,
|
||||
ShippingRateCreateUrlQueryParams
|
||||
>(navigate, params => shippingPriceRatesUrl(id, params), params);
|
||||
|
||||
const allChannels = createSortedShippingChannels(channelsData?.channels);
|
||||
|
||||
|
@ -69,27 +61,38 @@ export const PriceRatesCreate: React.FC<PriceRatesCreateProps> = ({ id }) => {
|
|||
toggleAllChannels
|
||||
} = useChannels(allChannels);
|
||||
|
||||
const [createShippingRate, createShippingRateOpts] = useShippingRateCreate(
|
||||
{}
|
||||
);
|
||||
const {
|
||||
channelErrors,
|
||||
createShippingRate,
|
||||
errors,
|
||||
status
|
||||
} = useShippingRateCreator(id, ShippingMethodTypeEnum.PRICE, zipCodes);
|
||||
|
||||
const handleSubmit = async (data: FormData) => {
|
||||
const response = await createShippingRate({
|
||||
variables: getCreateShippingPriceRateVariables(data, id)
|
||||
});
|
||||
const errors = response.data.shippingPriceCreate.errors;
|
||||
if (errors.length === 0) {
|
||||
updateShippingMethodChannelListing({
|
||||
variables: getShippingMethodChannelVariables(
|
||||
response.data.shippingPriceCreate.shippingMethod.id,
|
||||
data.noLimits,
|
||||
data.channelListings
|
||||
)
|
||||
});
|
||||
}
|
||||
};
|
||||
const handleBack = () => navigate(shippingZoneUrl(id));
|
||||
|
||||
const handleZipCodeRangeAdd = (data: MinMax) => {
|
||||
setZipCodes(zipCodes => [
|
||||
...zipCodes,
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: data.max,
|
||||
id: zipCodes.length.toString(),
|
||||
start: data.min
|
||||
}
|
||||
]);
|
||||
closeModal();
|
||||
};
|
||||
const handleZipCodeRangeDelete = (id: string) => {
|
||||
setZipCodes(zipCodes =>
|
||||
remove(
|
||||
zipCodes.find(zipCode => zipCode.id === id),
|
||||
zipCodes,
|
||||
(a, b) => a.id === b.id
|
||||
)
|
||||
);
|
||||
closeModal();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<WindowTitle title={intl.formatMessage(sectionNames.shipping)} />
|
||||
|
@ -114,23 +117,36 @@ export const PriceRatesCreate: React.FC<PriceRatesCreateProps> = ({ id }) => {
|
|||
<ShippingZoneRatesPage
|
||||
allChannelsCount={allChannels?.length}
|
||||
shippingChannels={currentChannels}
|
||||
disabled={
|
||||
channelsLoading ||
|
||||
createShippingRateOpts?.status === "loading" ||
|
||||
updateShippingMethodChannelListingOpts?.status === "loading"
|
||||
}
|
||||
saveButtonBarState={createShippingRateOpts?.status}
|
||||
onSubmit={handleSubmit}
|
||||
disabled={channelsLoading || status === "loading"}
|
||||
saveButtonBarState={status}
|
||||
onSubmit={createShippingRate}
|
||||
onBack={handleBack}
|
||||
errors={createShippingRateOpts.data?.shippingPriceCreate.errors || []}
|
||||
channelErrors={
|
||||
updateShippingMethodChannelListingOpts?.data
|
||||
?.shippingMethodChannelListingUpdate?.errors || []
|
||||
}
|
||||
errors={errors}
|
||||
channelErrors={channelErrors}
|
||||
rate={null}
|
||||
zipCodes={zipCodes}
|
||||
openChannelsModal={handleChannelsModalOpen}
|
||||
onChannelsChange={setCurrentChannels}
|
||||
onZipCodeAssign={() => openModal("add-range")}
|
||||
onZipCodeUnassign={id =>
|
||||
openModal("remove-range", {
|
||||
id
|
||||
})
|
||||
}
|
||||
variant={ShippingMethodTypeEnum.PRICE}
|
||||
/>
|
||||
<ShippingZoneZipCodeRangeDialog
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onSubmit={handleZipCodeRangeAdd}
|
||||
open={params.action === "add-range"}
|
||||
/>
|
||||
<ShippingRateZipCodeRangeRemoveDialog
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onConfirm={() => handleZipCodeRangeDelete(params.id)}
|
||||
open={params.action === "remove-range"}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,32 +11,46 @@ import useNotifier from "@saleor/hooks/useNotifier";
|
|||
import { sectionNames } from "@saleor/intl";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import DeleteShippingRateDialog from "@saleor/shipping/components/DeleteShippingRateDialog";
|
||||
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
||||
import ShippingZoneRatesPage, {
|
||||
FormData
|
||||
} from "@saleor/shipping/components/ShippingZoneRatesPage";
|
||||
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
||||
import {
|
||||
getShippingMethodChannelVariables,
|
||||
getUpdateShippingPriceRateVariables
|
||||
} from "@saleor/shipping/handlers";
|
||||
import { useShippingMethodChannelListingUpdate } from "@saleor/shipping/mutations";
|
||||
import {
|
||||
useShippingMethodChannelListingUpdate,
|
||||
useShippingMethodZipCodeRangeAssign,
|
||||
useShippingMethodZipCodeRangeUnassign
|
||||
} from "@saleor/shipping/mutations";
|
||||
import {
|
||||
useShippingRateDelete,
|
||||
useShippingRateUpdate
|
||||
} from "@saleor/shipping/mutations";
|
||||
import { useShippingZone } from "@saleor/shipping/queries";
|
||||
import { shippingZoneUrl } from "@saleor/shipping/urls";
|
||||
import {
|
||||
shippingPriceRatesEditUrl,
|
||||
ShippingRateUrlDialog,
|
||||
ShippingRateUrlQueryParams,
|
||||
shippingZoneUrl
|
||||
} from "@saleor/shipping/urls";
|
||||
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
export interface PriceRatesUpdateProps {
|
||||
id: string;
|
||||
rateId: string;
|
||||
params: ShippingRateUrlQueryParams;
|
||||
}
|
||||
|
||||
export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
||||
id,
|
||||
rateId
|
||||
rateId,
|
||||
params
|
||||
}) => {
|
||||
const navigate = useNavigator();
|
||||
const notify = useNotifier();
|
||||
|
@ -47,6 +61,11 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
|||
variables: { id }
|
||||
});
|
||||
|
||||
const [openModal, closeModal] = createDialogActionHandlers<
|
||||
ShippingRateUrlDialog,
|
||||
ShippingRateUrlQueryParams
|
||||
>(navigate, params => shippingPriceRatesEditUrl(id, rateId, params), params);
|
||||
|
||||
const rate = data?.shippingZone?.shippingMethods.find(
|
||||
rate => rate.id === rateId
|
||||
);
|
||||
|
@ -57,6 +76,43 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
|||
updateShippingMethodChannelListingOpts
|
||||
] = useShippingMethodChannelListingUpdate({});
|
||||
|
||||
const [
|
||||
assignZipCodeRange,
|
||||
assignZipCodeRangeOpts
|
||||
] = useShippingMethodZipCodeRangeAssign({
|
||||
onCompleted: data => {
|
||||
if (data.shippingMethodZipCodeRulesCreate.errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
});
|
||||
closeModal();
|
||||
} else {
|
||||
notify({
|
||||
status: "error",
|
||||
text: intl.formatMessage({
|
||||
defaultMessage: "Cannot add specified zip codes range.",
|
||||
description: "zip code range add error text"
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
const [
|
||||
unassignZipCodeRange,
|
||||
unassignZipCodeRangeOpts
|
||||
] = useShippingMethodZipCodeRangeUnassign({
|
||||
onCompleted: data => {
|
||||
if (data.shippingMethodZipCodeRulesDelete.errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
});
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const shippingChannels = createShippingChannelsFromRate(
|
||||
rate?.channelListings
|
||||
);
|
||||
|
@ -75,8 +131,6 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
|||
toggleAllChannels
|
||||
} = useChannels(shippingChannels);
|
||||
|
||||
const [openModal, setOpenModal] = React.useState(false);
|
||||
|
||||
const [updateShippingRate, updateShippingRateOpts] = useShippingRateUpdate(
|
||||
{}
|
||||
);
|
||||
|
@ -96,7 +150,6 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
|||
}
|
||||
});
|
||||
|
||||
const handleDelete = () => setOpenModal(true);
|
||||
const handleSubmit = async (formData: FormData) => {
|
||||
const response = await updateShippingRate({
|
||||
variables: getUpdateShippingPriceRateVariables(formData, id, rateId)
|
||||
|
@ -139,7 +192,7 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
|||
)}
|
||||
<DeleteShippingRateDialog
|
||||
confirmButtonState={deleteShippingRateOpts.status}
|
||||
onClose={() => setOpenModal(false)}
|
||||
onClose={closeModal}
|
||||
handleConfirm={() =>
|
||||
deleteShippingRate({
|
||||
variables: {
|
||||
|
@ -147,7 +200,7 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
|||
}
|
||||
})
|
||||
}
|
||||
open={openModal}
|
||||
open={params.action === "remove"}
|
||||
name={rate?.name}
|
||||
/>
|
||||
<ShippingZoneRatesPage
|
||||
|
@ -160,7 +213,7 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
|||
}
|
||||
hasChannelChanged={shippingChannels?.length !== currentChannels?.length}
|
||||
saveButtonBarState={updateShippingRateOpts.status}
|
||||
onDelete={handleDelete}
|
||||
onDelete={() => openModal("remove")}
|
||||
onSubmit={handleSubmit}
|
||||
onBack={handleBack}
|
||||
rate={rate}
|
||||
|
@ -172,6 +225,44 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
|||
openChannelsModal={handleChannelsModalOpen}
|
||||
onChannelsChange={setCurrentChannels}
|
||||
variant={ShippingMethodTypeEnum.PRICE}
|
||||
onZipCodeAssign={() => openModal("add-range")}
|
||||
onZipCodeUnassign={id =>
|
||||
openModal("remove-range", {
|
||||
id
|
||||
})
|
||||
}
|
||||
/>
|
||||
<ShippingZoneZipCodeRangeDialog
|
||||
confirmButtonState={assignZipCodeRangeOpts.status}
|
||||
onClose={closeModal}
|
||||
onSubmit={data =>
|
||||
assignZipCodeRange({
|
||||
variables: {
|
||||
id: rateId,
|
||||
input: {
|
||||
zipCodeRules: [
|
||||
{
|
||||
end: data.max || null,
|
||||
start: data.min
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
open={params.action === "add-range"}
|
||||
/>
|
||||
<ShippingRateZipCodeRangeRemoveDialog
|
||||
confirmButtonState={unassignZipCodeRangeOpts.status}
|
||||
onClose={closeModal}
|
||||
onConfirm={() =>
|
||||
unassignZipCodeRange({
|
||||
variables: {
|
||||
id: params.id
|
||||
}
|
||||
})
|
||||
}
|
||||
open={params.action === "remove-range"}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -5,57 +5,49 @@ import {
|
|||
} from "@saleor/channels/utils";
|
||||
import ChannelsAvailabilityDialog from "@saleor/components/ChannelsAvailabilityDialog";
|
||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||
import { ShippingMethodFragment_zipCodeRules } from "@saleor/fragments/types/ShippingMethodFragment";
|
||||
import useChannels from "@saleor/hooks/useChannels";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { commonMessages, sectionNames } from "@saleor/intl";
|
||||
import { FormData } from "@saleor/shipping/components/ShippingZoneRatesPage";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
||||
import ShippingZoneRatesPage from "@saleor/shipping/components/ShippingZoneRatesPage";
|
||||
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
||||
import { useShippingRateCreator } from "@saleor/shipping/handlers";
|
||||
import {
|
||||
getCreateShippingWeightRateVariables,
|
||||
getShippingMethodChannelVariables
|
||||
} from "@saleor/shipping/handlers";
|
||||
import { useShippingMethodChannelListingUpdate } from "@saleor/shipping/mutations";
|
||||
import { useShippingRateCreate } from "@saleor/shipping/mutations";
|
||||
import {
|
||||
shippingWeightRatesEditUrl,
|
||||
ShippingRateCreateUrlDialog,
|
||||
ShippingRateCreateUrlQueryParams,
|
||||
shippingWeightRatesUrl,
|
||||
shippingZoneUrl
|
||||
} from "@saleor/shipping/urls";
|
||||
import { MinMax } from "@saleor/types";
|
||||
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import { remove } from "@saleor/utils/lists";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
export interface WeightRatesCreateProps {
|
||||
id: string;
|
||||
params: ShippingRateCreateUrlQueryParams;
|
||||
}
|
||||
|
||||
export const WeightRatesCreate: React.FC<WeightRatesCreateProps> = ({ id }) => {
|
||||
export const WeightRatesCreate: React.FC<WeightRatesCreateProps> = ({
|
||||
id,
|
||||
params
|
||||
}) => {
|
||||
const navigate = useNavigator();
|
||||
const notify = useNotifier();
|
||||
const intl = useIntl();
|
||||
|
||||
const [zipCodes, setZipCodes] = React.useState<
|
||||
ShippingMethodFragment_zipCodeRules[]
|
||||
>([]);
|
||||
|
||||
const { data: channelsData, loading: channelsLoading } = useChannelsList({});
|
||||
|
||||
const [
|
||||
updateShippingMethodChannelListing,
|
||||
updateShippingMethodChannelListingOpts
|
||||
] = useShippingMethodChannelListingUpdate({
|
||||
onCompleted: data => {
|
||||
const errors = data.shippingMethodChannelListingUpdate.errors;
|
||||
if (errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
});
|
||||
navigate(
|
||||
shippingWeightRatesEditUrl(
|
||||
id,
|
||||
data.shippingMethodChannelListingUpdate.shippingMethod.id
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
const [openModal, closeModal] = createDialogActionHandlers<
|
||||
ShippingRateCreateUrlDialog,
|
||||
ShippingRateCreateUrlQueryParams
|
||||
>(navigate, params => shippingWeightRatesUrl(id, params), params);
|
||||
|
||||
const shippingChannels = createShippingChannels(channelsData?.channels);
|
||||
const allChannels = createSortedShippingChannels(channelsData?.channels);
|
||||
|
@ -73,28 +65,38 @@ export const WeightRatesCreate: React.FC<WeightRatesCreateProps> = ({ id }) => {
|
|||
toggleAllChannels
|
||||
} = useChannels(shippingChannels);
|
||||
|
||||
const [createShippingRate, createShippingRateOpts] = useShippingRateCreate(
|
||||
{}
|
||||
);
|
||||
|
||||
const handleSubmit = async (data: FormData) => {
|
||||
const response = await createShippingRate({
|
||||
variables: getCreateShippingWeightRateVariables(data, id)
|
||||
});
|
||||
const errors = response.data.shippingPriceCreate.errors;
|
||||
if (errors.length === 0) {
|
||||
updateShippingMethodChannelListing({
|
||||
variables: getShippingMethodChannelVariables(
|
||||
response.data.shippingPriceCreate.shippingMethod.id,
|
||||
data.noLimits,
|
||||
data.channelListings
|
||||
)
|
||||
});
|
||||
}
|
||||
};
|
||||
const {
|
||||
channelErrors,
|
||||
createShippingRate,
|
||||
errors,
|
||||
status
|
||||
} = useShippingRateCreator(id, ShippingMethodTypeEnum.WEIGHT, zipCodes);
|
||||
|
||||
const handleBack = () => navigate(shippingZoneUrl(id));
|
||||
|
||||
const handleZipCodeRangeAdd = (data: MinMax) => {
|
||||
setZipCodes(zipCodes => [
|
||||
...zipCodes,
|
||||
{
|
||||
__typename: "ShippingMethodZipCodeRule",
|
||||
end: data.max,
|
||||
id: zipCodes.length.toString(),
|
||||
start: data.min
|
||||
}
|
||||
]);
|
||||
closeModal();
|
||||
};
|
||||
const handleZipCodeRangeDelete = (id: string) => {
|
||||
setZipCodes(zipCodes =>
|
||||
remove(
|
||||
zipCodes.find(zipCode => zipCode.id === id),
|
||||
zipCodes,
|
||||
(a, b) => a.id === b.id
|
||||
)
|
||||
);
|
||||
closeModal();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<WindowTitle title={intl.formatMessage(sectionNames.shipping)} />
|
||||
|
@ -118,23 +120,36 @@ export const WeightRatesCreate: React.FC<WeightRatesCreateProps> = ({ id }) => {
|
|||
<ShippingZoneRatesPage
|
||||
allChannelsCount={allChannels?.length}
|
||||
shippingChannels={currentChannels}
|
||||
disabled={
|
||||
channelsLoading ||
|
||||
createShippingRateOpts?.status === "loading" ||
|
||||
updateShippingMethodChannelListingOpts?.status === "loading"
|
||||
}
|
||||
saveButtonBarState={createShippingRateOpts?.status}
|
||||
onSubmit={handleSubmit}
|
||||
disabled={channelsLoading || status === "loading"}
|
||||
saveButtonBarState={status}
|
||||
onSubmit={createShippingRate}
|
||||
onBack={handleBack}
|
||||
errors={createShippingRateOpts.data?.shippingPriceCreate.errors || []}
|
||||
channelErrors={
|
||||
updateShippingMethodChannelListingOpts?.data
|
||||
?.shippingMethodChannelListingUpdate?.errors || []
|
||||
}
|
||||
errors={errors}
|
||||
channelErrors={channelErrors}
|
||||
rate={null}
|
||||
zipCodes={zipCodes}
|
||||
openChannelsModal={handleChannelsModalOpen}
|
||||
onChannelsChange={setCurrentChannels}
|
||||
onZipCodeAssign={() => openModal("add-range")}
|
||||
onZipCodeUnassign={id =>
|
||||
openModal("remove-range", {
|
||||
id
|
||||
})
|
||||
}
|
||||
variant={ShippingMethodTypeEnum.WEIGHT}
|
||||
/>
|
||||
<ShippingZoneZipCodeRangeDialog
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onSubmit={handleZipCodeRangeAdd}
|
||||
open={params.action === "add-range"}
|
||||
/>
|
||||
<ShippingRateZipCodeRangeRemoveDialog
|
||||
confirmButtonState="default"
|
||||
onClose={closeModal}
|
||||
onConfirm={() => handleZipCodeRangeDelete(params.id)}
|
||||
open={params.action === "remove-range"}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,32 +11,44 @@ import useNotifier from "@saleor/hooks/useNotifier";
|
|||
import { sectionNames } from "@saleor/intl";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import DeleteShippingRateDialog from "@saleor/shipping/components/DeleteShippingRateDialog";
|
||||
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
||||
import ShippingZoneRatesPage, {
|
||||
FormData
|
||||
} from "@saleor/shipping/components/ShippingZoneRatesPage";
|
||||
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
||||
import {
|
||||
getShippingMethodChannelVariables,
|
||||
getUpdateShippingWeightRateVariables
|
||||
} from "@saleor/shipping/handlers";
|
||||
import {
|
||||
useShippingMethodZipCodeRangeAssign,
|
||||
useShippingMethodZipCodeRangeUnassign,
|
||||
useShippingRateDelete,
|
||||
useShippingRateUpdate
|
||||
} from "@saleor/shipping/mutations";
|
||||
import { useShippingMethodChannelListingUpdate } from "@saleor/shipping/mutations";
|
||||
import { useShippingZone } from "@saleor/shipping/queries";
|
||||
import { shippingZoneUrl } from "@saleor/shipping/urls";
|
||||
import {
|
||||
ShippingRateUrlDialog,
|
||||
ShippingRateUrlQueryParams,
|
||||
shippingWeightRatesEditUrl,
|
||||
shippingZoneUrl
|
||||
} from "@saleor/shipping/urls";
|
||||
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
export interface WeightRatesUpdateProps {
|
||||
id: string;
|
||||
rateId: string;
|
||||
params: ShippingRateUrlQueryParams;
|
||||
}
|
||||
|
||||
export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
||||
id,
|
||||
rateId
|
||||
rateId,
|
||||
params
|
||||
}) => {
|
||||
const navigate = useNavigator();
|
||||
const notify = useNotifier();
|
||||
|
@ -47,6 +59,11 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
|||
variables: { id }
|
||||
});
|
||||
|
||||
const [openModal, closeModal] = createDialogActionHandlers<
|
||||
ShippingRateUrlDialog,
|
||||
ShippingRateUrlQueryParams
|
||||
>(navigate, params => shippingWeightRatesEditUrl(id, rateId, params), params);
|
||||
|
||||
const rate = data?.shippingZone?.shippingMethods.find(
|
||||
rate => rate.id === rateId
|
||||
);
|
||||
|
@ -74,8 +91,6 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
|||
toggleAllChannels
|
||||
} = useChannels(shippingChannels);
|
||||
|
||||
const [openModal, setOpenModal] = React.useState(false);
|
||||
|
||||
const [updateShippingRate, updateShippingRateOpts] = useShippingRateUpdate(
|
||||
{}
|
||||
);
|
||||
|
@ -96,7 +111,43 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
|||
}
|
||||
});
|
||||
|
||||
const handleDelete = () => setOpenModal(true);
|
||||
const [
|
||||
assignZipCodeRange,
|
||||
assignZipCodeRangeOpts
|
||||
] = useShippingMethodZipCodeRangeAssign({
|
||||
onCompleted: data => {
|
||||
if (data.shippingMethodZipCodeRulesCreate.errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
});
|
||||
closeModal();
|
||||
} else {
|
||||
notify({
|
||||
status: "error",
|
||||
text: intl.formatMessage({
|
||||
defaultMessage: "Cannot add specified zip codes range.",
|
||||
description: "zip code range add error text"
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
const [
|
||||
unassignZipCodeRange,
|
||||
unassignZipCodeRangeOpts
|
||||
] = useShippingMethodZipCodeRangeUnassign({
|
||||
onCompleted: data => {
|
||||
if (data.shippingMethodZipCodeRulesDelete.errors.length === 0) {
|
||||
notify({
|
||||
status: "success",
|
||||
text: intl.formatMessage(commonMessages.savedChanges)
|
||||
});
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const handleSubmit = async (data: FormData) => {
|
||||
const response = await updateShippingRate({
|
||||
variables: getUpdateShippingWeightRateVariables(data, id, rateId)
|
||||
|
@ -139,7 +190,7 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
|||
)}
|
||||
<DeleteShippingRateDialog
|
||||
confirmButtonState={deleteShippingRateOpts.status}
|
||||
onClose={() => setOpenModal(false)}
|
||||
onClose={closeModal}
|
||||
handleConfirm={() =>
|
||||
deleteShippingRate({
|
||||
variables: {
|
||||
|
@ -147,7 +198,7 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
|||
}
|
||||
})
|
||||
}
|
||||
open={openModal}
|
||||
open={params.action === "remove"}
|
||||
name={rate?.name}
|
||||
/>
|
||||
<ShippingZoneRatesPage
|
||||
|
@ -160,7 +211,7 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
|||
}
|
||||
hasChannelChanged={shippingChannels?.length !== currentChannels?.length}
|
||||
saveButtonBarState={updateShippingRateOpts.status}
|
||||
onDelete={handleDelete}
|
||||
onDelete={() => openModal("remove")}
|
||||
onSubmit={handleSubmit}
|
||||
onBack={handleBack}
|
||||
rate={rate}
|
||||
|
@ -172,6 +223,44 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
|||
openChannelsModal={handleChannelsModalOpen}
|
||||
onChannelsChange={setCurrentChannels}
|
||||
variant={ShippingMethodTypeEnum.WEIGHT}
|
||||
onZipCodeAssign={() => openModal("add-range")}
|
||||
onZipCodeUnassign={id =>
|
||||
openModal("remove-range", {
|
||||
id
|
||||
})
|
||||
}
|
||||
/>
|
||||
<ShippingZoneZipCodeRangeDialog
|
||||
confirmButtonState={assignZipCodeRangeOpts.status}
|
||||
onClose={closeModal}
|
||||
onSubmit={data =>
|
||||
assignZipCodeRange({
|
||||
variables: {
|
||||
id: rateId,
|
||||
input: {
|
||||
zipCodeRules: [
|
||||
{
|
||||
end: data.max || null,
|
||||
start: data.min
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
open={params.action === "add-range"}
|
||||
/>
|
||||
<ShippingRateZipCodeRangeRemoveDialog
|
||||
confirmButtonState={unassignZipCodeRangeOpts.status}
|
||||
onClose={closeModal}
|
||||
onConfirm={() =>
|
||||
unassignZipCodeRange({
|
||||
variables: {
|
||||
id: params.id
|
||||
}
|
||||
})
|
||||
}
|
||||
open={params.action === "remove-range"}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1357,19 +1357,18 @@ export interface OrderLineInput {
|
|||
}
|
||||
|
||||
export interface OrderRefundFulfillmentLineInput {
|
||||
fulfillmentLineId?: string | null;
|
||||
fulfillmentLineId: string;
|
||||
quantity: number;
|
||||
}
|
||||
|
||||
export interface OrderRefundLineInput {
|
||||
orderLineId?: string | null;
|
||||
orderLineId: string;
|
||||
quantity: number;
|
||||
}
|
||||
|
||||
export interface OrderRefundProductsInput {
|
||||
orderLines?: OrderRefundLineInput[] | null;
|
||||
fulfillmentLines?: OrderRefundFulfillmentLineInput[] | null;
|
||||
notifyCustomer?: boolean | null;
|
||||
amountToRefund?: any | null;
|
||||
includeShippingCosts?: boolean | null;
|
||||
}
|
||||
|
@ -1698,6 +1697,15 @@ export interface ShippingPriceInput {
|
|||
shippingZone?: string | null;
|
||||
}
|
||||
|
||||
export interface ShippingZipCodeRulesCreateInput {
|
||||
zipCodeRules: (ShippingZipCodeRulesCreateInputRange | null)[];
|
||||
}
|
||||
|
||||
export interface ShippingZipCodeRulesCreateInputRange {
|
||||
start: string;
|
||||
end?: string | null;
|
||||
}
|
||||
|
||||
export interface ShippingZoneCreateInput {
|
||||
name?: string | null;
|
||||
countries?: (string | null)[] | null;
|
||||
|
|
Loading…
Reference in a new issue