Split components into pricing and stock sections
This commit is contained in:
parent
1b7eac3596
commit
688fc83f55
5 changed files with 369 additions and 258 deletions
|
@ -5,7 +5,7 @@ import { ProductVariantBulkCreate_productVariantBulkCreate_errors } from "@saleo
|
|||
import { isSelected } from "@saleor/utils/lists";
|
||||
import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment";
|
||||
import { ProductVariantCreateFormData } from "./form";
|
||||
import ProductVariantCreatePrices from "./ProductVariantCreatorPrices";
|
||||
import ProductVariantCreatePriceAndSku from "./ProductVariantCreatorPriceAndSku";
|
||||
import ProductVariantCreateSummary from "./ProductVariantCreatorSummary";
|
||||
import ProductVariantCreateValues from "./ProductVariantCreatorValues";
|
||||
import {
|
||||
|
@ -60,11 +60,11 @@ const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps>
|
|||
/>
|
||||
)}
|
||||
{step === ProductVariantCreatorStep.prices && (
|
||||
<ProductVariantCreatePrices
|
||||
<ProductVariantCreatePriceAndSku
|
||||
attributes={selectedAttributes}
|
||||
currencySymbol={currencySymbol}
|
||||
data={data}
|
||||
onApplyPriceOrStockChange={(all, type) =>
|
||||
onApplyToAllChange={(all, type) =>
|
||||
dispatchFormDataAction({
|
||||
applyPriceOrStockToAll: {
|
||||
all
|
||||
|
@ -75,17 +75,16 @@ const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps>
|
|||
: ProductVariantCreateReducerActionType.applyStockToAll
|
||||
})
|
||||
}
|
||||
// TODO: Stock change is not fixed in this PR so we won't include it here
|
||||
onApplyToAllChange={(price, type) =>
|
||||
dispatchFormDataAction(
|
||||
type === "price" && {
|
||||
onApplyToAllPriceOrStockChange={(value, type) =>
|
||||
dispatchFormDataAction({
|
||||
changeApplyPriceToAllValue: {
|
||||
price
|
||||
price: value
|
||||
},
|
||||
type:
|
||||
ProductVariantCreateReducerActionType.changeApplyPriceToAllValue
|
||||
}
|
||||
)
|
||||
type === "price"
|
||||
? ProductVariantCreateReducerActionType.applyPriceToAll
|
||||
: ProductVariantCreateReducerActionType.applyStockToAll
|
||||
})
|
||||
}
|
||||
onAttributeSelect={(attributeId, type) =>
|
||||
dispatchFormDataAction({
|
||||
|
@ -98,7 +97,6 @@ const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps>
|
|||
: ProductVariantCreateReducerActionType.changeApplyStockToAttributeId
|
||||
})
|
||||
}
|
||||
// TODO: Stock change is not fixed in this PR so we won't include it here
|
||||
onAttributeValueChange={(valueId, price, type) =>
|
||||
dispatchFormDataAction(
|
||||
type === "price" && {
|
||||
|
|
|
@ -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;
|
|
@ -15,9 +15,8 @@ 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 CardSpacer from "@saleor/components/CardSpacer";
|
||||
import { ProductVariantCreateFormData } from "./form";
|
||||
import { getPriceAttributeValues, getStockAttributeValues } from "./utils";
|
||||
import { getPriceAttributeValues } from "./utils";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
|
@ -38,19 +37,14 @@ const useStyles = makeStyles(
|
|||
{ name: "ProductVariantCreatorPrices" }
|
||||
);
|
||||
|
||||
export type PriceOrStock = "price" | "stock";
|
||||
export interface ProductVariantCreatorPricesProps {
|
||||
attributes: ProductDetails_product_productType_variantAttributes[];
|
||||
currencySymbol: string;
|
||||
data: ProductVariantCreateFormData;
|
||||
onApplyPriceOrStockChange: (applyToAll: boolean, type: PriceOrStock) => void;
|
||||
onApplyToAllChange: (value: string, type: PriceOrStock) => void;
|
||||
onAttributeSelect: (id: string, type: PriceOrStock) => void;
|
||||
onAttributeValueChange: (
|
||||
id: string,
|
||||
value: string,
|
||||
type: PriceOrStock
|
||||
) => void;
|
||||
onApplyToAllChange: (applyToAll: boolean) => void;
|
||||
onApplyToAllPriceChange: (value: string) => void;
|
||||
onAttributeSelect: (id: string) => void;
|
||||
onAttributeValueChange: (id: string, value: string) => void;
|
||||
}
|
||||
|
||||
const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> = props => {
|
||||
|
@ -58,8 +52,8 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
|
|||
attributes,
|
||||
currencySymbol,
|
||||
data,
|
||||
onApplyPriceOrStockChange,
|
||||
onApplyToAllChange,
|
||||
onApplyToAllPriceChange,
|
||||
onAttributeSelect,
|
||||
onAttributeValueChange
|
||||
} = props;
|
||||
|
@ -71,10 +65,8 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
|
|||
value: attribute.id
|
||||
}));
|
||||
const priceAttributeValues = getPriceAttributeValues(data, attributes);
|
||||
const stockAttributeValues = getStockAttributeValues(data, attributes);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
|
@ -83,16 +75,14 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
|
|||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
<RadioGroup
|
||||
value={data.price.all ? "applyToAll" : "applyToAttribute"}
|
||||
>
|
||||
<RadioGroup value={data.price.all ? "applyToAll" : "applyToAttribute"}>
|
||||
<FormControlLabel
|
||||
value="applyToAll"
|
||||
control={<Radio color="primary" />}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Apply single price to all SKUs"
|
||||
})}
|
||||
onChange={() => onApplyPriceOrStockChange(true, "price")}
|
||||
onChange={() => onApplyToAllChange(true)}
|
||||
/>
|
||||
<FormSpacer />
|
||||
<TextField
|
||||
|
@ -109,9 +99,7 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
|
|||
id: "productVariantCreatePricesPriceInputLabel"
|
||||
})}
|
||||
value={data.price.value}
|
||||
onChange={event =>
|
||||
onApplyToAllChange(event.target.value, "price")
|
||||
}
|
||||
onChange={event => onApplyToAllPriceChange(event.target.value)}
|
||||
/>
|
||||
<FormSpacer />
|
||||
<FormControlLabel
|
||||
|
@ -120,7 +108,7 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
|
|||
label={intl.formatMessage({
|
||||
defaultMessage: "Apply unique prices by attribute to each SKU"
|
||||
})}
|
||||
onChange={() => onApplyPriceOrStockChange(false, "price")}
|
||||
onChange={() => onApplyToAllChange(false)}
|
||||
/>
|
||||
</RadioGroup>
|
||||
{!data.price.all && (
|
||||
|
@ -143,9 +131,7 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
|
|||
description: "variant attribute"
|
||||
})}
|
||||
value={data.price.attribute}
|
||||
onChange={event =>
|
||||
onAttributeSelect(event.target.value, "price")
|
||||
}
|
||||
onChange={event => onAttributeSelect(event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
|
@ -181,8 +167,7 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
|
|||
onChange={event =>
|
||||
onAttributeValueChange(
|
||||
attributeValue.slug,
|
||||
event.target.value,
|
||||
"price"
|
||||
event.target.value
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
@ -194,117 +179,6 @@ const ProductVariantCreatorPrices: React.FC<ProductVariantCreatorPricesProps> =
|
|||
)}
|
||||
</CardContent>
|
||||
</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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -63,7 +63,7 @@ const ProductVariantCreator: React.FC<ProductVariantCreatorProps> = ({
|
|||
variables: { id, inputs }
|
||||
})
|
||||
}
|
||||
warehouses={data?.warehouses.edges.map(edge => edge.node)}
|
||||
warehouses={data?.warehouses.edges.map(edge => edge.node) || []}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue