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>
|
||||
<ProductVariantCreateTabs step={step} onStepClick={onStepClick} />
|
||||
<div className={classes.root}>
|
||||
{step === "values" && (
|
||||
{step === ProductVariantCreateStep.values && (
|
||||
<ProductVariantCreateValues
|
||||
attributes={selectedAttributes}
|
||||
data={data}
|
||||
|
@ -75,7 +75,7 @@ const ProductVariantCreateContent: React.FC<ProductVariantCreateContentProps> =
|
|||
}
|
||||
/>
|
||||
)}
|
||||
{step === "prices" && (
|
||||
{step === ProductVariantCreateStep.prices && (
|
||||
<ProductVariantCreatePrices
|
||||
attributes={selectedAttributes}
|
||||
currencySymbol={currencySymbol}
|
||||
|
@ -116,7 +116,7 @@ const ProductVariantCreateContent: React.FC<ProductVariantCreateContentProps> =
|
|||
}
|
||||
/>
|
||||
)}
|
||||
{step === "summary" && (
|
||||
{step === ProductVariantCreateStep.summary && (
|
||||
<ProductVariantCreateSummary
|
||||
attributes={selectedAttributes}
|
||||
currencySymbol={currencySymbol}
|
||||
|
|
|
@ -9,6 +9,7 @@ import { FormattedMessage } from "react-intl";
|
|||
|
||||
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
||||
import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen";
|
||||
import useWizard from "@saleor/hooks/useWizard";
|
||||
import { ProductVariantBulkCreateInput } from "../../../types/globalTypes";
|
||||
import { createInitialForm, ProductVariantCreateFormData } from "./form";
|
||||
import ProductVariantCreateContent, {
|
||||
|
@ -39,9 +40,9 @@ function canHitNext(
|
|||
data: ProductVariantCreateFormData
|
||||
): boolean {
|
||||
switch (step) {
|
||||
case "values":
|
||||
case ProductVariantCreateStep.values:
|
||||
return data.attributes.every(attribute => attribute.values.length > 0);
|
||||
case "prices":
|
||||
case ProductVariantCreateStep.prices:
|
||||
if (data.price.all) {
|
||||
if (data.price.value === "") {
|
||||
return false;
|
||||
|
@ -69,7 +70,7 @@ function canHitNext(
|
|||
}
|
||||
|
||||
return true;
|
||||
case "summary":
|
||||
case ProductVariantCreateStep.summary:
|
||||
return data.variants.every(variant => variant.sku !== "");
|
||||
|
||||
default:
|
||||
|
@ -88,9 +89,7 @@ export interface ProductVariantCreateDialogProps
|
|||
onSubmit: (data: ProductVariantBulkCreateInput[]) => void;
|
||||
}
|
||||
|
||||
const ProductVariantCreateDialog: React.FC<
|
||||
ProductVariantCreateDialogProps
|
||||
> = props => {
|
||||
const ProductVariantCreateDialog: React.FC<ProductVariantCreateDialogProps> = props => {
|
||||
const {
|
||||
attributes,
|
||||
defaultPrice,
|
||||
|
@ -101,29 +100,13 @@ const ProductVariantCreateDialog: React.FC<
|
|||
...contentProps
|
||||
} = props;
|
||||
const classes = useStyles(props);
|
||||
const [step, setStep] = React.useState<ProductVariantCreateStep>("values");
|
||||
|
||||
function handleNextStep() {
|
||||
switch (step) {
|
||||
case "values":
|
||||
setStep("prices");
|
||||
break;
|
||||
case "prices":
|
||||
setStep("summary");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function handlePrevStep() {
|
||||
switch (step) {
|
||||
case "prices":
|
||||
setStep("values");
|
||||
break;
|
||||
case "summary":
|
||||
setStep("prices");
|
||||
break;
|
||||
}
|
||||
}
|
||||
const [step, { next, prev, set: setStep }] = useWizard<
|
||||
ProductVariantCreateStep
|
||||
>(ProductVariantCreateStep.values, [
|
||||
ProductVariantCreateStep.values,
|
||||
ProductVariantCreateStep.prices,
|
||||
ProductVariantCreateStep.summary
|
||||
]);
|
||||
|
||||
const [data, dispatchFormDataAction] = React.useReducer(
|
||||
reduceProductVariantCreateFormData,
|
||||
|
@ -141,7 +124,7 @@ const ProductVariantCreateDialog: React.FC<
|
|||
useModalDialogOpen(open, {
|
||||
onClose: () => {
|
||||
reloadForm();
|
||||
setStep("values");
|
||||
setStep(ProductVariantCreateStep.values);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -171,25 +154,21 @@ const ProductVariantCreateDialog: React.FC<
|
|||
<FormattedMessage defaultMessage="Cancel" description="button" />
|
||||
</Button>
|
||||
<div className={classes.spacer} />
|
||||
{step !== "values" && (
|
||||
<Button
|
||||
className={classes.button}
|
||||
color="primary"
|
||||
onClick={handlePrevStep}
|
||||
>
|
||||
{step !== ProductVariantCreateStep.values && (
|
||||
<Button className={classes.button} color="primary" onClick={prev}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Previous"
|
||||
description="previous step, button"
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
{step !== "summary" ? (
|
||||
{step !== ProductVariantCreateStep.summary ? (
|
||||
<Button
|
||||
className={classes.button}
|
||||
color="primary"
|
||||
disabled={!canHitNext(step, data)}
|
||||
variant="contained"
|
||||
onClick={handleNextStep}
|
||||
onClick={next}
|
||||
>
|
||||
<FormattedMessage defaultMessage="Next" description="button" />
|
||||
</Button>
|
||||
|
|
|
@ -17,21 +17,21 @@ function getSteps(intl: IntlShape): Step[] {
|
|||
defaultMessage: "Select Values",
|
||||
description: "attribute values, variant creation step"
|
||||
}),
|
||||
value: "values"
|
||||
value: ProductVariantCreateStep.values
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Prices and SKU",
|
||||
description: "variant creation step"
|
||||
}),
|
||||
value: "prices"
|
||||
value: ProductVariantCreateStep.prices
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Summary",
|
||||
description: "variant creation step"
|
||||
}),
|
||||
value: "summary"
|
||||
value: ProductVariantCreateStep.summary
|
||||
}
|
||||
];
|
||||
}
|
||||
|
@ -71,9 +71,7 @@ export interface ProductVariantCreateTabsProps {
|
|||
onStepClick: (step: ProductVariantCreateStep) => void;
|
||||
}
|
||||
|
||||
const ProductVariantCreateTabs: React.FC<
|
||||
ProductVariantCreateTabsProps
|
||||
> = props => {
|
||||
const ProductVariantCreateTabs: React.FC<ProductVariantCreateTabsProps> = props => {
|
||||
const { step: currentStep, onStepClick } = props;
|
||||
const classes = useStyles(props);
|
||||
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