Use dedicated wizard hook
This commit is contained in:
parent
5967c71d13
commit
50ff050155
8 changed files with 76 additions and 48 deletions
47
src/hooks/useWizard.ts
Normal file
47
src/hooks/useWizard.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export interface UseWizardOpts<T> {
|
||||||
|
next: () => void;
|
||||||
|
prev: () => void;
|
||||||
|
set: (step: T) => void;
|
||||||
|
}
|
||||||
|
export type UseWizard<T> = [T, UseWizardOpts<T>];
|
||||||
|
function useWizard<T>(initial: T, steps: T[]): UseWizard<T> {
|
||||||
|
const [stepIndex, setStepIndex] = useState(steps.indexOf(initial));
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
if (stepIndex === steps.length - 1) {
|
||||||
|
console.error("This is the last step");
|
||||||
|
} else {
|
||||||
|
setStepIndex(stepIndex + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function prev() {
|
||||||
|
if (stepIndex === 0) {
|
||||||
|
console.error("This is the first step");
|
||||||
|
} else {
|
||||||
|
setStepIndex(stepIndex - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function set(step: T) {
|
||||||
|
const newStepIndex = steps.findIndex(s => s === step);
|
||||||
|
if (newStepIndex === -1) {
|
||||||
|
console.error("Step does not exist");
|
||||||
|
} else {
|
||||||
|
setStepIndex(newStepIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
steps[stepIndex],
|
||||||
|
{
|
||||||
|
next,
|
||||||
|
prev,
|
||||||
|
set
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useWizard;
|
|
@ -62,7 +62,7 @@ const ProductVariantCreateContent: React.FC<ProductVariantCreateContentProps> =
|
||||||
<div>
|
<div>
|
||||||
<ProductVariantCreateTabs step={step} onStepClick={onStepClick} />
|
<ProductVariantCreateTabs step={step} onStepClick={onStepClick} />
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
{step === "values" && (
|
{step === ProductVariantCreateStep.values && (
|
||||||
<ProductVariantCreateValues
|
<ProductVariantCreateValues
|
||||||
attributes={selectedAttributes}
|
attributes={selectedAttributes}
|
||||||
data={data}
|
data={data}
|
||||||
|
@ -75,7 +75,7 @@ const ProductVariantCreateContent: React.FC<ProductVariantCreateContentProps> =
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{step === "prices" && (
|
{step === ProductVariantCreateStep.prices && (
|
||||||
<ProductVariantCreatePrices
|
<ProductVariantCreatePrices
|
||||||
attributes={selectedAttributes}
|
attributes={selectedAttributes}
|
||||||
currencySymbol={currencySymbol}
|
currencySymbol={currencySymbol}
|
||||||
|
@ -116,7 +116,7 @@ const ProductVariantCreateContent: React.FC<ProductVariantCreateContentProps> =
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{step === "summary" && (
|
{step === ProductVariantCreateStep.summary && (
|
||||||
<ProductVariantCreateSummary
|
<ProductVariantCreateSummary
|
||||||
attributes={selectedAttributes}
|
attributes={selectedAttributes}
|
||||||
currencySymbol={currencySymbol}
|
currencySymbol={currencySymbol}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
||||||
import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen";
|
import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen";
|
||||||
|
import useWizard from "@saleor/hooks/useWizard";
|
||||||
import { ProductVariantBulkCreateInput } from "../../../types/globalTypes";
|
import { ProductVariantBulkCreateInput } from "../../../types/globalTypes";
|
||||||
import { createInitialForm, ProductVariantCreateFormData } from "./form";
|
import { createInitialForm, ProductVariantCreateFormData } from "./form";
|
||||||
import ProductVariantCreateContent, {
|
import ProductVariantCreateContent, {
|
||||||
|
@ -39,9 +40,9 @@ function canHitNext(
|
||||||
data: ProductVariantCreateFormData
|
data: ProductVariantCreateFormData
|
||||||
): boolean {
|
): boolean {
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case "values":
|
case ProductVariantCreateStep.values:
|
||||||
return data.attributes.every(attribute => attribute.values.length > 0);
|
return data.attributes.every(attribute => attribute.values.length > 0);
|
||||||
case "prices":
|
case ProductVariantCreateStep.prices:
|
||||||
if (data.price.all) {
|
if (data.price.all) {
|
||||||
if (data.price.value === "") {
|
if (data.price.value === "") {
|
||||||
return false;
|
return false;
|
||||||
|
@ -69,7 +70,7 @@ function canHitNext(
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
case "summary":
|
case ProductVariantCreateStep.summary:
|
||||||
return data.variants.every(variant => variant.sku !== "");
|
return data.variants.every(variant => variant.sku !== "");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -88,9 +89,7 @@ export interface ProductVariantCreateDialogProps
|
||||||
onSubmit: (data: ProductVariantBulkCreateInput[]) => void;
|
onSubmit: (data: ProductVariantBulkCreateInput[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductVariantCreateDialog: React.FC<
|
const ProductVariantCreateDialog: React.FC<ProductVariantCreateDialogProps> = props => {
|
||||||
ProductVariantCreateDialogProps
|
|
||||||
> = props => {
|
|
||||||
const {
|
const {
|
||||||
attributes,
|
attributes,
|
||||||
defaultPrice,
|
defaultPrice,
|
||||||
|
@ -101,29 +100,13 @@ const ProductVariantCreateDialog: React.FC<
|
||||||
...contentProps
|
...contentProps
|
||||||
} = props;
|
} = props;
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
const [step, setStep] = React.useState<ProductVariantCreateStep>("values");
|
const [step, { next, prev, set: setStep }] = useWizard<
|
||||||
|
ProductVariantCreateStep
|
||||||
function handleNextStep() {
|
>(ProductVariantCreateStep.values, [
|
||||||
switch (step) {
|
ProductVariantCreateStep.values,
|
||||||
case "values":
|
ProductVariantCreateStep.prices,
|
||||||
setStep("prices");
|
ProductVariantCreateStep.summary
|
||||||
break;
|
]);
|
||||||
case "prices":
|
|
||||||
setStep("summary");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlePrevStep() {
|
|
||||||
switch (step) {
|
|
||||||
case "prices":
|
|
||||||
setStep("values");
|
|
||||||
break;
|
|
||||||
case "summary":
|
|
||||||
setStep("prices");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const [data, dispatchFormDataAction] = React.useReducer(
|
const [data, dispatchFormDataAction] = React.useReducer(
|
||||||
reduceProductVariantCreateFormData,
|
reduceProductVariantCreateFormData,
|
||||||
|
@ -141,7 +124,7 @@ const ProductVariantCreateDialog: React.FC<
|
||||||
useModalDialogOpen(open, {
|
useModalDialogOpen(open, {
|
||||||
onClose: () => {
|
onClose: () => {
|
||||||
reloadForm();
|
reloadForm();
|
||||||
setStep("values");
|
setStep(ProductVariantCreateStep.values);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -171,25 +154,21 @@ const ProductVariantCreateDialog: React.FC<
|
||||||
<FormattedMessage defaultMessage="Cancel" description="button" />
|
<FormattedMessage defaultMessage="Cancel" description="button" />
|
||||||
</Button>
|
</Button>
|
||||||
<div className={classes.spacer} />
|
<div className={classes.spacer} />
|
||||||
{step !== "values" && (
|
{step !== ProductVariantCreateStep.values && (
|
||||||
<Button
|
<Button className={classes.button} color="primary" onClick={prev}>
|
||||||
className={classes.button}
|
|
||||||
color="primary"
|
|
||||||
onClick={handlePrevStep}
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Previous"
|
defaultMessage="Previous"
|
||||||
description="previous step, button"
|
description="previous step, button"
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{step !== "summary" ? (
|
{step !== ProductVariantCreateStep.summary ? (
|
||||||
<Button
|
<Button
|
||||||
className={classes.button}
|
className={classes.button}
|
||||||
color="primary"
|
color="primary"
|
||||||
disabled={!canHitNext(step, data)}
|
disabled={!canHitNext(step, data)}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={handleNextStep}
|
onClick={next}
|
||||||
>
|
>
|
||||||
<FormattedMessage defaultMessage="Next" description="button" />
|
<FormattedMessage defaultMessage="Next" description="button" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -17,21 +17,21 @@ function getSteps(intl: IntlShape): Step[] {
|
||||||
defaultMessage: "Select Values",
|
defaultMessage: "Select Values",
|
||||||
description: "attribute values, variant creation step"
|
description: "attribute values, variant creation step"
|
||||||
}),
|
}),
|
||||||
value: "values"
|
value: ProductVariantCreateStep.values
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: intl.formatMessage({
|
label: intl.formatMessage({
|
||||||
defaultMessage: "Prices and SKU",
|
defaultMessage: "Prices and SKU",
|
||||||
description: "variant creation step"
|
description: "variant creation step"
|
||||||
}),
|
}),
|
||||||
value: "prices"
|
value: ProductVariantCreateStep.prices
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: intl.formatMessage({
|
label: intl.formatMessage({
|
||||||
defaultMessage: "Summary",
|
defaultMessage: "Summary",
|
||||||
description: "variant creation step"
|
description: "variant creation step"
|
||||||
}),
|
}),
|
||||||
value: "summary"
|
value: ProductVariantCreateStep.summary
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -71,9 +71,7 @@ export interface ProductVariantCreateTabsProps {
|
||||||
onStepClick: (step: ProductVariantCreateStep) => void;
|
onStepClick: (step: ProductVariantCreateStep) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductVariantCreateTabs: React.FC<
|
const ProductVariantCreateTabs: React.FC<ProductVariantCreateTabsProps> = props => {
|
||||||
ProductVariantCreateTabsProps
|
|
||||||
> = props => {
|
|
||||||
const { step: currentStep, onStepClick } = props;
|
const { step: currentStep, onStepClick } = props;
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
|
@ -1 +1,5 @@
|
||||||
export type ProductVariantCreateStep = "values" | "prices" | "summary";
|
export enum ProductVariantCreateStep {
|
||||||
|
values,
|
||||||
|
prices,
|
||||||
|
summary
|
||||||
|
}
|
||||||
|
|
0
src/products/views/ProductMultipleVariantCreate/index.ts
Normal file
0
src/products/views/ProductMultipleVariantCreate/index.ts
Normal file
Loading…
Reference in a new issue