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,8 +24,7 @@ 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,
@ -33,7 +32,7 @@ const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps>
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">
<div className={classes.label}>
<Typography>
<FormattedMessage
defaultMessage="Choose attribute"
description="variant attribute"
/>
</Typography>
</div>
<div>
<SingleSelectField <SingleSelectField
className={classes.shortInput}
choices={attributeChoices} choices={attributeChoices}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Attribute", defaultMessage: "Select Attribute",
description: "variant attribute" description: "variant attribute"
})} })}
value={data.stock.attribute} value={data.stock.attribute}
onChange={onAttributeSelect} onChange={event => onAttributeSelect(event.target.value)}
/> />
</div> {stockAttributeValues && (
</Grid> <>
{stockAttributeValues &&
stockAttributeValues.map(attributeValue => (
<React.Fragment key={attributeValue.id}>
<Hr className={classes.hrAttribute} /> <Hr className={classes.hrAttribute} />
<FormSpacer /> <FormSpacer />
<Grid variant="uniform"> <div className={classes.attributeStockScroll}>
<div className={classes.label}> <div className={classes.attributeStockContainer}>
<div />
{data.stock.attribute &&
data.warehouses.map(warehouseId => (
<Typography
className={classes.warehouseName}
key={warehouseId}
>
{
warehouses.find(
warehouse => warehouse.id === warehouseId
).name
}
</Typography>
))}
{stockAttributeValues.map(attributeValue => (
<React.Fragment key={attributeValue.id}>
<Typography>{attributeValue.name}</Typography> <Typography>{attributeValue.name}</Typography>
</div> {data.warehouses.map(
<div> (warehouseId, warehouseIndex) => (
<TextField <TextField
fullWidth
inputProps={{
min: 0,
type: "number"
}}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Stock", defaultMessage: "Stock",
description: "variant stock", id:
id: "productVariantCreatePricesSetStockPlaceholder" "productVariantCreatePricesStockInputLabel"
})} })}
fullWidth
value={ value={
data.stock.values.find( data.stock.values.find(
value => value.slug === attributeValue.slug value => value.slug === attributeValue.slug
).value ).value[warehouseIndex]
} }
onChange={event => onChange={event =>
onAttributeValueChange( onAttributeValueChange(
attributeValue.slug, attributeValue.slug,
event.target.value parseInt(event.target.value, 10),
warehouseIndex
) )
} }
key={warehouseId}
/> />
</div> )
</Grid> )}
</React.Fragment> </React.Fragment>
))} ))}
</div>
</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