Add ability to create stock in multiple warehouses
This commit is contained in:
parent
b776321e0a
commit
715303e025
6 changed files with 133 additions and 99 deletions
|
@ -24,16 +24,15 @@ export interface ProductVariantCreatorContentProps {
|
|||
warehouses: WarehouseFragment[];
|
||||
}
|
||||
|
||||
const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps> = props => {
|
||||
const {
|
||||
attributes,
|
||||
currencySymbol,
|
||||
data,
|
||||
dispatchFormDataAction,
|
||||
errors,
|
||||
step,
|
||||
warehouses
|
||||
} = props;
|
||||
const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps> = ({
|
||||
attributes,
|
||||
currencySymbol,
|
||||
data,
|
||||
dispatchFormDataAction,
|
||||
errors,
|
||||
step,
|
||||
warehouses
|
||||
}) => {
|
||||
const selectedAttributes = attributes.filter(attribute =>
|
||||
isSelected(
|
||||
attribute.id,
|
||||
|
@ -104,17 +103,26 @@ const ProductVariantCreatorContent: React.FC<ProductVariantCreatorContentProps>
|
|||
: ProductVariantCreateReducerActionType.changeApplyStockToAttributeId
|
||||
})
|
||||
}
|
||||
onAttributeValueChange={(valueId, price, type) =>
|
||||
dispatchFormDataAction(
|
||||
type === "price" && {
|
||||
changeAttributeValuePrice: {
|
||||
price,
|
||||
valueId
|
||||
},
|
||||
type:
|
||||
ProductVariantCreateReducerActionType.changeAttributeValuePrice
|
||||
}
|
||||
)
|
||||
onAttributePriceChange={(valueId, price) =>
|
||||
dispatchFormDataAction({
|
||||
changeAttributeValuePrice: {
|
||||
price,
|
||||
valueId
|
||||
},
|
||||
type:
|
||||
ProductVariantCreateReducerActionType.changeAttributeValuePrice
|
||||
})
|
||||
}
|
||||
onAttributeStockChange={(valueId, quantity, warehouseIndex) =>
|
||||
dispatchFormDataAction({
|
||||
changeAttributeValueStock: {
|
||||
quantity,
|
||||
valueId,
|
||||
warehouseIndex
|
||||
},
|
||||
type:
|
||||
ProductVariantCreateReducerActionType.changeAttributeValueStock
|
||||
})
|
||||
}
|
||||
onWarehouseToggle={warehouseId =>
|
||||
dispatchFormDataAction({
|
||||
|
|
|
@ -50,11 +50,9 @@ function canHitNext(
|
|||
) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (data.stock.mode === "attribute" || data.stock.attribute) {
|
||||
if (data.stock.mode === "attribute" && data.stock.attribute === "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,10 +23,11 @@ export interface ProductVariantCreatorPriceAndSkuProps {
|
|||
onApplyToAllPriceChange: (value: string) => void;
|
||||
onApplyToAllStockChange: (warehouseIndex: number, value: string) => void;
|
||||
onAttributeSelect: (id: string, type: PriceOrStock) => void;
|
||||
onAttributeValueChange: (
|
||||
onAttributePriceChange: (id: string, value: string) => void;
|
||||
onAttributeStockChange: (
|
||||
id: string,
|
||||
value: string,
|
||||
type: PriceOrStock
|
||||
quantity: number,
|
||||
warehouseIndex: number
|
||||
) => void;
|
||||
onWarehouseToggle: (id: string) => void;
|
||||
}
|
||||
|
@ -40,7 +41,8 @@ const ProductVariantCreatorPriceAndSku: React.FC<ProductVariantCreatorPriceAndSk
|
|||
onApplyToAllPriceChange,
|
||||
onApplyToAllStockChange,
|
||||
onAttributeSelect,
|
||||
onAttributeValueChange,
|
||||
onAttributePriceChange,
|
||||
onAttributeStockChange,
|
||||
onWarehouseToggle
|
||||
}) => (
|
||||
<>
|
||||
|
@ -51,9 +53,7 @@ const ProductVariantCreatorPriceAndSku: React.FC<ProductVariantCreatorPriceAndSk
|
|||
onApplyToAllChange={value => onApplyToAllChange(value, "price")}
|
||||
onApplyToAllPriceChange={onApplyToAllPriceChange}
|
||||
onAttributeSelect={id => onAttributeSelect(id, "price")}
|
||||
onAttributeValueChange={(id, value) =>
|
||||
onAttributeValueChange(id, value, "price")
|
||||
}
|
||||
onAttributeValueChange={onAttributePriceChange}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<ProductVariantCreatorStock
|
||||
|
@ -63,9 +63,7 @@ const ProductVariantCreatorPriceAndSku: React.FC<ProductVariantCreatorPriceAndSk
|
|||
onApplyToAllChange={value => onApplyToAllChange(value, "stock")}
|
||||
onApplyToAllStockChange={onApplyToAllStockChange}
|
||||
onAttributeSelect={id => onAttributeSelect(id, "stock")}
|
||||
onAttributeValueChange={(id, value) =>
|
||||
onAttributeValueChange(id, value, "stock")
|
||||
}
|
||||
onAttributeValueChange={onAttributeStockChange}
|
||||
onWarehouseToggle={onWarehouseToggle}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -27,6 +27,17 @@ import { getStockAttributeValues } from "./utils";
|
|||
|
||||
const useStyles = makeStyles(
|
||||
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: {
|
||||
marginBottom: theme.spacing(),
|
||||
marginTop: theme.spacing(0.5)
|
||||
|
@ -75,7 +86,11 @@ export interface ProductVariantCreatorStockProps {
|
|||
onApplyToAllChange: (mode: VariantCreatorPricesAndSkuMode) => void;
|
||||
onApplyToAllStockChange: (warehouseIndex: number, value: string) => void;
|
||||
onAttributeSelect: (id: string) => void;
|
||||
onAttributeValueChange: (id: string, value: string) => void;
|
||||
onAttributeValueChange: (
|
||||
id: string,
|
||||
quantity: number,
|
||||
warehouseIndex: number
|
||||
) => void;
|
||||
onWarehouseToggle: (id: string) => void;
|
||||
}
|
||||
|
||||
|
@ -168,11 +183,8 @@ const ProductVariantCreatorStock: React.FC<ProductVariantCreatorStockProps> = pr
|
|||
{data.stock.mode === "all" && (
|
||||
<div className={classes.stockContainer}>
|
||||
{data.warehouses.map((warehouseId, warehouseIndex) => (
|
||||
<div>
|
||||
<Typography
|
||||
className={classes.warehouseName}
|
||||
key={warehouseId}
|
||||
>
|
||||
<div key={warehouseId}>
|
||||
<Typography className={classes.warehouseName}>
|
||||
{
|
||||
warehouses.find(warehouse => warehouse.id === warehouseId)
|
||||
.name
|
||||
|
@ -212,60 +224,74 @@ const ProductVariantCreatorStock: React.FC<ProductVariantCreatorStockProps> = pr
|
|||
{data.stock.mode === "attribute" && (
|
||||
<>
|
||||
<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
|
||||
<SingleSelectField
|
||||
className={classes.shortInput}
|
||||
choices={attributeChoices}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Select Attribute",
|
||||
description: "variant attribute"
|
||||
})}
|
||||
value={data.stock.attribute}
|
||||
onChange={event => onAttributeSelect(event.target.value)}
|
||||
/>
|
||||
{stockAttributeValues && (
|
||||
<>
|
||||
<Hr className={classes.hrAttribute} />
|
||||
<FormSpacer />
|
||||
<div className={classes.attributeStockScroll}>
|
||||
<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>
|
||||
{data.warehouses.map(
|
||||
(warehouseId, warehouseIndex) => (
|
||||
<TextField
|
||||
fullWidth
|
||||
inputProps={{
|
||||
min: 0,
|
||||
type: "number"
|
||||
}}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Stock",
|
||||
id:
|
||||
"productVariantCreatePricesStockInputLabel"
|
||||
})}
|
||||
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}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
))}
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<FormSpacer />
|
||||
|
|
|
@ -92,7 +92,7 @@ const useStyles = makeStyles<
|
|||
marginTop: theme.spacing(0.5)
|
||||
},
|
||||
hr: {
|
||||
gridColumn: props => `span ${4 + props.data.stock.value.length}`
|
||||
gridColumn: props => `span ${4 + props.data.variants[0].stocks.length}`
|
||||
},
|
||||
input: {
|
||||
"& input": {
|
||||
|
@ -103,7 +103,7 @@ const useStyles = makeStyles<
|
|||
columnGap: theme.spacing(3),
|
||||
display: "grid",
|
||||
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",
|
||||
rowGap: theme.spacing() + "px"
|
||||
}
|
||||
|
|
|
@ -186,8 +186,8 @@ function changeAttributeValuePrice(
|
|||
function changeAttributeValueStock(
|
||||
state: ProductVariantCreateFormData,
|
||||
attributeValueSlug: string,
|
||||
warehouseIndex: number,
|
||||
quantity: number
|
||||
quantity: number,
|
||||
warehouseIndex: number
|
||||
): ProductVariantCreateFormData {
|
||||
const index = state.stock.values.findIndex(
|
||||
value => value.slug === attributeValueSlug
|
||||
|
@ -199,8 +199,12 @@ function changeAttributeValueStock(
|
|||
|
||||
const values = updateAtIndex(
|
||||
{
|
||||
slug: attributeValueSlug,
|
||||
value: updateAtIndex(quantity, state.stock.value, warehouseIndex)
|
||||
...state.stock.values[index],
|
||||
value: updateAtIndex(
|
||||
quantity,
|
||||
state.stock.values[index].value,
|
||||
warehouseIndex
|
||||
)
|
||||
},
|
||||
state.stock.values,
|
||||
index
|
||||
|
|
Loading…
Reference in a new issue