Add ability to create stock in multiple warehouses

This commit is contained in:
dominik-zeglen 2020-04-09 12:13:42 +02:00
parent b776321e0a
commit 715303e025
6 changed files with 133 additions and 99 deletions

View file

@ -24,16 +24,15 @@ export interface ProductVariantCreatorContentProps {
warehouses: WarehouseFragment[]; warehouses: WarehouseFragment[];
} }
const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps> = props => { const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps> = ({
const { attributes,
attributes, currencySymbol,
currencySymbol, data,
data, dispatchFormDataAction,
dispatchFormDataAction, errors,
errors, step,
step, warehouses
warehouses }) => {
} = props;
const selectedAttributes = attributes.filter(attribute => const selectedAttributes = attributes.filter(attribute =>
isSelected( isSelected(
attribute.id, attribute.id,
@ -104,17 +103,26 @@ const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps>
: ProductVariantCreateReducerActionType.changeApplyStockToAttributeId : ProductVariantCreateReducerActionType.changeApplyStockToAttributeId
}) })
} }
onAttributeValueChange={(valueId, price, type) => onAttributePriceChange={(valueId, price) =>
dispatchFormDataAction( dispatchFormDataAction({
type === "price" && { changeAttributeValuePrice: {
changeAttributeValuePrice: { price,
price, valueId
valueId },
}, type:
type: ProductVariantCreateReducerActionType.changeAttributeValuePrice
ProductVariantCreateReducerActionType.changeAttributeValuePrice })
} }
) onAttributeStockChange={(valueId, quantity, warehouseIndex) =>
dispatchFormDataAction({
changeAttributeValueStock: {
quantity,
valueId,
warehouseIndex
},
type:
ProductVariantCreateReducerActionType.changeAttributeValueStock
})
} }
onWarehouseToggle={warehouseId => onWarehouseToggle={warehouseId =>
dispatchFormDataAction({ dispatchFormDataAction({

View file

@ -50,11 +50,9 @@ function canHitNext(
) { ) {
return false; return false;
} }
} else {
return true;
} }
if (data.stock.mode === "attribute" || data.stock.attribute) { if (data.stock.mode === "attribute" && data.stock.attribute === "") {
return false; return false;
} }

View file

@ -23,10 +23,11 @@ export interface ProductVariantCreatorPriceAndSkuProps {
onApplyToAllPriceChange: (value: string) => void; onApplyToAllPriceChange: (value: string) => void;
onApplyToAllStockChange: (warehouseIndex: number, value: string) => void; onApplyToAllStockChange: (warehouseIndex: number, value: string) => void;
onAttributeSelect: (id: string, type: PriceOrStock) => void; onAttributeSelect: (id: string, type: PriceOrStock) => void;
onAttributeValueChange: ( onAttributePriceChange: (id: string, value: string) => void;
onAttributeStockChange: (
id: string, id: string,
value: string, quantity: number,
type: PriceOrStock warehouseIndex: number
) => void; ) => void;
onWarehouseToggle: (id: string) => void; onWarehouseToggle: (id: string) => void;
} }
@ -40,7 +41,8 @@ const ProductVariantCreatorPriceAndSku: React.FC<ProductVariantCreatorPriceAndSk
onApplyToAllPriceChange, onApplyToAllPriceChange,
onApplyToAllStockChange, onApplyToAllStockChange,
onAttributeSelect, onAttributeSelect,
onAttributeValueChange, onAttributePriceChange,
onAttributeStockChange,
onWarehouseToggle onWarehouseToggle
}) => ( }) => (
<> <>
@ -51,9 +53,7 @@ const ProductVariantCreatorPriceAndSku: React.FC<ProductVariantCreatorPriceAndSk
onApplyToAllChange={value => onApplyToAllChange(value, "price")} onApplyToAllChange={value => onApplyToAllChange(value, "price")}
onApplyToAllPriceChange={onApplyToAllPriceChange} onApplyToAllPriceChange={onApplyToAllPriceChange}
onAttributeSelect={id => onAttributeSelect(id, "price")} onAttributeSelect={id => onAttributeSelect(id, "price")}
onAttributeValueChange={(id, value) => onAttributeValueChange={onAttributePriceChange}
onAttributeValueChange(id, value, "price")
}
/> />
<CardSpacer /> <CardSpacer />
<ProductVariantCreatorStock <ProductVariantCreatorStock
@ -63,9 +63,7 @@ const ProductVariantCreatorPriceAndSku: React.FC<ProductVariantCreatorPriceAndSk
onApplyToAllChange={value => onApplyToAllChange(value, "stock")} onApplyToAllChange={value => onApplyToAllChange(value, "stock")}
onApplyToAllStockChange={onApplyToAllStockChange} onApplyToAllStockChange={onApplyToAllStockChange}
onAttributeSelect={id => onAttributeSelect(id, "stock")} onAttributeSelect={id => onAttributeSelect(id, "stock")}
onAttributeValueChange={(id, value) => onAttributeValueChange={onAttributeStockChange}
onAttributeValueChange(id, value, "stock")
}
onWarehouseToggle={onWarehouseToggle} onWarehouseToggle={onWarehouseToggle}
/> />
</> </>

View file

@ -27,6 +27,17 @@ import { getStockAttributeValues } from "./utils";
const useStyles = makeStyles( const useStyles = makeStyles(
theme => ({ theme => ({
attributeStockContainer: {
columnGap: theme.spacing(3) + "px",
display: "grid",
gridTemplateColumns: ({ data }: ProductVariantCreatorStockProps) =>
`150px repeat(${data.warehouses.length}, 288px)`,
rowGap: theme.spacing(2) + "px"
},
attributeStockScroll: {
overflowX: "scroll",
width: "100%"
},
hr: { hr: {
marginBottom: theme.spacing(), marginBottom: theme.spacing(),
marginTop: theme.spacing(0.5) marginTop: theme.spacing(0.5)
@ -75,7 +86,11 @@ export interface ProductVariantCreatorStockProps {
onApplyToAllChange: (mode: VariantCreatorPricesAndSkuMode) => void; onApplyToAllChange: (mode: VariantCreatorPricesAndSkuMode) => void;
onApplyToAllStockChange: (warehouseIndex: number, value: string) => void; onApplyToAllStockChange: (warehouseIndex: number, value: string) => void;
onAttributeSelect: (id: string) => void; onAttributeSelect: (id: string) => void;
onAttributeValueChange: (id: string, value: string) => void; onAttributeValueChange: (
id: string,
quantity: number,
warehouseIndex: number
) => void;
onWarehouseToggle: (id: string) => void; onWarehouseToggle: (id: string) => void;
} }
@ -168,11 +183,8 @@ const ProductVariantCreatorStock: React.FC<ProductVariantCreatorStockProps> = pr
{data.stock.mode === "all" && ( {data.stock.mode === "all" && (
<div className={classes.stockContainer}> <div className={classes.stockContainer}>
{data.warehouses.map((warehouseId, warehouseIndex) => ( {data.warehouses.map((warehouseId, warehouseIndex) => (
<div> <div key={warehouseId}>
<Typography <Typography className={classes.warehouseName}>
className={classes.warehouseName}
key={warehouseId}
>
{ {
warehouses.find(warehouse => warehouse.id === warehouseId) warehouses.find(warehouse => warehouse.id === warehouseId)
.name .name
@ -212,60 +224,74 @@ const ProductVariantCreatorStock: React.FC<ProductVariantCreatorStockProps> = pr
{data.stock.mode === "attribute" && ( {data.stock.mode === "attribute" && (
<> <>
<FormSpacer /> <FormSpacer />
<Grid variant="uniform"> <SingleSelectField
<div className={classes.label}> className={classes.shortInput}
<Typography> choices={attributeChoices}
<FormattedMessage label={intl.formatMessage({
defaultMessage="Choose attribute" defaultMessage: "Select Attribute",
description="variant attribute" description: "variant attribute"
/> })}
</Typography> value={data.stock.attribute}
</div> onChange={event => onAttributeSelect(event.target.value)}
<div> />
<SingleSelectField {stockAttributeValues && (
choices={attributeChoices} <>
label={intl.formatMessage({ <Hr className={classes.hrAttribute} />
defaultMessage: "Attribute", <FormSpacer />
description: "variant attribute" <div className={classes.attributeStockScroll}>
})} <div className={classes.attributeStockContainer}>
value={data.stock.attribute} <div />
onChange={onAttributeSelect} {data.stock.attribute &&
/> data.warehouses.map(warehouseId => (
</div> <Typography
</Grid> className={classes.warehouseName}
{stockAttributeValues && key={warehouseId}
stockAttributeValues.map(attributeValue => ( >
<React.Fragment key={attributeValue.id}> {
<Hr className={classes.hrAttribute} /> warehouses.find(
<FormSpacer /> warehouse => warehouse.id === warehouseId
<Grid variant="uniform"> ).name
<div className={classes.label}> }
<Typography>{attributeValue.name}</Typography> </Typography>
</div> ))}
<div> {stockAttributeValues.map(attributeValue => (
<TextField <React.Fragment key={attributeValue.id}>
label={intl.formatMessage({ <Typography>{attributeValue.name}</Typography>
defaultMessage: "Stock", {data.warehouses.map(
description: "variant stock", (warehouseId, warehouseIndex) => (
id: "productVariantCreatePricesSetStockPlaceholder" <TextField
})} fullWidth
fullWidth inputProps={{
value={ min: 0,
data.stock.values.find( type: "number"
value => value.slug === attributeValue.slug }}
).value label={intl.formatMessage({
} defaultMessage: "Stock",
onChange={event => id:
onAttributeValueChange( "productVariantCreatePricesStockInputLabel"
attributeValue.slug, })}
event.target.value value={
data.stock.values.find(
value => value.slug === attributeValue.slug
).value[warehouseIndex]
}
onChange={event =>
onAttributeValueChange(
attributeValue.slug,
parseInt(event.target.value, 10),
warehouseIndex
)
}
key={warehouseId}
/>
) )
} )}
/> </React.Fragment>
</div> ))}
</Grid> </div>
</React.Fragment> </div>
))} </>
)}
</> </>
)} )}
<FormSpacer /> <FormSpacer />

View file

@ -92,7 +92,7 @@ const useStyles = makeStyles<
marginTop: theme.spacing(0.5) marginTop: theme.spacing(0.5)
}, },
hr: { hr: {
gridColumn: props => `span ${4 + props.data.stock.value.length}` gridColumn: props => `span ${4 + props.data.variants[0].stocks.length}`
}, },
input: { input: {
"& input": { "& input": {
@ -103,7 +103,7 @@ const useStyles = makeStyles<
columnGap: theme.spacing(3), columnGap: theme.spacing(3),
display: "grid", display: "grid",
gridTemplateColumns: props => gridTemplateColumns: props =>
`minmax(240px, auto) 170px repeat(${props.data.stock.value.length}, 140px) 140px 64px`, `minmax(240px, auto) 170px repeat(${props.data.variants[0].stocks.length}, 140px) 140px 64px`,
overflowX: "scroll", overflowX: "scroll",
rowGap: theme.spacing() + "px" rowGap: theme.spacing() + "px"
} }

View file

@ -186,8 +186,8 @@ function changeAttributeValuePrice(
function changeAttributeValueStock( function changeAttributeValueStock(
state: ProductVariantCreateFormData, state: ProductVariantCreateFormData,
attributeValueSlug: string, attributeValueSlug: string,
warehouseIndex: number, quantity: number,
quantity: number warehouseIndex: number
): ProductVariantCreateFormData { ): ProductVariantCreateFormData {
const index = state.stock.values.findIndex( const index = state.stock.values.findIndex(
value => value.slug === attributeValueSlug value => value.slug === attributeValueSlug
@ -199,8 +199,12 @@ function changeAttributeValueStock(
const values = updateAtIndex( const values = updateAtIndex(
{ {
slug: attributeValueSlug, ...state.stock.values[index],
value: updateAtIndex(quantity, state.stock.value, warehouseIndex) value: updateAtIndex(
quantity,
state.stock.values[index].value,
warehouseIndex
)
}, },
state.stock.values, state.stock.values,
index index