Add variant stock filtering by warehouse
This commit is contained in:
parent
ccc51b1243
commit
ee36d6046c
10 changed files with 160 additions and 16 deletions
|
@ -53,13 +53,15 @@ const useStyles = makeStyles(
|
||||||
);
|
);
|
||||||
|
|
||||||
export interface LinkChoiceProps {
|
export interface LinkChoiceProps {
|
||||||
|
className?: string;
|
||||||
choices: SingleAutocompleteChoiceType[];
|
choices: SingleAutocompleteChoiceType[];
|
||||||
name: "country";
|
name?: string;
|
||||||
value: string;
|
value: string;
|
||||||
onChange: FormChange;
|
onChange: FormChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LinkChoice: React.FC<LinkChoiceProps> = ({
|
const LinkChoice: React.FC<LinkChoiceProps> = ({
|
||||||
|
className,
|
||||||
choices,
|
choices,
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
|
@ -107,7 +109,7 @@ const LinkChoice: React.FC<LinkChoiceProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={classes.root}
|
className={classNames(classes.root, className)}
|
||||||
ref={anchor}
|
ref={anchor}
|
||||||
onKeyDown={handleKeyPress}
|
onKeyDown={handleKeyPress}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import TableCell from "@material-ui/core/TableCell";
|
||||||
import TableRow from "@material-ui/core/TableRow";
|
import TableRow from "@material-ui/core/TableRow";
|
||||||
import Typography from "@material-ui/core/Typography";
|
import Typography from "@material-ui/core/Typography";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl, IntlShape } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import Checkbox from "@saleor/components/Checkbox";
|
import Checkbox from "@saleor/components/Checkbox";
|
||||||
|
@ -16,11 +16,51 @@ import Money from "@saleor/components/Money";
|
||||||
import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
||||||
import Skeleton from "@saleor/components/Skeleton";
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
import TableHead from "@saleor/components/TableHead";
|
import TableHead from "@saleor/components/TableHead";
|
||||||
|
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
|
import LinkChoice from "@saleor/components/LinkChoice";
|
||||||
import { maybe, renderCollection } from "../../../misc";
|
import { maybe, renderCollection } from "../../../misc";
|
||||||
import { ListActions } from "../../../types";
|
import { ListActions } from "../../../types";
|
||||||
import { ProductDetails_product_variants } from "../../types/ProductDetails";
|
import {
|
||||||
|
ProductDetails_product_variants,
|
||||||
|
ProductDetails_product_variants_stock_warehouse
|
||||||
|
} from "../../types/ProductDetails";
|
||||||
import { ProductVariant_costPrice } from "../../types/ProductVariant";
|
import { ProductVariant_costPrice } from "../../types/ProductVariant";
|
||||||
|
|
||||||
|
function getWarehouseChoices(
|
||||||
|
variants: ProductDetails_product_variants[],
|
||||||
|
intl: IntlShape
|
||||||
|
): SingleAutocompleteChoiceType[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
defaultMessage: "All Warehouses",
|
||||||
|
description: "filtering option"
|
||||||
|
}),
|
||||||
|
value: null
|
||||||
|
},
|
||||||
|
...variants
|
||||||
|
.reduce<ProductDetails_product_variants_stock_warehouse[]>(
|
||||||
|
(warehouses, variant) => [
|
||||||
|
...warehouses,
|
||||||
|
...variant.stock.reduce<
|
||||||
|
ProductDetails_product_variants_stock_warehouse[]
|
||||||
|
>((variantStocks, stock) => {
|
||||||
|
if (!!warehouses.find(w => w.id === stock.warehouse.id)) {
|
||||||
|
return variantStocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...variantStocks, stock.warehouse];
|
||||||
|
}, [])
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
.map(w => ({
|
||||||
|
label: w.name,
|
||||||
|
value: w.id
|
||||||
|
}))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
theme => ({
|
theme => ({
|
||||||
[theme.breakpoints.up("lg")]: {
|
[theme.breakpoints.up("lg")]: {
|
||||||
|
@ -57,6 +97,13 @@ const useStyles = makeStyles(
|
||||||
},
|
},
|
||||||
textRight: {
|
textRight: {
|
||||||
textAlign: "right" as "right"
|
textAlign: "right" as "right"
|
||||||
|
},
|
||||||
|
warehouseLabel: {
|
||||||
|
display: "inline-block",
|
||||||
|
marginRight: theme.spacing()
|
||||||
|
},
|
||||||
|
warehouseSelectContainer: {
|
||||||
|
paddingTop: theme.spacing(2)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
{ name: "ProductVariants" }
|
{ name: "ProductVariants" }
|
||||||
|
@ -90,6 +137,7 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const [warehouse, setWarehouse] = React.useState(null);
|
||||||
const hasVariants = maybe(() => variants.length > 0, true);
|
const hasVariants = maybe(() => variants.length > 0, true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -127,7 +175,23 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{!variants.length && (
|
|
||||||
|
{variants.length > 0 ? (
|
||||||
|
<CardContent className={classes.warehouseSelectContainer}>
|
||||||
|
<Typography className={classes.warehouseLabel}>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Available inventoty at:"
|
||||||
|
description="variant stock status"
|
||||||
|
/>
|
||||||
|
</Typography>
|
||||||
|
<LinkChoice
|
||||||
|
choices={getWarehouseChoices(variants, intl)}
|
||||||
|
name="warehouse"
|
||||||
|
value={warehouse}
|
||||||
|
onChange={event => setWarehouse(event.target.value)}
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
) : (
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography color={hasVariants ? "textPrimary" : "textSecondary"}>
|
<Typography color={hasVariants ? "textPrimary" : "textSecondary"}>
|
||||||
<FormattedMessage defaultMessage="Use variants for products that come in a variety of versions for example different sizes or colors" />
|
<FormattedMessage defaultMessage="Use variants for products that come in a variety of versions for example different sizes or colors" />
|
||||||
|
@ -146,7 +210,7 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
||||||
>
|
>
|
||||||
<TableCell className={classes.colName}>
|
<TableCell className={classes.colName}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Name"
|
defaultMessage="Variant"
|
||||||
description="product variant name"
|
description="product variant name"
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
@ -175,6 +239,9 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
||||||
variant && variant.stock
|
variant && variant.stock
|
||||||
? variant.stock.reduce((acc, s) => acc + s.quantity, 0)
|
? variant.stock.reduce((acc, s) => acc + s.quantity, 0)
|
||||||
: null;
|
: null;
|
||||||
|
const variantStock = variant.stock.find(
|
||||||
|
s => s.warehouse.id === warehouse
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow
|
||||||
|
@ -219,19 +286,41 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
||||||
>
|
>
|
||||||
{numAvailable === null ? (
|
{numAvailable === null ? (
|
||||||
<Skeleton />
|
<Skeleton />
|
||||||
) : numAvailable === 0 ? (
|
) : warehouse === null ? (
|
||||||
<FormattedMessage
|
numAvailable === 0 ? (
|
||||||
defaultMessage="Unavailable in all locations"
|
<FormattedMessage
|
||||||
description="product variant inventory"
|
defaultMessage="Unavailable in all locations"
|
||||||
/>
|
description="product variant inventory"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="{numAvailable} available at {numLocations} {numLocations,plural,one{location} other{locations}}"
|
||||||
|
description="product variant inventory"
|
||||||
|
values={{
|
||||||
|
numAvailable,
|
||||||
|
numLocations: variant.stock.length
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
) : !!variantStock ? (
|
||||||
|
variantStock.quantity > 0 ? (
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="{stockQuantity} available"
|
||||||
|
description="product variant inventory"
|
||||||
|
values={{
|
||||||
|
stockQuantity: variantStock.quantity
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Unavailable"
|
||||||
|
description="product variant inventory"
|
||||||
|
/>
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="{numAvailable} available at {numLocations} {numLocations,plural,one{location} other{locations}}"
|
defaultMessage="Not stocked"
|
||||||
description="product variant inventory"
|
description="product variant inventory"
|
||||||
values={{
|
|
||||||
numAvailable,
|
|
||||||
numLocations: variant.stock.length
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
|
@ -149,6 +149,10 @@ export const productFragmentDetails = gql`
|
||||||
stock {
|
stock {
|
||||||
id
|
id
|
||||||
quantity
|
quantity
|
||||||
|
warehouse {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
productType {
|
productType {
|
||||||
|
|
|
@ -127,10 +127,17 @@ export interface Product_variants_priceOverride {
|
||||||
currency: string;
|
currency: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Product_variants_stock_warehouse {
|
||||||
|
__typename: "Warehouse";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Product_variants_stock {
|
export interface Product_variants_stock {
|
||||||
__typename: "Stock";
|
__typename: "Stock";
|
||||||
id: string;
|
id: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
warehouse: Product_variants_stock_warehouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Product_variants {
|
export interface Product_variants {
|
||||||
|
|
|
@ -133,10 +133,17 @@ export interface ProductCreate_productCreate_product_variants_priceOverride {
|
||||||
currency: string;
|
currency: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProductCreate_productCreate_product_variants_stock_warehouse {
|
||||||
|
__typename: "Warehouse";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProductCreate_productCreate_product_variants_stock {
|
export interface ProductCreate_productCreate_product_variants_stock {
|
||||||
__typename: "Stock";
|
__typename: "Stock";
|
||||||
id: string;
|
id: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
warehouse: ProductCreate_productCreate_product_variants_stock_warehouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductCreate_productCreate_product_variants {
|
export interface ProductCreate_productCreate_product_variants {
|
||||||
|
|
|
@ -127,10 +127,17 @@ export interface ProductDetails_product_variants_priceOverride {
|
||||||
currency: string;
|
currency: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProductDetails_product_variants_stock_warehouse {
|
||||||
|
__typename: "Warehouse";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProductDetails_product_variants_stock {
|
export interface ProductDetails_product_variants_stock {
|
||||||
__typename: "Stock";
|
__typename: "Stock";
|
||||||
id: string;
|
id: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
warehouse: ProductDetails_product_variants_stock_warehouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductDetails_product_variants {
|
export interface ProductDetails_product_variants {
|
||||||
|
|
|
@ -133,10 +133,17 @@ export interface ProductImageCreate_productImageCreate_product_variants_priceOve
|
||||||
currency: string;
|
currency: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProductImageCreate_productImageCreate_product_variants_stock_warehouse {
|
||||||
|
__typename: "Warehouse";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProductImageCreate_productImageCreate_product_variants_stock {
|
export interface ProductImageCreate_productImageCreate_product_variants_stock {
|
||||||
__typename: "Stock";
|
__typename: "Stock";
|
||||||
id: string;
|
id: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
warehouse: ProductImageCreate_productImageCreate_product_variants_stock_warehouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductImageCreate_productImageCreate_product_variants {
|
export interface ProductImageCreate_productImageCreate_product_variants {
|
||||||
|
|
|
@ -133,10 +133,17 @@ export interface ProductImageUpdate_productImageUpdate_product_variants_priceOve
|
||||||
currency: string;
|
currency: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProductImageUpdate_productImageUpdate_product_variants_stock_warehouse {
|
||||||
|
__typename: "Warehouse";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProductImageUpdate_productImageUpdate_product_variants_stock {
|
export interface ProductImageUpdate_productImageUpdate_product_variants_stock {
|
||||||
__typename: "Stock";
|
__typename: "Stock";
|
||||||
id: string;
|
id: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
warehouse: ProductImageUpdate_productImageUpdate_product_variants_stock_warehouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductImageUpdate_productImageUpdate_product_variants {
|
export interface ProductImageUpdate_productImageUpdate_product_variants {
|
||||||
|
|
|
@ -133,10 +133,17 @@ export interface ProductUpdate_productUpdate_product_variants_priceOverride {
|
||||||
currency: string;
|
currency: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProductUpdate_productUpdate_product_variants_stock_warehouse {
|
||||||
|
__typename: "Warehouse";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProductUpdate_productUpdate_product_variants_stock {
|
export interface ProductUpdate_productUpdate_product_variants_stock {
|
||||||
__typename: "Stock";
|
__typename: "Stock";
|
||||||
id: string;
|
id: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
warehouse: ProductUpdate_productUpdate_product_variants_stock_warehouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProductUpdate_productUpdate_product_variants {
|
export interface ProductUpdate_productUpdate_product_variants {
|
||||||
|
|
|
@ -133,10 +133,17 @@ export interface SimpleProductUpdate_productUpdate_product_variants_priceOverrid
|
||||||
currency: string;
|
currency: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SimpleProductUpdate_productUpdate_product_variants_stock_warehouse {
|
||||||
|
__typename: "Warehouse";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface SimpleProductUpdate_productUpdate_product_variants_stock {
|
export interface SimpleProductUpdate_productUpdate_product_variants_stock {
|
||||||
__typename: "Stock";
|
__typename: "Stock";
|
||||||
id: string;
|
id: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
warehouse: SimpleProductUpdate_productUpdate_product_variants_stock_warehouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SimpleProductUpdate_productUpdate_product_variants {
|
export interface SimpleProductUpdate_productUpdate_product_variants {
|
||||||
|
|
Loading…
Reference in a new issue