Remove attribute selection
This commit is contained in:
parent
0148bc4527
commit
36396c9d3e
8 changed files with 47 additions and 149 deletions
|
@ -1,77 +0,0 @@
|
||||||
import Table from "@material-ui/core/Table";
|
|
||||||
import TableBody from "@material-ui/core/TableBody";
|
|
||||||
import TableCell from "@material-ui/core/TableCell";
|
|
||||||
import TableRow from "@material-ui/core/TableRow";
|
|
||||||
import makeStyles from "@material-ui/styles/makeStyles";
|
|
||||||
import React from "react";
|
|
||||||
import { FormattedMessage } from "react-intl";
|
|
||||||
|
|
||||||
import Checkbox from "@saleor/components/Checkbox";
|
|
||||||
import { maybe, renderCollection } from "@saleor/misc";
|
|
||||||
import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails";
|
|
||||||
import { ProductVariantCreateFormData } from "./form";
|
|
||||||
|
|
||||||
export interface ProductVariantCreateAttributesProps {
|
|
||||||
attributes: ProductDetails_product_productType_variantAttributes[];
|
|
||||||
data: ProductVariantCreateFormData;
|
|
||||||
onAttributeClick: (id: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
checkboxCell: {
|
|
||||||
paddingLeft: 0
|
|
||||||
},
|
|
||||||
wideCell: {
|
|
||||||
width: "100%"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const ProductVariantCreateAttributes: React.FC<
|
|
||||||
ProductVariantCreateAttributesProps
|
|
||||||
> = props => {
|
|
||||||
const { attributes, data, onAttributeClick } = props;
|
|
||||||
const classes = useStyles(props);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Table key="table">
|
|
||||||
<TableBody>
|
|
||||||
{renderCollection(
|
|
||||||
attributes,
|
|
||||||
attribute => {
|
|
||||||
if (!attribute) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const isChecked = !!data.attributes.find(
|
|
||||||
selectedAttribute => selectedAttribute.id === attribute.id
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TableRow key={maybe(() => attribute.id)}>
|
|
||||||
<TableCell padding="checkbox" className={classes.checkboxCell}>
|
|
||||||
<Checkbox
|
|
||||||
checked={isChecked}
|
|
||||||
disableClickPropagation={true}
|
|
||||||
onChange={() => onAttributeClick(attribute.id)}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className={classes.wideCell}>
|
|
||||||
{attribute.name}
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
() => (
|
|
||||||
<TableRow>
|
|
||||||
<TableCell colSpan={2}>
|
|
||||||
<FormattedMessage defaultMessage="This product type has no variant attributes" />
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ProductVariantCreateAttributes.displayName = "ProductVariantCreateAttributes";
|
|
||||||
export default ProductVariantCreateAttributes;
|
|
|
@ -5,7 +5,6 @@ import { ProductDetails_product_productType_variantAttributes } from "@saleor/pr
|
||||||
import { ProductVariantBulkCreate_productVariantBulkCreate_bulkProductErrors } from "@saleor/products/types/ProductVariantBulkCreate";
|
import { ProductVariantBulkCreate_productVariantBulkCreate_bulkProductErrors } from "@saleor/products/types/ProductVariantBulkCreate";
|
||||||
import { isSelected } from "@saleor/utils/lists";
|
import { isSelected } from "@saleor/utils/lists";
|
||||||
import { ProductVariantCreateFormData } from "./form";
|
import { ProductVariantCreateFormData } from "./form";
|
||||||
import ProductVariantCreateAttributes from "./ProductVariantCreateAttributes";
|
|
||||||
import ProductVariantCreatePrices from "./ProductVariantCreatePrices";
|
import ProductVariantCreatePrices from "./ProductVariantCreatePrices";
|
||||||
import ProductVariantCreateSummary from "./ProductVariantCreateSummary";
|
import ProductVariantCreateSummary from "./ProductVariantCreateSummary";
|
||||||
import ProductVariantCreateTabs from "./ProductVariantCreateTabs";
|
import ProductVariantCreateTabs from "./ProductVariantCreateTabs";
|
||||||
|
@ -54,18 +53,6 @@ const ProductVariantCreateContent: React.FC<
|
||||||
<div>
|
<div>
|
||||||
<ProductVariantCreateTabs step={step} />
|
<ProductVariantCreateTabs step={step} />
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
{step === "attributes" && (
|
|
||||||
<ProductVariantCreateAttributes
|
|
||||||
attributes={attributes}
|
|
||||||
data={data}
|
|
||||||
onAttributeClick={attributeId =>
|
|
||||||
dispatchFormDataAction({
|
|
||||||
attributeId,
|
|
||||||
type: "selectAttribute"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{step === "values" && (
|
{step === "values" && (
|
||||||
<ProductVariantCreateValues
|
<ProductVariantCreateValues
|
||||||
attributes={selectedAttributes}
|
attributes={selectedAttributes}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import React from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import { ProductVariantBulkCreateInput } from "../../../types/globalTypes";
|
import { ProductVariantBulkCreateInput } from "../../../types/globalTypes";
|
||||||
import { initialForm, ProductVariantCreateFormData } from "./form";
|
import { createInitialForm, ProductVariantCreateFormData } from "./form";
|
||||||
import ProductVariantCreateContent, {
|
import ProductVariantCreateContent, {
|
||||||
ProductVariantCreateContentProps
|
ProductVariantCreateContentProps
|
||||||
} from "./ProductVariantCreateContent";
|
} from "./ProductVariantCreateContent";
|
||||||
|
@ -32,8 +32,6 @@ function canHitNext(
|
||||||
data: ProductVariantCreateFormData
|
data: ProductVariantCreateFormData
|
||||||
): boolean {
|
): boolean {
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case "attributes":
|
|
||||||
return data.attributes.length > 0;
|
|
||||||
case "values":
|
case "values":
|
||||||
return data.attributes.every(attribute => attribute.values.length > 0);
|
return data.attributes.every(attribute => attribute.values.length > 0);
|
||||||
case "prices":
|
case "prices":
|
||||||
|
@ -77,6 +75,7 @@ export interface ProductVariantCreateDialogProps
|
||||||
ProductVariantCreateContentProps,
|
ProductVariantCreateContentProps,
|
||||||
"data" | "dispatchFormDataAction" | "step"
|
"data" | "dispatchFormDataAction" | "step"
|
||||||
> {
|
> {
|
||||||
|
defaultPrice: string;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSubmit: (data: ProductVariantBulkCreateInput[]) => void;
|
onSubmit: (data: ProductVariantBulkCreateInput[]) => void;
|
||||||
|
@ -85,17 +84,19 @@ export interface ProductVariantCreateDialogProps
|
||||||
const ProductVariantCreateDialog: React.FC<
|
const ProductVariantCreateDialog: React.FC<
|
||||||
ProductVariantCreateDialogProps
|
ProductVariantCreateDialogProps
|
||||||
> = props => {
|
> = props => {
|
||||||
const { open, onClose, onSubmit, ...contentProps } = props;
|
const {
|
||||||
|
attributes,
|
||||||
|
defaultPrice,
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
onSubmit,
|
||||||
|
...contentProps
|
||||||
|
} = props;
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
const [step, setStep] = React.useState<ProductVariantCreateStep>(
|
const [step, setStep] = React.useState<ProductVariantCreateStep>("values");
|
||||||
"attributes"
|
|
||||||
);
|
|
||||||
|
|
||||||
function handleNextStep() {
|
function handleNextStep() {
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case "attributes":
|
|
||||||
setStep("values");
|
|
||||||
break;
|
|
||||||
case "values":
|
case "values":
|
||||||
setStep("prices");
|
setStep("prices");
|
||||||
break;
|
break;
|
||||||
|
@ -107,9 +108,6 @@ const ProductVariantCreateDialog: React.FC<
|
||||||
|
|
||||||
function handlePrevStep() {
|
function handlePrevStep() {
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case "values":
|
|
||||||
setStep("attributes");
|
|
||||||
break;
|
|
||||||
case "prices":
|
case "prices":
|
||||||
setStep("values");
|
setStep("values");
|
||||||
break;
|
break;
|
||||||
|
@ -121,7 +119,16 @@ const ProductVariantCreateDialog: React.FC<
|
||||||
|
|
||||||
const [data, dispatchFormDataAction] = React.useReducer(
|
const [data, dispatchFormDataAction] = React.useReducer(
|
||||||
reduceProductVariantCreateFormData,
|
reduceProductVariantCreateFormData,
|
||||||
initialForm
|
createInitialForm(attributes, defaultPrice)
|
||||||
|
);
|
||||||
|
|
||||||
|
React.useEffect(
|
||||||
|
() =>
|
||||||
|
dispatchFormDataAction({
|
||||||
|
data: createInitialForm(attributes, defaultPrice),
|
||||||
|
type: "reload"
|
||||||
|
}),
|
||||||
|
[attributes.length]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -135,6 +142,7 @@ const ProductVariantCreateDialog: React.FC<
|
||||||
<DialogContent className={classes.content}>
|
<DialogContent className={classes.content}>
|
||||||
<ProductVariantCreateContent
|
<ProductVariantCreateContent
|
||||||
{...contentProps}
|
{...contentProps}
|
||||||
|
attributes={attributes}
|
||||||
data={data}
|
data={data}
|
||||||
dispatchFormDataAction={dispatchFormDataAction}
|
dispatchFormDataAction={dispatchFormDataAction}
|
||||||
step={step}
|
step={step}
|
||||||
|
@ -144,7 +152,7 @@ const ProductVariantCreateDialog: React.FC<
|
||||||
<Button className={classes.button} onClick={onClose}>
|
<Button className={classes.button} onClick={onClose}>
|
||||||
<FormattedMessage defaultMessage="Cancel" description="button" />
|
<FormattedMessage defaultMessage="Cancel" description="button" />
|
||||||
</Button>
|
</Button>
|
||||||
{step !== "attributes" && (
|
{step !== "values" && (
|
||||||
<Button
|
<Button
|
||||||
className={classes.button}
|
className={classes.button}
|
||||||
color="primary"
|
color="primary"
|
||||||
|
|
|
@ -13,13 +13,6 @@ interface Step {
|
||||||
}
|
}
|
||||||
function getSteps(intl: IntlShape): Step[] {
|
function getSteps(intl: IntlShape): Step[] {
|
||||||
return [
|
return [
|
||||||
{
|
|
||||||
label: intl.formatMessage({
|
|
||||||
defaultMessage: "Choose Attributes",
|
|
||||||
description: "variant creation step"
|
|
||||||
}),
|
|
||||||
value: "attributes"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: intl.formatMessage({
|
label: intl.formatMessage({
|
||||||
defaultMessage: "Select Values",
|
defaultMessage: "Select Values",
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { ProductDetails_product_productType_variantAttributes } from "@saleor/products/types/ProductDetails";
|
||||||
import { ProductVariantBulkCreateInput } from "../../../types/globalTypes";
|
import { ProductVariantBulkCreateInput } from "../../../types/globalTypes";
|
||||||
|
|
||||||
export interface AttributeValue {
|
export interface AttributeValue {
|
||||||
|
@ -21,12 +22,18 @@ export interface ProductVariantCreateFormData {
|
||||||
variants: ProductVariantBulkCreateInput[];
|
variants: ProductVariantBulkCreateInput[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialForm: ProductVariantCreateFormData = {
|
export const createInitialForm = (
|
||||||
attributes: [],
|
attributes: ProductDetails_product_productType_variantAttributes[],
|
||||||
|
price: string
|
||||||
|
): ProductVariantCreateFormData => ({
|
||||||
|
attributes: attributes.map(attribute => ({
|
||||||
|
id: attribute.id,
|
||||||
|
values: []
|
||||||
|
})),
|
||||||
price: {
|
price: {
|
||||||
all: true,
|
all: true,
|
||||||
attribute: undefined,
|
attribute: undefined,
|
||||||
value: "",
|
value: price || "",
|
||||||
values: []
|
values: []
|
||||||
},
|
},
|
||||||
stock: {
|
stock: {
|
||||||
|
@ -36,4 +43,4 @@ export const initialForm: ProductVariantCreateFormData = {
|
||||||
values: []
|
values: []
|
||||||
},
|
},
|
||||||
variants: []
|
variants: []
|
||||||
};
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
updateAtIndex
|
updateAtIndex
|
||||||
} from "@saleor/utils/lists";
|
} from "@saleor/utils/lists";
|
||||||
import { createVariants } from "./createVariants";
|
import { createVariants } from "./createVariants";
|
||||||
import { initialForm, ProductVariantCreateFormData } from "./form";
|
import { ProductVariantCreateFormData } from "./form";
|
||||||
|
|
||||||
export type ProductVariantCreateReducerActionType =
|
export type ProductVariantCreateReducerActionType =
|
||||||
| "applyPriceToAll"
|
| "applyPriceToAll"
|
||||||
|
@ -21,13 +21,14 @@ export type ProductVariantCreateReducerActionType =
|
||||||
| "changeAttributeValueStock"
|
| "changeAttributeValueStock"
|
||||||
| "changeVariantData"
|
| "changeVariantData"
|
||||||
| "deleteVariant"
|
| "deleteVariant"
|
||||||
| "selectAttribute"
|
| "reload"
|
||||||
| "selectValue";
|
| "selectValue";
|
||||||
|
|
||||||
export type VariantField = "stock" | "price" | "sku";
|
export type VariantField = "stock" | "price" | "sku";
|
||||||
export interface ProductVariantCreateReducerAction {
|
export interface ProductVariantCreateReducerAction {
|
||||||
all?: boolean;
|
all?: boolean;
|
||||||
attributeId?: string;
|
attributeId?: string;
|
||||||
|
data?: ProductVariantCreateFormData;
|
||||||
field?: VariantField;
|
field?: VariantField;
|
||||||
type: ProductVariantCreateReducerActionType;
|
type: ProductVariantCreateReducerActionType;
|
||||||
value?: string;
|
value?: string;
|
||||||
|
@ -35,31 +36,12 @@ export interface ProductVariantCreateReducerAction {
|
||||||
variantIndex?: number;
|
variantIndex?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectAttribute(
|
|
||||||
state: ProductVariantCreateFormData,
|
|
||||||
attributeId: string
|
|
||||||
): ProductVariantCreateFormData {
|
|
||||||
const attributes = toggle(
|
|
||||||
{
|
|
||||||
id: attributeId,
|
|
||||||
values: []
|
|
||||||
},
|
|
||||||
state.attributes,
|
|
||||||
(a, b) => a.id === b.id
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...initialForm,
|
|
||||||
attributes
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectValue(
|
function selectValue(
|
||||||
state: ProductVariantCreateFormData,
|
prevState: ProductVariantCreateFormData,
|
||||||
attributeId: string,
|
attributeId: string,
|
||||||
valueId: string
|
valueId: string
|
||||||
): ProductVariantCreateFormData {
|
): ProductVariantCreateFormData {
|
||||||
const attribute = state.attributes.find(
|
const attribute = prevState.attributes.find(
|
||||||
attribute => attribute.id === attributeId
|
attribute => attribute.id === attributeId
|
||||||
);
|
);
|
||||||
const values = toggle(valueId, attribute.values, (a, b) => a === b);
|
const values = toggle(valueId, attribute.values, (a, b) => a === b);
|
||||||
|
@ -68,11 +50,11 @@ function selectValue(
|
||||||
id: attributeId,
|
id: attributeId,
|
||||||
values
|
values
|
||||||
},
|
},
|
||||||
remove(attribute, state.attributes, (a, b) => a.id === b.id)
|
remove(attribute, prevState.attributes, (a, b) => a.id === b.id)
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...initialForm,
|
...prevState,
|
||||||
attributes: updatedAttributes
|
attributes: updatedAttributes
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -310,9 +292,6 @@ function reduceProductVariantCreateFormData(
|
||||||
action: ProductVariantCreateReducerAction
|
action: ProductVariantCreateReducerAction
|
||||||
) {
|
) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "selectAttribute":
|
|
||||||
return selectAttribute(prevState, action.attributeId);
|
|
||||||
|
|
||||||
case "selectValue":
|
case "selectValue":
|
||||||
return selectValue(prevState, action.attributeId, action.valueId);
|
return selectValue(prevState, action.attributeId, action.valueId);
|
||||||
|
|
||||||
|
@ -341,6 +320,8 @@ function reduceProductVariantCreateFormData(
|
||||||
);
|
);
|
||||||
case "deleteVariant":
|
case "deleteVariant":
|
||||||
return deleteVariant(prevState, action.variantIndex);
|
return deleteVariant(prevState, action.variantIndex);
|
||||||
|
case "reload":
|
||||||
|
return action.data;
|
||||||
default:
|
default:
|
||||||
return prevState;
|
return prevState;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1 @@
|
||||||
export type ProductVariantCreateStep =
|
export type ProductVariantCreateStep = "values" | "prices" | "summary";
|
||||||
| "attributes"
|
|
||||||
| "values"
|
|
||||||
| "prices"
|
|
||||||
| "summary";
|
|
||||||
|
|
|
@ -353,6 +353,9 @@ export const ProductUpdate: React.StatelessComponent<ProductUpdateProps> = ({
|
||||||
</DialogContentText>
|
</DialogContentText>
|
||||||
</ActionDialog>
|
</ActionDialog>
|
||||||
<ProductVariantCreateDialog
|
<ProductVariantCreateDialog
|
||||||
|
defaultPrice={maybe(() =>
|
||||||
|
data.product.basePrice.amount.toFixed(2)
|
||||||
|
)}
|
||||||
errors={maybe(
|
errors={maybe(
|
||||||
() =>
|
() =>
|
||||||
bulkProductVariantCreate.opts.data
|
bulkProductVariantCreate.opts.data
|
||||||
|
|
Loading…
Reference in a new issue