diff --git a/package-lock.json b/package-lock.json index 0dd6faa25..158ec5659 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,56 +16,56 @@ } }, "@apollo/react-common": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@apollo/react-common/-/react-common-3.1.3.tgz", - "integrity": "sha512-Q7ZjDOeqjJf/AOGxUMdGxKF+JVClRXrYBGVq+SuVFqANRpd68MxtVV2OjCWavsFAN0eqYnRqRUrl7vtUCiJqeg==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@apollo/react-common/-/react-common-3.1.4.tgz", + "integrity": "sha512-X5Kyro73bthWSCBJUC5XYQqMnG0dLWuDZmVkzog9dynovhfiVCV4kPSdgSIkqnb++cwCzOVuQ4rDKVwo2XRzQA==", "requires": { "ts-invariant": "^0.4.4", "tslib": "^1.10.0" } }, "@apollo/react-components": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@apollo/react-components/-/react-components-3.1.3.tgz", - "integrity": "sha512-H0l2JKDQMz+LkM93QK7j3ThbNXkWQCduN3s3eKxFN3Rdg7rXsrikJWvx2wQ868jmqy0VhwJbS1vYdRLdh114uQ==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@apollo/react-components/-/react-components-3.1.5.tgz", + "integrity": "sha512-c82VyUuE9VBnJB7bnX+3dmwpIPMhyjMwyoSLyQWPHxz8jK4ak30XszJtqFf4eC4hwvvLYa+Ou6X73Q8V8e2/jg==", "requires": { - "@apollo/react-common": "^3.1.3", - "@apollo/react-hooks": "^3.1.3", + "@apollo/react-common": "^3.1.4", + "@apollo/react-hooks": "^3.1.5", "prop-types": "^15.7.2", "ts-invariant": "^0.4.4", "tslib": "^1.10.0" } }, "@apollo/react-hoc": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@apollo/react-hoc/-/react-hoc-3.1.3.tgz", - "integrity": "sha512-oCPma0uBVPTcYTR5sOvtMbpaWll4xDBvYfKr6YkDorUcQVeNzFu1LK1kmQjJP64bKsaziKYji5ibFaeCnVptmA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@apollo/react-hoc/-/react-hoc-3.1.5.tgz", + "integrity": "sha512-jlZ2pvEnRevLa54H563BU0/xrYSgWQ72GksarxUzCHQW85nmn9wQln0kLBX7Ua7SBt9WgiuYQXQVechaaCulfQ==", "requires": { - "@apollo/react-common": "^3.1.3", - "@apollo/react-components": "^3.1.3", + "@apollo/react-common": "^3.1.4", + "@apollo/react-components": "^3.1.5", "hoist-non-react-statics": "^3.3.0", "ts-invariant": "^0.4.4", "tslib": "^1.10.0" } }, "@apollo/react-hooks": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@apollo/react-hooks/-/react-hooks-3.1.3.tgz", - "integrity": "sha512-reIRO9xKdfi+B4gT/o/hnXuopUnm7WED/ru8VQydPw+C/KG/05Ssg1ZdxFKHa3oxwiTUIDnevtccIH35POanbA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@apollo/react-hooks/-/react-hooks-3.1.5.tgz", + "integrity": "sha512-y0CJ393DLxIIkksRup4nt+vSjxalbZBXnnXxYbviq/woj+zKa431zy0yT4LqyRKpFy9ahMIwxBnBwfwIoupqLQ==", "requires": { - "@apollo/react-common": "^3.1.3", + "@apollo/react-common": "^3.1.4", "@wry/equality": "^0.1.9", "ts-invariant": "^0.4.4", "tslib": "^1.10.0" } }, "@apollo/react-ssr": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@apollo/react-ssr/-/react-ssr-3.1.3.tgz", - "integrity": "sha512-fUTmEYHxSTX1GA43B8vICxXXplpcEBnDwn0IgdAc3eG0p2YK97ZrJDRFCJ5vD7fyDZsrYhMf+rAI3sd+H2SS+A==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@apollo/react-ssr/-/react-ssr-3.1.5.tgz", + "integrity": "sha512-wuLPkKlctNn3u8EU8rlECyktpOUCeekFfb0KhIKknpGY6Lza2Qu0bThx7D9MIbVEzhKadNNrzLcpk0Y8/5UuWg==", "requires": { - "@apollo/react-common": "^3.1.3", - "@apollo/react-hooks": "^3.1.3", + "@apollo/react-common": "^3.1.4", + "@apollo/react-hooks": "^3.1.5", "tslib": "^1.10.0" } }, @@ -17593,15 +17593,15 @@ } }, "react-apollo": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/react-apollo/-/react-apollo-3.1.3.tgz", - "integrity": "sha512-orCZNoAkgveaK5b75y7fw1MSqSHOU/Wuu9rRFOGmRQBSQVZjvV4DI+hj604rHmuN9+WDABxb5W48wTa0F/xNZQ==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/react-apollo/-/react-apollo-3.1.5.tgz", + "integrity": "sha512-xOxMqxORps+WHrUYbjVHPliviomefOpu5Sh35oO3osuOyPTxvrljdfTLGCggMhcXBsDljtS5Oy4g+ijWg3D4JQ==", "requires": { - "@apollo/react-common": "^3.1.3", - "@apollo/react-components": "^3.1.3", - "@apollo/react-hoc": "^3.1.3", - "@apollo/react-hooks": "^3.1.3", - "@apollo/react-ssr": "^3.1.3" + "@apollo/react-common": "^3.1.4", + "@apollo/react-components": "^3.1.5", + "@apollo/react-hoc": "^3.1.5", + "@apollo/react-hooks": "^3.1.5", + "@apollo/react-ssr": "^3.1.5" } }, "react-clientside-effect": { diff --git a/package.json b/package.json index e11e138a5..5550d1f81 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "moment-timezone": "^0.5.26", "qs": "^6.9.0", "react": "^16.12.0", - "react-apollo": "^3.1.3", + "react-apollo": "^3.1.4", "react-dom": "^16.9.0", "react-dropzone": "^8.2.0", "react-error-boundary": "^1.2.5", diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreator.stories.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreator.stories.tsx index 5b8a3e0e8..71416b3ff 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreator.stories.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreator.stories.tsx @@ -19,8 +19,8 @@ const selectedAttributes = [1, 4, 5].map(index => attributes[index]); const selectedWarehouses = [0, 1, 3].map(index => warehouseList[index]); const price: AllOrAttribute = { - all: false, attribute: selectedAttributes[0].id, + mode: "attribute", value: "2.79", values: selectedAttributes[0].values.map((attribute, attributeIndex) => ({ slug: attribute.slug, @@ -29,8 +29,8 @@ const price: AllOrAttribute = { }; const stock: AllOrAttribute = { - all: false, attribute: selectedAttributes[0].id, + mode: "attribute", value: selectedWarehouses.map( (_, warehouseIndex) => (warehouseIndex + 2) * 3 ), @@ -88,8 +88,28 @@ const props: ProductVariantCreatorContentProps = { storiesOf("Views / Products / Create multiple variants", module) .addDecorator(storyFn => {storyFn()}) .addDecorator(Decorator) - .add("choose values", () => ) - .add("prices and SKU", () => ( + .add("choose values", () => ); + +storiesOf( + "Views / Products / Create multiple variants / prices and SKUs", + module +) + .addDecorator(storyFn => {storyFn()}) + .addDecorator(Decorator) + .add("apply to all", () => ( + + )) + .add("apply to attribute", () => ( attributes={selectedAttributes} currencySymbol={currencySymbol} data={data} - onApplyToAllChange={(all, type) => + warehouses={warehouses} + onApplyToAllChange={(mode, type) => dispatchFormDataAction({ applyPriceOrStockToAll: { - all + mode }, type: type === "price" @@ -109,6 +110,14 @@ const ProductVariantCreatorContent: React.FC } ) } + onWarehouseToggle={warehouseId => + dispatchFormDataAction({ + changeWarehouses: { + warehouseId + }, + type: ProductVariantCreateReducerActionType.changeWarehouses + }) + } /> )} {step === ProductVariantCreatorStep.summary && ( diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPage.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPage.tsx index 28817c83e..89135c1af 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPage.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPage.tsx @@ -39,20 +39,22 @@ function canHitNext( case ProductVariantCreatorStep.values: return data.attributes.every(attribute => attribute.values.length > 0); case ProductVariantCreatorStep.prices: - if (data.price.all) { + if (data.price.mode === "all") { if (data.price.value === "") { return false; } - } else { + } else if (data.price.mode === "attribute") { if ( data.price.attribute === "" || data.price.values.some(attributeValue => attributeValue.value === "") ) { return false; } + } else { + return true; } - if (!data.stock.all || data.stock.attribute) { + if (data.stock.mode === "attribute" || data.stock.attribute) { return false; } diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPriceAndSku.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPriceAndSku.tsx index 238338399..8e4e350ee 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPriceAndSku.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPriceAndSku.tsx @@ -2,7 +2,11 @@ import React from "react"; import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; import CardSpacer from "@saleor/components/CardSpacer"; -import { ProductVariantCreateFormData } from "./form"; +import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; +import { + ProductVariantCreateFormData, + VariantCreatorPricesAndSkuMode +} from "./form"; import ProductVariantCreatorPrices from "./ProductVariantCreatorPrices"; import ProductVariantCreatorStock from "./ProductVariantCreatorStock"; @@ -11,7 +15,11 @@ export interface ProductVariantCreatorPriceAndSkuProps { attributes: ProductDetails_product_productType_variantAttributes[]; currencySymbol: string; data: ProductVariantCreateFormData; - onApplyToAllChange: (applyToAll: boolean, type: PriceOrStock) => void; + warehouses: WarehouseFragment[]; + onApplyToAllChange: ( + value: VariantCreatorPricesAndSkuMode, + type: PriceOrStock + ) => void; onApplyToAllPriceOrStockChange: (value: string, type: PriceOrStock) => void; onAttributeSelect: (id: string, type: PriceOrStock) => void; onAttributeValueChange: ( @@ -19,16 +27,19 @@ export interface ProductVariantCreatorPriceAndSkuProps { value: string, type: PriceOrStock ) => void; + onWarehouseToggle: (id: string) => void; } const ProductVariantCreatorPriceAndSku: React.FC = ({ attributes, currencySymbol, data, + warehouses, onApplyToAllPriceOrStockChange, onApplyToAllChange, onAttributeSelect, - onAttributeValueChange + onAttributeValueChange, + onWarehouseToggle }) => ( <> onApplyToAllChange(value, "stock")} onApplyToAllStockChange={value => onApplyToAllPriceOrStockChange(value, "stock") @@ -56,6 +68,7 @@ const ProductVariantCreatorPriceAndSku: React.FC onAttributeValueChange(id, value, "stock") } + onWarehouseToggle={onWarehouseToggle} /> ); diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPrices.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPrices.tsx index 0e0af5ec2..21ddd1938 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPrices.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPrices.tsx @@ -15,7 +15,10 @@ import Hr from "@saleor/components/Hr"; import SingleSelectField from "@saleor/components/SingleSelectField"; import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; import CardTitle from "@saleor/components/CardTitle"; -import { ProductVariantCreateFormData } from "./form"; +import { + ProductVariantCreateFormData, + VariantCreatorPricesAndSkuMode +} from "./form"; import { getPriceAttributeValues } from "./utils"; const useStyles = makeStyles( @@ -41,7 +44,7 @@ export interface ProductVariantCreatorPricesProps { attributes: ProductDetails_product_productType_variantAttributes[]; currencySymbol: string; data: ProductVariantCreateFormData; - onApplyToAllChange: (applyToAll: boolean) => void; + onApplyToAllChange: (applyToAll: VariantCreatorPricesAndSkuMode) => void; onApplyToAllPriceChange: (value: string) => void; onAttributeSelect: (id: string) => void; onAttributeValueChange: (id: string, value: string) => void; @@ -75,14 +78,14 @@ const ProductVariantCreatorPrices: React.FC = })} /> - + } label={intl.formatMessage({ defaultMessage: "Apply single price to all SKUs" })} - onChange={() => onApplyToAllChange(true)} + onChange={() => onApplyToAllChange("all")} /> = /> } label={intl.formatMessage({ defaultMessage: "Apply unique prices by attribute to each SKU" })} - onChange={() => onApplyToAllChange(false)} + onChange={() => onApplyToAllChange("attribute")} /> - {!data.price.all && ( + {data.price.mode === "attribute" && ( <> diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorStock.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorStock.tsx index 2b33e5f84..8ce48200a 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorStock.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorStock.tsx @@ -15,7 +15,14 @@ import Hr from "@saleor/components/Hr"; import SingleSelectField from "@saleor/components/SingleSelectField"; import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; import CardTitle from "@saleor/components/CardTitle"; -import { ProductVariantCreateFormData } from "./form"; +import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; +import CardSpacer from "@saleor/components/CardSpacer"; +import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; +import { isSelected, toggle } from "@saleor/utils/lists"; +import { + ProductVariantCreateFormData, + VariantCreatorPricesAndSkuMode +} from "./form"; import { getStockAttributeValues } from "./utils"; const useStyles = makeStyles( @@ -32,6 +39,30 @@ const useStyles = makeStyles( }, shortInput: { width: "33%" + }, + stockContainer: { + columnGap: theme.spacing(3) + "px", + display: "grid", + gridTemplateColumns: "repeat(3, 288px)", + rowGap: theme.spacing(2) + "px" + }, + stockHeader: { + marginBottom: theme.spacing() + }, + warehouseContainer: { + columnGap: theme.spacing(3) + "px", + display: "grid", + gridTemplateColumns: "repeat(4, 1fr)", + rowGap: theme.spacing(2) + "px" + }, + warehouseHeader: { + marginBottom: theme.spacing() + }, + warehouseName: { + marginBottom: theme.spacing() + }, + warehouseSubheader: { + marginBottom: theme.spacing(2) } }), { name: "ProductVariantCreatorStock" } @@ -40,20 +71,24 @@ const useStyles = makeStyles( export interface ProductVariantCreatorStockProps { attributes: ProductDetails_product_productType_variantAttributes[]; data: ProductVariantCreateFormData; - onApplyToAllChange: (applyToAll: boolean) => void; + warehouses: WarehouseFragment[]; + onApplyToAllChange: (mode: VariantCreatorPricesAndSkuMode) => void; onApplyToAllStockChange: (value: string) => void; onAttributeSelect: (id: string) => void; onAttributeValueChange: (id: string, value: string) => void; + onWarehouseToggle: (id: string) => void; } const ProductVariantCreatorStock: React.FC = props => { const { attributes, data, + warehouses, onApplyToAllChange, onApplyToAllStockChange, onAttributeSelect, - onAttributeValueChange + onAttributeValueChange, + onWarehouseToggle } = props; const classes = useStyles(props); const intl = useIntl(); @@ -73,98 +108,173 @@ const ProductVariantCreatorStock: React.FC = pr })} /> - + {warehouses.length > 1 && ( + <> + + + + + acc + attr.values.length, + 0 + ) + }} + /> + +
+ {warehouses.map(warehouse => ( + a === b + )} + name={`warehouse:${warehouse.id}`} + label={warehouse.name} + onChange={() => onWarehouseToggle(warehouse.id)} + key={warehouse.id} + /> + ))} +
+ +
+ + + )} + + + + } label={intl.formatMessage({ defaultMessage: "Apply single stock to all SKUs" })} - onChange={() => onApplyToAllChange(true)} - /> - - onApplyToAllStockChange(event.target.value)} + onChange={() => onApplyToAllChange("all")} /> + {data.stock.mode === "all" && ( +
+ {data.warehouses.map((warehouseId, warehouseIndex) => ( +
+ + { + warehouses.find(warehouse => warehouse.id === warehouseId) + .name + } + + + onApplyToAllStockChange(event.target.value) + } + /> +
+ ))} +
+ )} } label={intl.formatMessage({ defaultMessage: "Apply unique stock by attribute to each SKU" })} - onChange={() => onApplyToAllChange(false)} + onChange={() => onApplyToAllChange("attribute")} + /> + {data.stock.mode === "attribute" && ( + <> + + +
+ + + +
+
+ +
+
+ {stockAttributeValues && + stockAttributeValues.map(attributeValue => ( + +
+ + +
+ {attributeValue.name} +
+
+ value.slug === attributeValue.slug + ).value + } + onChange={event => + onAttributeValueChange( + attributeValue.slug, + event.target.value + ) + } + /> +
+
+
+ ))} + + )} + + } + label={intl.formatMessage({ + defaultMessage: "Skip stock for now" + })} + onChange={() => onApplyToAllChange("skip")} />
- {!data.stock.all && ( - <> - - -
- - - -
-
- -
-
- {stockAttributeValues && - stockAttributeValues.map(attributeValue => ( - -
- - -
- {attributeValue.name} -
-
- value.slug === attributeValue.slug - ).value - } - onChange={event => - onAttributeValueChange( - attributeValue.slug, - event.target.value - ) - } - /> -
-
-
- ))} - - )}
); diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorValues.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorValues.tsx index 74e6fe431..b482bbd30 100644 --- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorValues.tsx +++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorValues.tsx @@ -52,7 +52,7 @@ const ProductVariantCreatorValues: React.FC = value.slug, data.attributes.find( dataAttribute => attribute.id === dataAttribute.id - ).values, + )?.values || [], (a, b) => a === b )} name={`value:${value.slug}`} diff --git a/src/products/components/ProductVariantCreatorPage/createVariants.ts b/src/products/components/ProductVariantCreatorPage/createVariants.ts index 5ec21dd15..231ad44a8 100644 --- a/src/products/components/ProductVariantCreatorPage/createVariants.ts +++ b/src/products/components/ProductVariantCreatorPage/createVariants.ts @@ -26,16 +26,32 @@ function getAttributeValuePriceOrStock( return attributeValue.value; } +function getValueFromMode( + attributes: CreateVariantInput, + priceOrStock: AllOrAttribute, + skipValue: T +): T { + switch (priceOrStock.mode) { + case "all": + return priceOrStock.value; + case "attribute": + return getAttributeValuePriceOrStock(attributes, priceOrStock); + case "skip": + return skipValue; + } +} + function createVariant( data: ProductVariantCreateFormData, attributes: CreateVariantInput ): ProductVariantBulkCreateInput { - const priceOverride = data.price.all - ? data.price.value - : getAttributeValuePriceOrStock(attributes, data.price); - const stocks = data.stock.all - ? data.stock.value - : getAttributeValuePriceOrStock(attributes, data.stock); + const priceOverride = getValueFromMode(attributes, data.price, "0"); + const stocks = getValueFromMode( + attributes, + data.stock, + data.warehouses.map(() => 0) + ); + return { attributes: attributes.map(attribute => ({ id: attribute.attributeId, @@ -91,8 +107,8 @@ export function createVariants( data: ProductVariantCreateFormData ): ProductVariantBulkCreateInput[] { if ( - (!data.price.all && !data.price.attribute) || - (!data.stock.all && !data.stock.attribute) + (data.price.mode === "attribute" && !data.price.attribute) || + (data.stock.mode === "attribute" && !data.stock.attribute) ) { return []; } diff --git a/src/products/components/ProductVariantCreatorPage/form.ts b/src/products/components/ProductVariantCreatorPage/form.ts index 689f1b784..db3f2c46d 100644 --- a/src/products/components/ProductVariantCreatorPage/form.ts +++ b/src/products/components/ProductVariantCreatorPage/form.ts @@ -6,8 +6,9 @@ export interface AttributeValue { slug: string; value: T; } +export type VariantCreatorPricesAndSkuMode = "all" | "attribute" | "skip"; export interface AllOrAttribute { - all: boolean; + mode: VariantCreatorPricesAndSkuMode; attribute: string; value: T; values: Array>; @@ -34,14 +35,14 @@ export const createInitialForm = ( values: [] })), price: { - all: true, attribute: undefined, + mode: "all", value: price || "", values: [] }, stock: { - all: true, attribute: undefined, + mode: "all", value: warehouses.length === 1 ? [0] : [], values: [] }, diff --git a/src/products/components/ProductVariantCreatorPage/reducer.ts b/src/products/components/ProductVariantCreatorPage/reducer.ts index ec2c26a33..64e7b785a 100644 --- a/src/products/components/ProductVariantCreatorPage/reducer.ts +++ b/src/products/components/ProductVariantCreatorPage/reducer.ts @@ -8,11 +8,16 @@ import { } from "@saleor/utils/lists"; import { StockInput } from "@saleor/types/globalTypes"; import { createVariants } from "./createVariants"; -import { ProductVariantCreateFormData } from "./form"; +import { + ProductVariantCreateFormData, + VariantCreatorPricesAndSkuMode +} from "./form"; export enum ProductVariantCreateReducerActionType { applyPriceToAll, + applyPriceToAttribute, applyStockToAll, + applyStockToAttribute, changeApplyPriceToAllValue, changeApplyPriceToAttributeId, changeApplyStockToAllValue, @@ -21,6 +26,7 @@ export enum ProductVariantCreateReducerActionType { changeAttributeValueStock, changeVariantData, changeVariantStockData, + changeWarehouses, deleteVariant, reload, selectValue @@ -28,7 +34,7 @@ export enum ProductVariantCreateReducerActionType { export type VariantField = "price" | "sku"; export interface ProductVariantCreateReducerAction { applyPriceOrStockToAll?: { - all: boolean; + mode: VariantCreatorPricesAndSkuMode; }; changeApplyPriceToAllValue?: { price: string; @@ -52,6 +58,9 @@ export interface ProductVariantCreateReducerAction { stock: StockInput; variantIndex: number; }; + changeWarehouses?: { + warehouseId: string; + }; deleteVariant?: { variantIndex: number; }; @@ -119,26 +128,26 @@ function selectValue( function applyPriceToAll( state: ProductVariantCreateFormData, - value: boolean + mode: VariantCreatorPricesAndSkuMode ): ProductVariantCreateFormData { return { ...state, price: { ...state.price, - all: value + mode } }; } function applyStockToAll( state: ProductVariantCreateFormData, - value: boolean + mode: VariantCreatorPricesAndSkuMode ): ProductVariantCreateFormData { return { ...state, stock: { ...state.stock, - all: value + mode } }; } @@ -318,6 +327,16 @@ function changeVariantStockData( }; } +function changeWarehouses( + state: ProductVariantCreateFormData, + warehouseId: string +): ProductVariantCreateFormData { + return { + ...state, + warehouses: toggle(warehouseId, state.warehouses, (a, b) => a === b) + }; +} + function deleteVariant( state: ProductVariantCreateFormData, variantIndex: number @@ -349,9 +368,9 @@ function reduceProductVariantCreateFormData( action.selectValue.valueId ); case ProductVariantCreateReducerActionType.applyPriceToAll: - return applyPriceToAll(prevState, action.applyPriceOrStockToAll.all); + return applyPriceToAll(prevState, action.applyPriceOrStockToAll.mode); case ProductVariantCreateReducerActionType.applyStockToAll: - return applyStockToAll(prevState, action.applyPriceOrStockToAll.all); + return applyStockToAll(prevState, action.applyPriceOrStockToAll.mode); case ProductVariantCreateReducerActionType.changeAttributeValuePrice: return changeAttributeValuePrice( prevState, @@ -383,8 +402,8 @@ function reduceProductVariantCreateFormData( case ProductVariantCreateReducerActionType.changeApplyStockToAllValue: return changeApplyStockToAllValue( prevState, - action.changeApplyStockToAllValue.quantity, - action.changeApplyStockToAllValue.warehouseIndex + action.changeApplyStockToAllValue.warehouseIndex, + action.changeApplyStockToAllValue.quantity ); case ProductVariantCreateReducerActionType.changeVariantData: return changeVariantData( @@ -399,6 +418,8 @@ function reduceProductVariantCreateFormData( action.changeVariantStockData.stock, action.changeVariantStockData.variantIndex ); + case ProductVariantCreateReducerActionType.changeWarehouses: + return changeWarehouses(prevState, action.changeWarehouses.warehouseId); case ProductVariantCreateReducerActionType.deleteVariant: return deleteVariant(prevState, action.deleteVariant.variantIndex); case ProductVariantCreateReducerActionType.reload: diff --git a/src/products/queries.ts b/src/products/queries.ts index 621f185db..0b43ce676 100644 --- a/src/products/queries.ts +++ b/src/products/queries.ts @@ -103,6 +103,7 @@ const productVariantAttributesFragment = gql` } } productType { + id variantAttributes { id name diff --git a/src/utils/lists/lists.ts b/src/utils/lists/lists.ts index 3401c665b..5526b39b1 100644 --- a/src/utils/lists/lists.ts +++ b/src/utils/lists/lists.ts @@ -45,6 +45,9 @@ export function updateAtIndex( list: List, index: number ) { + if (!index.toFixed) { + throw new Error("Index is not a number"); + } return addAtIndex(data, removeAtIndex(list, index), index); }