Split components into pricing and stock sections

This commit is contained in:
dominik-zeglen 2020-04-06 16:32:39 +02:00
parent 1b7eac3596
commit 688fc83f55
5 changed files with 369 additions and 258 deletions

View file

@ -5,7 +5,7 @@ import { ProductVariantBulkCreate_productVariantBulkCreate_errors } from "@saleo
import { isSelected } from "@saleor/utils/lists"; import { isSelected } from "@saleor/utils/lists";
import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment";
import { ProductVariantCreateFormData } from "./form"; import { ProductVariantCreateFormData } from "./form";
import ProductVariantCreatePrices from "./ProductVariantCreatorPrices"; import ProductVariantCreatePriceAndSku from "./ProductVariantCreatorPriceAndSku";
import ProductVariantCreateSummary from "./ProductVariantCreatorSummary"; import ProductVariantCreateSummary from "./ProductVariantCreatorSummary";
import ProductVariantCreateValues from "./ProductVariantCreatorValues"; import ProductVariantCreateValues from "./ProductVariantCreatorValues";
import { import {
@ -60,11 +60,11 @@ const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps>
/> />
)} )}
{step === ProductVariantCreatorStep.prices && ( {step === ProductVariantCreatorStep.prices && (
<ProductVariantCreatePrices <ProductVariantCreatePriceAndSku
attributes={selectedAttributes} attributes={selectedAttributes}
currencySymbol={currencySymbol} currencySymbol={currencySymbol}
data={data} data={data}
onApplyPriceOrStockChange={(all, type) => onApplyToAllChange={(all, type) =>
dispatchFormDataAction({ dispatchFormDataAction({
applyPriceOrStockToAll: { applyPriceOrStockToAll: {
all all
@ -75,17 +75,16 @@ const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps>
: ProductVariantCreateReducerActionType.applyStockToAll : ProductVariantCreateReducerActionType.applyStockToAll
}) })
} }
// TODO: Stock change is not fixed in this PR so we won't include it here onApplyToAllPriceOrStockChange={(value, type) =>
onApplyToAllChange={(price, type) => dispatchFormDataAction({
dispatchFormDataAction(
type === "price" && {
changeApplyPriceToAllValue: { changeApplyPriceToAllValue: {
price price: value
}, },
type: type:
ProductVariantCreateReducerActionType.changeApplyPriceToAllValue type === "price"
} ? ProductVariantCreateReducerActionType.applyPriceToAll
) : ProductVariantCreateReducerActionType.applyStockToAll
})
} }
onAttributeSelect={(attributeId, type) => onAttributeSelect={(attributeId, type) =>
dispatchFormDataAction({ dispatchFormDataAction({
@ -98,7 +97,6 @@ const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps>
: ProductVariantCreateReducerActionType.changeApplyStockToAttributeId : ProductVariantCreateReducerActionType.changeApplyStockToAttributeId
}) })
} }
// TODO: Stock change is not fixed in this PR so we won't include it here
onAttributeValueChange={(valueId, price, type) => onAttributeValueChange={(valueId, price, type) =>
dispatchFormDataAction( dispatchFormDataAction(
type === "price" && { type === "price" && {

View file

@ -0,0 +1,65 @@
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 ProductVariantCreatorPrices from "./ProductVariantCreatorPrices";
import ProductVariantCreatorStock from "./ProductVariantCreatorStock";
export type PriceOrStock = "price" | "stock";
export interface ProductVariantCreatorPriceAndSkuProps {
attributes: ProductDetails_product_productType_variantAttributes[];
currencySymbol: string;
data: ProductVariantCreateFormData;
onApplyToAllChange: (applyToAll: boolean, type: PriceOrStock) => void;
onApplyToAllPriceOrStockChange: (value: string, type: PriceOrStock) => void;
onAttributeSelect: (id: string, type: PriceOrStock) => void;
onAttributeValueChange: (
id: string,
value: string,
type: PriceOrStock
) => void;
}
const ProductVariantCreatorPriceAndSku: React.FC<ProductVariantCreatorPriceAndSkuProps> = ({
attributes,
currencySymbol,
data,
onApplyToAllPriceOrStockChange,
onApplyToAllChange,
onAttributeSelect,
onAttributeValueChange
}) => (
<>
<ProductVariantCreatorPrices
attributes={attributes}
currencySymbol={currencySymbol}
data={data}
onApplyToAllChange={value => onApplyToAllChange(value, "price")}
onApplyToAllPriceChange={value =>
onApplyToAllPriceOrStockChange(value, "price")
}
onAttributeSelect={id => onAttributeSelect(id, "price")}
onAttributeValueChange={(id, value) =>
onAttributeValueChange(id, value, "price")
}
/>
<CardSpacer />
<ProductVariantCreatorStock
attributes={attributes}
data={data}
onApplyToAllChange={value => onApplyToAllChange(value, "stock")}
onApplyToAllStockChange={value =>
onApplyToAllPriceOrStockChange(value, "stock")
}
onAttributeSelect={id => onAttributeSelect(id, "stock")}
onAttributeValueChange={(id, value) =>
onAttributeValueChange(id, value, "stock")
}
/>
</>
);
ProductVariantCreatorPriceAndSku.displayName =
"ProductVariantCreatorPriceAndSku";
export default ProductVariantCreatorPriceAndSku;

View file

@ -15,9 +15,8 @@ import Hr from "@saleor/components/Hr";
import SingleSelectField from "@saleor/components/SingleSelectField"; import SingleSelectField from "@saleor/components/SingleSelectField";
import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails"; import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import CardSpacer from "@saleor/components/CardSpacer";
import { ProductVariantCreateFormData } from "./form"; import { ProductVariantCreateFormData } from "./form";
import { getPriceAttributeValues, getStockAttributeValues } from "./utils"; import { getPriceAttributeValues } from "./utils";
const useStyles = makeStyles( const useStyles = makeStyles(
theme => ({ theme => ({
@ -38,19 +37,14 @@ const useStyles = makeStyles(
{ name: "ProductVariantCreatorPrices" } { name: "ProductVariantCreatorPrices" }
); );
export type PriceOrStock = "price" | "stock";
export interface ProductVariantCreatorPricesProps { export interface ProductVariantCreatorPricesProps {
attributes: ProductDetails_product_productType_variantAttributes[]; attributes: ProductDetails_product_productType_variantAttributes[];
currencySymbol: string; currencySymbol: string;
data: ProductVariantCreateFormData; data: ProductVariantCreateFormData;
onApplyPriceOrStockChange: (applyToAll: boolean, type: PriceOrStock) => void; onApplyToAllChange: (applyToAll: boolean) => void;
onApplyToAllChange: (value: string, type: PriceOrStock) => void; onApplyToAllPriceChange: (value: string) => void;
onAttributeSelect: (id: string, type: PriceOrStock) => void; onAttributeSelect: (id: string) => void;
onAttributeValueChange: ( onAttributeValueChange: (id: string, value: string) => void;
id: string,
value: string,
type: PriceOrStock
) => void;
} }
const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> = props => { const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> = props => {
@ -58,8 +52,8 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
attributes, attributes,
currencySymbol, currencySymbol,
data, data,
onApplyPriceOrStockChange,
onApplyToAllChange, onApplyToAllChange,
onApplyToAllPriceChange,
onAttributeSelect, onAttributeSelect,
onAttributeValueChange onAttributeValueChange
} = props; } = props;
@ -71,10 +65,8 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
value: attribute.id value: attribute.id
})); }));
const priceAttributeValues = getPriceAttributeValues(data, attributes); const priceAttributeValues = getPriceAttributeValues(data, attributes);
const stockAttributeValues = getStockAttributeValues(data, attributes);
return ( return (
<>
<Card> <Card>
<CardTitle <CardTitle
title={intl.formatMessage({ title={intl.formatMessage({
@ -83,16 +75,14 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
})} })}
/> />
<CardContent> <CardContent>
<RadioGroup <RadioGroup value={data.price.all ? "applyToAll" : "applyToAttribute"}>
value={data.price.all ? "applyToAll" : "applyToAttribute"}
>
<FormControlLabel <FormControlLabel
value="applyToAll" value="applyToAll"
control={<Radio color="primary" />} control={<Radio color="primary" />}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Apply single price to all SKUs" defaultMessage: "Apply single price to all SKUs"
})} })}
onChange={() => onApplyPriceOrStockChange(true, "price")} onChange={() => onApplyToAllChange(true)}
/> />
<FormSpacer /> <FormSpacer />
<TextField <TextField
@ -109,9 +99,7 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
id: "productVariantCreatePricesPriceInputLabel" id: "productVariantCreatePricesPriceInputLabel"
})} })}
value={data.price.value} value={data.price.value}
onChange={event => onChange={event => onApplyToAllPriceChange(event.target.value)}
onApplyToAllChange(event.target.value, "price")
}
/> />
<FormSpacer /> <FormSpacer />
<FormControlLabel <FormControlLabel
@ -120,7 +108,7 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Apply unique prices by attribute to each SKU" defaultMessage: "Apply unique prices by attribute to each SKU"
})} })}
onChange={() => onApplyPriceOrStockChange(false, "price")} onChange={() => onApplyToAllChange(false)}
/> />
</RadioGroup> </RadioGroup>
{!data.price.all && ( {!data.price.all && (
@ -143,9 +131,7 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
description: "variant attribute" description: "variant attribute"
})} })}
value={data.price.attribute} value={data.price.attribute}
onChange={event => onChange={event => onAttributeSelect(event.target.value)}
onAttributeSelect(event.target.value, "price")
}
/> />
</div> </div>
</Grid> </Grid>
@ -181,8 +167,7 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
onChange={event => onChange={event =>
onAttributeValueChange( onAttributeValueChange(
attributeValue.slug, attributeValue.slug,
event.target.value, event.target.value
"price"
) )
} }
/> />
@ -194,117 +179,6 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
)} )}
</CardContent> </CardContent>
</Card> </Card>
<CardSpacer />
<Card>
<CardTitle
title={intl.formatMessage({
defaultMessage: "Stock",
description: "variant stock, header"
})}
/>
<CardContent>
<RadioGroup
value={data.stock.all ? "applyToAll" : "applyToAttribute"}
>
<FormControlLabel
value="applyToAll"
control={<Radio color="primary" />}
label={intl.formatMessage({
defaultMessage: "Apply single stock to all SKUs"
})}
onChange={() => onApplyPriceOrStockChange(true, "stock")}
/>
<FormSpacer />
<TextField
className={classes.shortInput}
inputProps={{
min: 0,
type: "number"
}}
label={intl.formatMessage({
defaultMessage: "Stock",
id: "productVariantCreatePricesStockInputLabel"
})}
value={data.stock.value}
onChange={event =>
onApplyToAllChange(event.target.value, "stock")
}
/>
<FormSpacer />
<FormControlLabel
value="applyToAttribute"
control={<Radio color="primary" />}
label={intl.formatMessage({
defaultMessage: "Apply unique stock by attribute to each SKU"
})}
onChange={() => onApplyPriceOrStockChange(false, "stock")}
/>
</RadioGroup>
{!data.stock.all && (
<>
<FormSpacer />
<Grid variant="uniform">
<div className={classes.label}>
<Typography>
<FormattedMessage
defaultMessage="Choose attribute"
description="variant attribute"
/>
</Typography>
</div>
<div>
<SingleSelectField
choices={attributeChoices}
label={intl.formatMessage({
defaultMessage: "Attribute",
description: "variant attribute"
})}
value={data.stock.attribute}
onChange={event =>
onAttributeSelect(event.target.value, "stock")
}
/>
</div>
</Grid>
{stockAttributeValues &&
stockAttributeValues.map(attributeValue => (
<React.Fragment key={attributeValue.id}>
<Hr className={classes.hrAttribute} />
<FormSpacer />
<Grid variant="uniform">
<div className={classes.label}>
<Typography>{attributeValue.name}</Typography>
</div>
<div>
<TextField
label={intl.formatMessage({
defaultMessage: "Stock",
description: "variant stock",
id: "productVariantCreatePricesSetStockPlaceholder"
})}
fullWidth
value={
data.stock.values.find(
value => value.slug === attributeValue.slug
).value
}
onChange={event =>
onAttributeValueChange(
attributeValue.slug,
event.target.value,
"stock"
)
}
/>
</div>
</Grid>
</React.Fragment>
))}
</>
)}
</CardContent>
</Card>
</>
); );
}; };

View file

@ -0,0 +1,174 @@
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Radio from "@material-ui/core/Radio";
import RadioGroup from "@material-ui/core/RadioGroup";
import { makeStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import Typography from "@material-ui/core/Typography";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import FormSpacer from "@saleor/components/FormSpacer";
import Grid from "@saleor/components/Grid";
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 { getStockAttributeValues } from "./utils";
const useStyles = makeStyles(
theme => ({
hr: {
marginBottom: theme.spacing(),
marginTop: theme.spacing(0.5)
},
hrAttribute: {
marginTop: theme.spacing(2)
},
label: {
alignSelf: "center"
},
shortInput: {
width: "33%"
}
}),
{ name: "ProductVariantCreatorStock" }
);
export interface ProductVariantCreatorStockProps {
attributes: ProductDetails_product_productType_variantAttributes[];
data: ProductVariantCreateFormData;
onApplyToAllChange: (applyToAll: boolean) => void;
onApplyToAllStockChange: (value: string) => void;
onAttributeSelect: (id: string) => void;
onAttributeValueChange: (id: string, value: string) => void;
}
const ProductVariantCreatorStock: React.FC<ProductVariantCreatorStockProps> = props => {
const {
attributes,
data,
onApplyToAllChange,
onApplyToAllStockChange,
onAttributeSelect,
onAttributeValueChange
} = props;
const classes = useStyles(props);
const intl = useIntl();
const attributeChoices = attributes.map(attribute => ({
label: attribute.name,
value: attribute.id
}));
const stockAttributeValues = getStockAttributeValues(data, attributes);
return (
<Card>
<CardTitle
title={intl.formatMessage({
defaultMessage: "Stock and Warehousing",
description: "variant stock, header"
})}
/>
<CardContent>
<RadioGroup value={data.stock.all ? "applyToAll" : "applyToAttribute"}>
<FormControlLabel
value="applyToAll"
control={<Radio color="primary" />}
label={intl.formatMessage({
defaultMessage: "Apply single stock to all SKUs"
})}
onChange={() => onApplyToAllChange(true)}
/>
<FormSpacer />
<TextField
className={classes.shortInput}
inputProps={{
min: 0,
type: "number"
}}
label={intl.formatMessage({
defaultMessage: "Stock",
id: "productVariantCreatePricesStockInputLabel"
})}
value={data.stock.value}
onChange={event => onApplyToAllStockChange(event.target.value)}
/>
<FormSpacer />
<FormControlLabel
value="applyToAttribute"
control={<Radio color="primary" />}
label={intl.formatMessage({
defaultMessage: "Apply unique stock by attribute to each SKU"
})}
onChange={() => onApplyToAllChange(false)}
/>
</RadioGroup>
{!data.stock.all && (
<>
<FormSpacer />
<Grid variant="uniform">
<div className={classes.label}>
<Typography>
<FormattedMessage
defaultMessage="Choose attribute"
description="variant attribute"
/>
</Typography>
</div>
<div>
<SingleSelectField
choices={attributeChoices}
label={intl.formatMessage({
defaultMessage: "Attribute",
description: "variant attribute"
})}
value={data.stock.attribute}
onChange={onAttributeSelect}
/>
</div>
</Grid>
{stockAttributeValues &&
stockAttributeValues.map(attributeValue => (
<React.Fragment key={attributeValue.id}>
<Hr className={classes.hrAttribute} />
<FormSpacer />
<Grid variant="uniform">
<div className={classes.label}>
<Typography>{attributeValue.name}</Typography>
</div>
<div>
<TextField
label={intl.formatMessage({
defaultMessage: "Stock",
description: "variant stock",
id: "productVariantCreatePricesSetStockPlaceholder"
})}
fullWidth
value={
data.stock.values.find(
value => value.slug === attributeValue.slug
).value
}
onChange={event =>
onAttributeValueChange(
attributeValue.slug,
event.target.value
)
}
/>
</div>
</Grid>
</React.Fragment>
))}
</>
)}
</CardContent>
</Card>
);
};
ProductVariantCreatorStock.displayName = "ProductVariantCreatorStock";
export default ProductVariantCreatorStock;

View file

@ -63,7 +63,7 @@ const ProductVariantCreator: React.FC<ProductVariantCreatorProps> = ({
variables: { id, inputs } variables: { id, inputs }
}) })
} }
warehouses={data?.warehouses.edges.map(edge => edge.node)} warehouses={data?.warehouses.edges.map(edge => edge.node) || []}
/> />
</> </>
); );