Add stock management components to simple product
This commit is contained in:
parent
0805ff052d
commit
11a10686ce
23 changed files with 256 additions and 135 deletions
|
@ -1,96 +0,0 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment";
|
||||
import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors";
|
||||
import { ProductDetails_product } from "../../types/ProductDetails";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
root: {
|
||||
display: "grid",
|
||||
gridColumnGap: theme.spacing(2),
|
||||
gridTemplateColumns: "1fr 1fr"
|
||||
}
|
||||
}),
|
||||
{ name: "ProductStock" }
|
||||
);
|
||||
|
||||
interface ProductStockProps {
|
||||
data: {
|
||||
sku: string;
|
||||
stockQuantity: number;
|
||||
};
|
||||
disabled: boolean;
|
||||
errors: ProductErrorFragment[];
|
||||
product: ProductDetails_product;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
const ProductStock: React.FC<ProductStockProps> = props => {
|
||||
const { data, disabled, product, onChange, errors } = props;
|
||||
|
||||
const classes = useStyles(props);
|
||||
const intl = useIntl();
|
||||
|
||||
const formErrors = getFormErrors(["sku", "stockQuantity"], errors);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Inventory",
|
||||
description: "product stock, section header",
|
||||
id: "productStockHeader"
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
<div className={classes.root}>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
name="sku"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "SKU (Stock Keeping Unit)"
|
||||
})}
|
||||
value={data.sku}
|
||||
onChange={onChange}
|
||||
error={!!formErrors.sku}
|
||||
helperText={getProductErrorMessage(formErrors.sku, intl)}
|
||||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
name="stockQuantity"
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Inventory",
|
||||
description: "product stock",
|
||||
id: "prodictStockInventoryLabel"
|
||||
})}
|
||||
value={data.stockQuantity}
|
||||
type="number"
|
||||
onChange={onChange}
|
||||
helperText={
|
||||
getProductErrorMessage(formErrors.stockQuantity, intl) ||
|
||||
(product &&
|
||||
intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Allocated: {quantity}",
|
||||
description: "allocated product stock"
|
||||
},
|
||||
{
|
||||
quantity: product?.variants[0].quantityAllocated
|
||||
}
|
||||
))
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
ProductStock.displayName = "ProductStock";
|
||||
export default ProductStock;
|
|
@ -1,2 +0,0 @@
|
|||
export { default } from "./ProductStock";
|
||||
export * from "./ProductStock";
|
199
src/products/components/ProductStocks/ProductStocks.tsx
Normal file
199
src/products/components/ProductStocks/ProductStocks.tsx
Normal file
|
@ -0,0 +1,199 @@
|
|||
import Button from "@material-ui/core/Button";
|
||||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import Table from "@material-ui/core/Table";
|
||||
import TableHead from "@material-ui/core/TableHead";
|
||||
import TableBody from "@material-ui/core/TableBody";
|
||||
import TableCell from "@material-ui/core/TableCell";
|
||||
import TableRow from "@material-ui/core/TableRow";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import React from "react";
|
||||
import { useIntl, FormattedMessage } from "react-intl";
|
||||
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||
|
||||
import { FormChange } from "@saleor/hooks/useForm";
|
||||
import { FormsetChange, FormsetAtomicData } from "@saleor/hooks/useFormset";
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { getFieldError } from "@saleor/utils/errors";
|
||||
import { UserError } from "@saleor/types";
|
||||
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import Hr from "@saleor/components/Hr";
|
||||
import { renderCollection } from "@saleor/misc";
|
||||
|
||||
export type ProductStockInput = FormsetAtomicData<null, string>;
|
||||
export interface ProductStockFormData {
|
||||
sku: string;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface ProductStocksProps {
|
||||
data: ProductStockFormData;
|
||||
disabled: boolean;
|
||||
errors: UserError[];
|
||||
stocks: ProductStockInput[];
|
||||
onChange: FormsetChange;
|
||||
onFormDataChange: FormChange;
|
||||
onWarehousesEdit: () => undefined;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
colName: {},
|
||||
colQuantity: {
|
||||
textAlign: "right",
|
||||
width: 200
|
||||
},
|
||||
editWarehouses: {
|
||||
marginRight: -theme.spacing()
|
||||
},
|
||||
input: {
|
||||
padding: theme.spacing(1.5),
|
||||
textAlign: "right"
|
||||
},
|
||||
inputComponent: {
|
||||
width: 100
|
||||
},
|
||||
quantityContainer: {
|
||||
paddingTop: theme.spacing()
|
||||
},
|
||||
quantityHeader: {
|
||||
alignItems: "center",
|
||||
display: "flex",
|
||||
justifyContent: "space-between"
|
||||
},
|
||||
skuInputContainer: {
|
||||
display: "grid",
|
||||
gridColumnGap: theme.spacing(3) + "px",
|
||||
gridTemplateColumns: "repeat(2, 1fr)"
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: "ProductStocks"
|
||||
}
|
||||
);
|
||||
|
||||
const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||
data,
|
||||
disabled,
|
||||
errors,
|
||||
stocks,
|
||||
onChange,
|
||||
onFormDataChange,
|
||||
onWarehousesEdit
|
||||
}) => {
|
||||
const classes = useStyles({});
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Inventory",
|
||||
description: "product stock, section header",
|
||||
id: "productStockHeader"
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
<div className={classes.skuInputContainer}>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!getFieldError(errors, "sku")}
|
||||
fullWidth
|
||||
helperText={getFieldError(errors, "sku")?.message}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "SKU (Stock Keeping Unit)"
|
||||
})}
|
||||
name="sku"
|
||||
onChange={onFormDataChange}
|
||||
value={data.sku}
|
||||
/>
|
||||
</div>
|
||||
<FormSpacer />
|
||||
<ControlledCheckbox
|
||||
checked={data.trackInventory}
|
||||
name="trackInventory"
|
||||
onChange={onFormDataChange}
|
||||
disabled={disabled}
|
||||
label={
|
||||
<>
|
||||
<FormattedMessage
|
||||
defaultMessage="Track Inventory"
|
||||
description="product inventory, checkbox"
|
||||
/>
|
||||
<Typography variant="caption">
|
||||
<FormattedMessage defaultMessage="Active inventory tracking will automatically calculate changes of stock" />
|
||||
</Typography>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</CardContent>
|
||||
<Hr />
|
||||
<CardContent className={classes.quantityContainer}>
|
||||
<Typography>
|
||||
<div className={classes.quantityHeader}>
|
||||
<span>
|
||||
<FormattedMessage
|
||||
defaultMessage="Quantity"
|
||||
description="header"
|
||||
/>
|
||||
</span>
|
||||
<Button
|
||||
className={classes.editWarehouses}
|
||||
color="primary"
|
||||
data-cy="edit-warehouses"
|
||||
onClick={onWarehousesEdit}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Edit Warehouses"
|
||||
description="button"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell className={classes.colName}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Warehouse Name"
|
||||
description="tabel column header"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell className={classes.colQuantity}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Quantity Available"
|
||||
description="tabel column header"
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{renderCollection(stocks, stock => (
|
||||
<TableRow>
|
||||
<TableCell className={classes.colName}>{stock.label}</TableCell>
|
||||
<TableCell className={classes.colQuantity}>
|
||||
<TextField
|
||||
className={classes.inputComponent}
|
||||
fullWidth
|
||||
inputProps={{
|
||||
className: classes.input,
|
||||
min: 0,
|
||||
type: "number"
|
||||
}}
|
||||
onChange={event => onChange(stock.id, event.target.value)}
|
||||
value={stock.value}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
ProductStocks.displayName = "ProductStocks";
|
||||
export default ProductStocks;
|
2
src/products/components/ProductStocks/index.ts
Normal file
2
src/products/components/ProductStocks/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export * from "./ProductStocks";
|
||||
export { default } from "./ProductStocks";
|
|
@ -34,7 +34,8 @@ import {
|
|||
getProductUpdatePageFormData,
|
||||
getSelectedAttributesFromProduct,
|
||||
ProductAttributeValueChoices,
|
||||
ProductUpdatePageFormData
|
||||
ProductUpdatePageFormData,
|
||||
getStockInputFromProduct
|
||||
} from "../../utils/data";
|
||||
import {
|
||||
createAttributeChangeHandler,
|
||||
|
@ -45,8 +46,8 @@ import ProductDetailsForm from "../ProductDetailsForm";
|
|||
import ProductImages from "../ProductImages";
|
||||
import ProductOrganization from "../ProductOrganization";
|
||||
import ProductPricing from "../ProductPricing";
|
||||
import ProductStock from "../ProductStock";
|
||||
import ProductVariants from "../ProductVariants";
|
||||
import ProductStocks, { ProductStockInput } from "../ProductStocks";
|
||||
|
||||
export interface ProductUpdatePageProps extends ListActions {
|
||||
errors: ProductErrorFragment[];
|
||||
|
@ -71,7 +72,6 @@ export interface ProductUpdatePageProps extends ListActions {
|
|||
onImageEdit?(id: string);
|
||||
onImageReorder?(event: { oldIndex: number; newIndex: number });
|
||||
onImageUpload(file: File);
|
||||
onProductShow?();
|
||||
onSeoClick?();
|
||||
onSubmit?(data: ProductUpdatePageSubmitData);
|
||||
onVariantAdd?();
|
||||
|
@ -80,6 +80,7 @@ export interface ProductUpdatePageProps extends ListActions {
|
|||
export interface ProductUpdatePageSubmitData extends ProductUpdatePageFormData {
|
||||
attributes: ProductAttributeInput[];
|
||||
collections: string[];
|
||||
stocks: ProductStockInput[];
|
||||
}
|
||||
|
||||
export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
||||
|
@ -120,9 +121,13 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
|||
() => getAttributeInputFromProduct(product),
|
||||
[product]
|
||||
);
|
||||
const stockInput = React.useMemo(() => getStockInputFromProduct(product), [
|
||||
product
|
||||
]);
|
||||
const { change: changeAttributeData, data: attributes } = useFormset(
|
||||
attributeInput
|
||||
);
|
||||
const { change: changeStockData, data: stocks } = useFormset(stockInput);
|
||||
|
||||
const [selectedAttributes, setSelectedAttributes] = useStateFromProps<
|
||||
ProductAttributeValueChoices[]
|
||||
|
@ -149,6 +154,7 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
|||
const handleSubmit = (data: ProductUpdatePageFormData) =>
|
||||
onSubmit({
|
||||
attributes,
|
||||
stocks,
|
||||
...data
|
||||
});
|
||||
|
||||
|
@ -239,12 +245,13 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
|||
toggleAll={toggleAll}
|
||||
/>
|
||||
) : (
|
||||
<ProductStock
|
||||
<ProductStocks
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
product={product}
|
||||
onChange={change}
|
||||
errors={errors}
|
||||
stocks={stocks}
|
||||
onChange={changeStockData}
|
||||
onFormDataChange={change}
|
||||
/>
|
||||
)}
|
||||
<CardSpacer />
|
||||
|
|
|
@ -22,7 +22,7 @@ import { maybe, renderCollection } from "../../../misc";
|
|||
import { ListActions } from "../../../types";
|
||||
import {
|
||||
ProductDetails_product_variants,
|
||||
ProductDetails_product_variants_stock_warehouse
|
||||
ProductDetails_product_variants_stocks_warehouse
|
||||
} from "../../types/ProductDetails";
|
||||
import { ProductVariant_costPrice } from "../../types/ProductVariant";
|
||||
|
||||
|
@ -39,11 +39,11 @@ function getWarehouseChoices(
|
|||
value: null
|
||||
},
|
||||
...variants
|
||||
.reduce<ProductDetails_product_variants_stock_warehouse[]>(
|
||||
.reduce<ProductDetails_product_variants_stocks_warehouse[]>(
|
||||
(warehouses, variant) => [
|
||||
...warehouses,
|
||||
...variant.stock.reduce<
|
||||
ProductDetails_product_variants_stock_warehouse[]
|
||||
...variant.stocks.reduce<
|
||||
ProductDetails_product_variants_stocks_warehouse[]
|
||||
>((variantStocks, stock) => {
|
||||
if (!!warehouses.find(w => w.id === stock.warehouse.id)) {
|
||||
return variantStocks;
|
||||
|
@ -118,7 +118,7 @@ function getAvailabilityLabel(
|
|||
variant: ProductDetails_product_variants,
|
||||
numAvailable: number
|
||||
): string {
|
||||
const variantStock = variant.stock.find(s => s.warehouse.id === warehouse);
|
||||
const variantStock = variant.stocks.find(s => s.warehouse.id === warehouse);
|
||||
|
||||
if (!!warehouse) {
|
||||
if (!!variantStock) {
|
||||
|
@ -155,7 +155,7 @@ function getAvailabilityLabel(
|
|||
},
|
||||
{
|
||||
numAvailable,
|
||||
numLocations: variant.stock.length
|
||||
numLocations: variant.stocks.length
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -295,8 +295,8 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
|
|||
{renderCollection(variants, variant => {
|
||||
const isSelected = variant ? isChecked(variant.id) : false;
|
||||
const numAvailable =
|
||||
variant && variant.stock
|
||||
? variant.stock.reduce((acc, s) => acc + s.quantity, 0)
|
||||
variant && variant.stocks
|
||||
? variant.stocks.reduce((acc, s) => acc + s.quantity, 0)
|
||||
: null;
|
||||
|
||||
return (
|
||||
|
|
|
@ -260,10 +260,8 @@ export const product: (
|
|||
amount: 678.78,
|
||||
currency: "USD"
|
||||
},
|
||||
quantity: 12,
|
||||
quantityAllocated: 1,
|
||||
sku: "87192-94370",
|
||||
stock: [
|
||||
stocks: [
|
||||
{
|
||||
__typename: "Stock",
|
||||
id: "1",
|
||||
|
@ -277,7 +275,7 @@ export const product: (
|
|||
warehouse: warehouseList[1]
|
||||
}
|
||||
],
|
||||
stockQuantity: 48
|
||||
trackInventory: true
|
||||
},
|
||||
{
|
||||
__typename: "ProductVariant",
|
||||
|
@ -297,10 +295,8 @@ export const product: (
|
|||
margin: 7,
|
||||
name: "silver",
|
||||
priceOverride: null,
|
||||
quantity: 12,
|
||||
quantityAllocated: 1,
|
||||
sku: "69055-15190",
|
||||
stock: [
|
||||
stocks: [
|
||||
{
|
||||
__typename: "Stock",
|
||||
id: "1",
|
||||
|
@ -308,7 +304,7 @@ export const product: (
|
|||
warehouse: warehouseList[0]
|
||||
}
|
||||
],
|
||||
stockQuantity: 14
|
||||
trackInventory: false
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
|
@ -158,6 +158,7 @@ export const productFragmentDetails = gql`
|
|||
stocks {
|
||||
...StockFragment
|
||||
}
|
||||
trackInventory
|
||||
}
|
||||
productType {
|
||||
id
|
||||
|
@ -225,6 +226,7 @@ export const fragmentVariant = gql`
|
|||
stocks {
|
||||
...StockFragment
|
||||
}
|
||||
trackInventory
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ export interface Product_variants {
|
|||
priceOverride: Product_variants_priceOverride | null;
|
||||
margin: number | null;
|
||||
stocks: (Product_variants_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface Product_productType {
|
||||
|
|
|
@ -154,6 +154,7 @@ export interface ProductCreate_productCreate_product_variants {
|
|||
priceOverride: ProductCreate_productCreate_product_variants_priceOverride | null;
|
||||
margin: number | null;
|
||||
stocks: (ProductCreate_productCreate_product_variants_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface ProductCreate_productCreate_product_productType {
|
||||
|
|
|
@ -148,6 +148,7 @@ export interface ProductDetails_product_variants {
|
|||
priceOverride: ProductDetails_product_variants_priceOverride | null;
|
||||
margin: number | null;
|
||||
stocks: (ProductDetails_product_variants_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface ProductDetails_product_productType_variantAttributes_values {
|
||||
|
|
|
@ -154,6 +154,7 @@ export interface ProductImageCreate_productImageCreate_product_variants {
|
|||
priceOverride: ProductImageCreate_productImageCreate_product_variants_priceOverride | null;
|
||||
margin: number | null;
|
||||
stocks: (ProductImageCreate_productImageCreate_product_variants_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface ProductImageCreate_productImageCreate_product_productType {
|
||||
|
|
|
@ -154,6 +154,7 @@ export interface ProductImageUpdate_productImageUpdate_product_variants {
|
|||
priceOverride: ProductImageUpdate_productImageUpdate_product_variants_priceOverride | null;
|
||||
margin: number | null;
|
||||
stocks: (ProductImageUpdate_productImageUpdate_product_variants_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface ProductImageUpdate_productImageUpdate_product_productType {
|
||||
|
|
|
@ -154,6 +154,7 @@ export interface ProductUpdate_productUpdate_product_variants {
|
|||
priceOverride: ProductUpdate_productUpdate_product_variants_priceOverride | null;
|
||||
margin: number | null;
|
||||
stocks: (ProductUpdate_productUpdate_product_variants_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface ProductUpdate_productUpdate_product_productType {
|
||||
|
|
|
@ -113,4 +113,5 @@ export interface ProductVariant {
|
|||
product: ProductVariant_product;
|
||||
sku: string;
|
||||
stocks: (ProductVariant_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ export interface ProductVariantDetails_productVariant {
|
|||
product: ProductVariantDetails_productVariant_product;
|
||||
sku: string;
|
||||
stocks: (ProductVariantDetails_productVariant_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface ProductVariantDetails {
|
||||
|
|
|
@ -154,6 +154,7 @@ export interface SimpleProductUpdate_productUpdate_product_variants {
|
|||
priceOverride: SimpleProductUpdate_productUpdate_product_variants_priceOverride | null;
|
||||
margin: number | null;
|
||||
stocks: (SimpleProductUpdate_productUpdate_product_variants_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface SimpleProductUpdate_productUpdate_product_productType {
|
||||
|
@ -305,6 +306,7 @@ export interface SimpleProductUpdate_productVariantUpdate_productVariant {
|
|||
product: SimpleProductUpdate_productVariantUpdate_productVariant_product;
|
||||
sku: string;
|
||||
stocks: (SimpleProductUpdate_productVariantUpdate_productVariant_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface SimpleProductUpdate_productVariantUpdate {
|
||||
|
|
|
@ -121,6 +121,7 @@ export interface VariantCreate_productVariantCreate_productVariant {
|
|||
product: VariantCreate_productVariantCreate_productVariant_product;
|
||||
sku: string;
|
||||
stocks: (VariantCreate_productVariantCreate_productVariant_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface VariantCreate_productVariantCreate {
|
||||
|
|
|
@ -121,6 +121,7 @@ export interface VariantImageAssign_variantImageAssign_productVariant {
|
|||
product: VariantImageAssign_variantImageAssign_productVariant_product;
|
||||
sku: string;
|
||||
stocks: (VariantImageAssign_variantImageAssign_productVariant_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface VariantImageAssign_variantImageAssign {
|
||||
|
|
|
@ -121,6 +121,7 @@ export interface VariantImageUnassign_variantImageUnassign_productVariant {
|
|||
product: VariantImageUnassign_variantImageUnassign_productVariant_product;
|
||||
sku: string;
|
||||
stocks: (VariantImageUnassign_variantImageUnassign_productVariant_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface VariantImageUnassign_variantImageUnassign {
|
||||
|
|
|
@ -121,6 +121,7 @@ export interface VariantUpdate_productVariantUpdate_productVariant {
|
|||
product: VariantUpdate_productVariantUpdate_productVariant_product;
|
||||
sku: string;
|
||||
stocks: (VariantUpdate_productVariantUpdate_productVariant_stocks | null)[] | null;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export interface VariantUpdate_productVariantUpdate {
|
||||
|
|
|
@ -13,6 +13,7 @@ import { ProductAttributeInput } from "../components/ProductAttributes";
|
|||
import { VariantAttributeInput } from "../components/ProductVariantAttributes";
|
||||
import { ProductVariant } from "../types/ProductVariant";
|
||||
import { ProductVariantCreateData_product } from "../types/ProductVariantCreateData";
|
||||
import { ProductStockInput } from "../components/ProductStocks";
|
||||
|
||||
export interface Collection {
|
||||
id: string;
|
||||
|
@ -117,6 +118,17 @@ export function getVariantAttributeInputFromProduct(
|
|||
);
|
||||
}
|
||||
|
||||
export function getStockInputFromProduct(
|
||||
product: ProductDetails_product
|
||||
): ProductStockInput[] {
|
||||
return product?.variants[0].stocks.map(stock => ({
|
||||
data: null,
|
||||
id: stock.warehouse.id,
|
||||
label: stock.warehouse.name,
|
||||
value: stock.quantity.toString()
|
||||
}));
|
||||
}
|
||||
|
||||
export function getCollectionInput(
|
||||
productCollections: ProductDetails_product_collections[]
|
||||
): Collection[] {
|
||||
|
@ -153,7 +165,7 @@ export interface ProductUpdatePageFormData {
|
|||
seoDescription: string;
|
||||
seoTitle: string;
|
||||
sku: string;
|
||||
stockQuantity: number;
|
||||
trackInventory: boolean;
|
||||
}
|
||||
|
||||
export function getProductUpdatePageFormData(
|
||||
|
@ -183,14 +195,6 @@ export function getProductUpdatePageFormData(
|
|||
: undefined,
|
||||
""
|
||||
),
|
||||
stockQuantity: maybe(
|
||||
() =>
|
||||
product.productType.hasVariants
|
||||
? undefined
|
||||
: variants && variants[0]
|
||||
? variants[0].quantity
|
||||
: undefined,
|
||||
0
|
||||
)
|
||||
trackInventory: !!product?.variants[0]?.trackInventory
|
||||
};
|
||||
}
|
||||
|
|
|
@ -232,11 +232,6 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
|||
variants={maybe(() => product.variants)}
|
||||
onBack={handleBack}
|
||||
onDelete={() => openModal("remove")}
|
||||
onProductShow={() => {
|
||||
if (product) {
|
||||
window.open(product.url);
|
||||
}
|
||||
}}
|
||||
onImageReorder={handleImageReorder}
|
||||
onSubmit={handleSubmit}
|
||||
onVariantAdd={handleVariantAdd}
|
||||
|
|
Loading…
Reference in a new issue