@material-ui/core#Stepper JavaScript Examples

The following examples show how to use @material-ui/core#Stepper. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Stepper.js    From akashlytics-deploy with GNU General Public License v3.0 6 votes vote down vote up
export function CustomizedSteppers({ steps, activeStep }) {
  const classes = useStyles();
  return (
    <Stepper alternativeLabel activeStep={activeStep} connector={<QontoConnector />} classes={{ root: classes.root }}>
      {steps.map((label) => (
        <Step key={label}>
          <StepLabel StepIconComponent={QontoStepIcon} classes={{ label: classes.label, completed: classes.labelCompleted, active: classes.labelActive }}>
            {label}
          </StepLabel>
        </Step>
      ))}
    </Stepper>
  );
}
Example #2
Source File: VaccinesOverview.js    From covid-trials-dashboard with MIT License 6 votes vote down vote up
VaccinesOverview = () => {
  const classes = useStyles()
  return (
    <div className={classes.root}>
      <Typography variant='h3' component='h2' gutterBottom>
        Phases of Vaccine Development
      </Typography>
      <Stepper activeStep={steps.length - 1} orientation='vertical'>
        {steps.map(({ label, info }) => (
          <Step key={label} expanded>
            <StepLabel>{label}</StepLabel>
            <StepContent>
              <Typography>{info}</Typography>
            </StepContent>
          </Step>
        ))}
      </Stepper>
    </div>
  )
}
Example #3
Source File: customized-stepper.js    From horondi_admin with MIT License 6 votes vote down vote up
CustomizedStepper = ({ steps, activeStep }) => {
  const styles = useStyles();

  return (
    <div className={styles.root}>
      <Stepper activeStep={activeStep} orientation='vertical'>
        {stepsLabels.map((label, index) => (
          <Step key={label}>
            <StepLabel>{label}</StepLabel>
            <StepContent>{steps[index]}</StepContent>
          </Step>
        ))}
      </Stepper>
    </div>
  );
}
Example #4
Source File: StripeConnect.js    From Merch-Dropper-fe with MIT License 5 votes vote down vote up
StripeConnect = () => {
  const [queryString, setQueryString] = useState(window.location.search);
  let stripeConnected = false;
  let stripeError = false;
  const [activeStep, setActiveStep] = useState(1);
  let userCode = "";
  const steps = getSteps();
  const profile = JSON.parse(localStorage.getItem("profile"));
  console.log(profile.email);

  if (queryString.includes("error")) {
    stripeError = true;
  }

  if (queryString.includes("code=")) {
    userCode = queryString.substring(queryString.indexOf("code=") + 5);
    console.log(userCode);

    axiosWithAuth()
      .post(`/api/stripe/accounts`, {
        user_code: userCode,
        email: profile.email,
      })
      .then((res) => {
        console.log(res);
      });

    stripeConnected = true;
  }

  return (
    <FormContainer>
      <ExitButton onClick={SkipSetup} />

      <StripeTitle>Connect Stripe</StripeTitle>
      <StepContainer>
        <Stepper activeStep={activeStep} alternativeLabel>
          {steps.map((label) => (
            <Step key={label}>
              <StepLabel>{label}</StepLabel>
            </Step>
          ))}
        </Stepper>
      </StepContainer>
      {
        //For the initial setup form
        !queryString && (
          <StripeButton onClick={ConnectStripe}>Connect Stripe</StripeButton>
        )
      }
      {
        //For the initial setup form
        (!queryString || stripeError) && (
          <StripeSkipButton onClick={SkipSetup}>Skip for now</StripeSkipButton>
        )
      }
      {   //For connecting to a faked stripe account (will not be active)
        (!queryString && process.env.REACT_APP_BASE_URL === "development") &&
        <button className='dev-stripe' onClick={DevStripeConnect}>Connect 4 Develop</button>
      }
      {queryString && stripeConnected && (
        <ConnectionMessage>Connection was successful!</ConnectionMessage>
      )}
      {
        //If we get a user code back and the connect was successful
        queryString && stripeConnected && (
          <CreateStore onClick={SkipSetup}>Create Store</CreateStore>
        )
      }
      {
        //If the connection was not successful
        stripeError && (
          <StripeButton onClick={ConnectStripe}>Try Again</StripeButton>
        )
      }
    </FormContainer>
  );
}
Example #5
Source File: FormikStepper.js    From dscbppimt-official-website with MIT License 5 votes vote down vote up
export function FormikStepper({ children, ...props}) {
    console.log(props.renderFormikForm)
    const [step, setStep] = useState(0);
    const [completed, setCompleted] = useState(false);
  
    function isLastStep() {
      return step === props.labels.length - 2;
    }
    return (
      <Formik
        {...props}
        validationSchema={props.validationSchemas[step]}
        onSubmit={async (values, helpers) => {
          if (isLastStep()) {
            helpers.setSubmitting(true);
            try{
              await props.onSubmit(values, helpers);
            }catch(e){
              console.log(e)
            }
            helpers.setSubmitting(false);
            setStep((s) => s + 1);
            setCompleted(true);
          } else {
            setStep((s) => s + 1);
          }
        }}
      >
        {({ values, isSubmitting, errors, touched, status }) => (
          <Form autoComplete="off" noValidate>
            { isSubmitting && <LinearProgress />}
            <Stepper alternativeLabel activeStep={step}>
              {props.labels.map((index) => (
                <Step key={index} completed={step > index || completed}>
                  <StepLabel>{index}</StepLabel>
                </Step>
              ))}
            </Stepper>
  
            { props.renderFormikForm(step, values, errors, touched, status) }
            { step <= props.labels.length - 2 &&
              <Grid container spacing={2} justifyContent="flex-end" style={{marginTop : '2em'}}>
              {step > 0 ? (
                <Grid item>
                  <Button
                    style={{width : '110px'}}
                    disabled={isSubmitting}
                    variant="contained"
                    color="primary"
                    onClick={() => setStep((s) => s - 1)}
                  >
                    Back
                  </Button>
                </Grid>
              ) : null}
              <Grid item>
                <Button
                  style={{width : '110px'}}
                  disabled={isSubmitting}
                  variant="contained"
                  color="primary"
                  type="submit"
                >
                  {isSubmitting ? 'Submitting' : step === props.labels.length - 2 ? 'Submit' : 'Next'}
                </Button>
              </Grid>
            </Grid>
            }

          </Form>
        )}
      </Formik>
    );
  }
Example #6
Source File: CreateEditSteps.js    From beluga with GNU General Public License v3.0 5 votes vote down vote up
CreateEditSteps = (props) => {
  const { collection, handleChange, activeStep, storeConfig } = props;

  const steps = [
    "Title and Products",
    "Cover Image"
  ];

  const getStepContent = (step) => {
    switch (step) {
      case 0:
        return <CollectionStep1
            collection={collection}
            handleChange={handleChange}
            storeConfig={storeConfig}
          />;
      case 1:
        return <CollectionStep2
            collection={collection}
            handleChange={handleChange}
            saveConfig={props.saveConfig}
          />;
      default:
        return 'ya done goofed';
    }
  }

  return (
    <Stepper activeStep={activeStep} orientation="vertical">
      {steps.map((label, index) => (
        <Step key={label}>
          <StepLabel>{label}</StepLabel>
          <StepContent>
            <div>{getStepContent(index)}</div>
            <CreateEditButtons
              activeStep={activeStep}
              setActiveStep={props.setActiveStep}
              handleNext={props.handleNext}
              steps={steps}
            />
          </StepContent>
        </Step>
      ))}
    </Stepper>
  );
}
Example #7
Source File: CreateEditSteps.js    From beluga with GNU General Public License v3.0 5 votes vote down vote up
CreateEditSteps = (props) => {
  const { product, handleChange, activeStep } = props;

  const steps = [
    "Name and Description",
    "Product Variations",
    "Price",
    "Photos"
  ];

  const getStepContent = (step) => {
    switch (step) {
      case 0:
        return <ProductStep1 product={product} handleChange={handleChange} />;
      case 1:
        return <ProductStep2 product={product} handleChange={handleChange} />;
      case 2:
        return <ProductStep3
            product={product}
            skus={props.skus}
            setSkus={props.setSkus}
          />;
      case 3:
        return <ProductStep4
            product={product}
            handleChange={handleChange}
            saveConfig={props.saveConfig}
          />;
      default:
        return 'ya done goofed';
    }
  }

  return (
    <div>
      <ExampleWrapper>
        <ExampleProductImage />
      </ExampleWrapper>

      <Stepper activeStep={activeStep} orientation="vertical">
        {steps.map((label, index) => (
          <Step key={label}>
            <StepLabel>{label}</StepLabel>
            <StepContent>
              <div>{getStepContent(index)}</div>
              <CreateEditButtons
                activeStep={activeStep}
                setActiveStep={props.setActiveStep}
                handleNext={props.handleNext}
                product={product}
                steps={steps}
              />
            </StepContent>
          </Step>
        ))}
      </Stepper>
    </div>
  );
}
Example #8
Source File: index.js    From Artion-Client with GNU General Public License v3.0 4 votes vote down vote up
PaintBoard = () => {
  const dispatch = useDispatch();
  const history = useHistory();

  const {
    explorerUrl,
    apiUrl,
    fetchMintableCollections,
    getNonce,
    addUnlockableContent,
    checkBan,
  } = useApi();

  const { registerRoyalty } = useSalesContract();
  const { loadContract } = useContract();

  const { account, chainId } = useWeb3React();

  const imageRef = useRef();

  const [selected, setSelected] = useState([]);
  const [collections, setCollections] = useState([]);
  const [nft, setNft] = useState();
  const [type, setType] = useState();
  const [image, setImage] = useState(null);
  const [fee, setFee] = useState(null);

  const [name, setName] = useState('');
  const [symbol, setSymbol] = useState('');
  const [description, setDescription] = useState('');
  const [royalty, setRoyalty] = useState('');
  const [xtra, setXtra] = useState('');
  const [supply, setSupply] = useState(0);
  const [hasUnlockableContent, setHasUnlockableContent] = useState(false);
  const [unlockableContent, setUnlockableContent] = useState('');

  const [currentMintingStep, setCurrentMintingStep] = useState(0);
  const [isMinting, setIsMinting] = useState(false);

  const [lastMintedTnxId, setLastMintedTnxId] = useState('');

  const authToken = useSelector(state => state.ConnectWallet.authToken);

  const getFee = async () => {
    setFee(null);

    try {
      const contract = await loadContract(nft, FEE_ABI);
      const _fee = await contract.platformFee();
      setFee(parseFloat(_fee.toString()) / 10 ** 18);
    } catch {
      setFee(0);
    }
  };

  const getCollections = async () => {
    try {
      const { data } = await fetchMintableCollections(authToken);
      setCollections(data);
      if (data.length) {
        setSelected([data[0]]);
      }
    } catch (err) {
      console.log(err);
    }
  };

  useEffect(() => {
    if (authToken) {
      getCollections();
    }
  }, [authToken]);

  useEffect(() => {
    if (!nft) return;

    getFee();
  }, [nft]);

  useEffect(() => {
    dispatch(HeaderActions.toggleSearchbar(true));
  }, []);

  const onDrop = useCallback(acceptedFiles => {
    setImage(acceptedFiles[0]);
  }, []);

  const { getRootProps, getInputProps } = useDropzone({
    accept: accept.join(', '),
    multiple: false,
    onDrop,
    maxSize: 15728640,
  });

  const removeImage = () => {
    setImage(null);
    if (imageRef.current) {
      imageRef.current.value = '';
    }
  };

  const imageToBase64 = () => {
    return new Promise((resolve, reject) => {
      let reader = new FileReader();
      reader.readAsDataURL(image);
      reader.onload = () => {
        resolve(reader.result);
      };
      reader.onerror = err => {
        reject(err);
      };
    });
  };

  const validateMetadata = () => {
    return name !== '' && account !== '' && image;
  };

  const resetMintingStatus = () => {
    setTimeout(() => {
      setIsMinting(false);
      setCurrentMintingStep(0);
    }, 1000);
  };

  const mintNFT = async () => {
    if (!account) {
      showToast('info', 'Connect your wallet first');
      return;
    }
    if (chainId !== ChainId.FANTOM && chainId !== ChainId.FANTOM_TESTNET) {
      showToast('info', 'You are not connected to Fantom Opera Network');
      return;
    }
    const balance = await WalletUtils.checkBalance(account);

    if (balance < fee) {
      showToast(
        'custom',
        `Your balance should be at least ${fee} FTM to mint an NFT`
      );
      return;
    }

    let isBanned = await checkBan(account, authToken);

    if (isBanned) {
      showToast('error', 'You are banned from minting');
      return;
    }

    setLastMintedTnxId('');
    // show stepper
    setIsMinting(true);
    console.log('created from ', account);
    if (!validateMetadata()) {
      resetMintingStatus();
      return;
    }

    let signature;
    let addr;

    if (hasUnlockableContent && unlockableContent.length > 0) {
      const { data: nonce } = await getNonce(account, authToken);
      try {
        const signer = await getSigner();
        const msg = `Approve Signature on Artion.io with nonce ${nonce}`;
        signature = await signer.signMessage(msg);
        addr = ethers.utils.verifyMessage(msg, signature);
      } catch (err) {
        showToast(
          'error',
          'You need to sign the message to be able to update account settings.'
        );
        resetMintingStatus();
        return;
      }
    }

    let formData = new FormData();
    const base64 = await imageToBase64();
    formData.append('image', base64);
    formData.append('name', name);
    formData.append('account', account);
    formData.append('description', description);
    formData.append('symbol', symbol);
    formData.append('xtra', xtra);
    const _royalty = parseInt(royalty) * 100;
    formData.append('royalty', isNaN(_royalty) ? 0 : _royalty);
    try {
      let result = await axios({
        method: 'post',
        url: `${apiUrl}/ipfs/uploadImage2Server`,
        data: formData,
        headers: {
          'Content-Type': 'multipart/form-data',
          Authorization: 'Bearer ' + authToken,
        },
      });

      console.log('upload image result is ');

      const jsonHash = result.data.jsonHash;

      const contract = await loadContract(
        nft,
        type === 721 ? SINGLE_NFT_ABI : MULTI_NFT_ABI
      );
      try {
        const args =
          type === 721 ? [account, jsonHash] : [account, supply, jsonHash];

        let tx;

        if (!fee) {
          tx = await contract.mint(...args);
        } else {
          const options = {
            value: ethers.utils.parseEther(fee.toString()),
            gasPrice: getHigherGWEI(),
          };
          const gasEstimate = await contract.estimateGas.mint(...args, options);
          options.gasLimit = calculateGasMargin(gasEstimate);
          tx = await contract.mint(...args, options);
        }
        setCurrentMintingStep(1);
        setLastMintedTnxId(tx.hash);

        setCurrentMintingStep(2);
        const confirmedTnx = await tx.wait();
        setCurrentMintingStep(3);
        let mintedTkId;
        if (type === 721) {
          const evtCaught = confirmedTnx.logs[0].topics;
          mintedTkId = BigNumber.from(evtCaught[3]);
        } else {
          mintedTkId = BigNumber.from(
            ethers.utils.hexDataSlice(confirmedTnx.logs[1].data, 0, 32)
          );
        }

        const royaltyTx = await registerRoyalty(
          nft,
          mintedTkId.toNumber(),
          isNaN(_royalty) ? 0 : _royalty
        );
        await royaltyTx.wait();

        // save unlockable content
        if (hasUnlockableContent && unlockableContent.length > 0) {
          await addUnlockableContent(
            nft,
            mintedTkId.toNumber(),
            unlockableContent,
            signature,
            addr,
            authToken
          );
        }

        showToast('success', 'New NFT item minted!');
        removeImage();
        setName('');
        setSymbol('');
        setDescription('');

        setTimeout(() => {
          history.push(`/explore/${nft}/${mintedTkId.toNumber()}`);
        }, 1000 + Math.random() * 2000);
      } catch (error) {
        showToast('error', formatError(error));
      }
    } catch (error) {
      showToast('error', error.message);
    }
    resetMintingStatus();
  };

  return (
    <div className={styles.container}>
      <Header border />
      <div className={styles.body}>
        <div className={styles.board}>
          <div {...getRootProps({ className: styles.uploadCont })}>
            <input {...getInputProps()} ref={imageRef} />
            {image ? (
              <>
                <img
                  className={styles.image}
                  src={URL.createObjectURL(image)}
                />
                <div className={styles.overlay}>
                  <CloseIcon className={styles.remove} onClick={removeImage} />
                </div>
              </>
            ) : (
              <>
                <div className={styles.uploadtitle}>
                  Drop files here or&nbsp;
                  <span
                    className={styles.browse}
                    onClick={() => imageRef.current?.click()}
                  >
                    browse
                  </span>
                </div>
                <div className={styles.uploadsubtitle}>
                  JPG, PNG, BMP, GIF Max 15mb.
                </div>
              </>
            )}
          </div>
        </div>
        <div className={styles.panel}>
          <div className={styles.panelInputs}>
            <div className={styles.panelLeft}>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>Collection</p>
                <Select
                  options={collections}
                  disabled={isMinting}
                  values={selected}
                  onChange={([col]) => {
                    setSelected([col]);
                    setNft(col.erc721Address);
                    setType(col.type);
                  }}
                  className={styles.select}
                  placeholder="Choose Collection"
                  itemRenderer={({ item, methods }) => (
                    <div
                      key={item.erc721Address}
                      className={styles.collection}
                      onClick={() => {
                        methods.clearAll();
                        methods.addItem(item);
                      }}
                    >
                      <img
                        src={`https://cloudflare-ipfs.com/ipfs/${item.logoImageHash}`}
                        className={styles.collectionLogo}
                      />
                      <div className={styles.collectionName}>
                        {item.collectionName}
                      </div>
                    </div>
                  )}
                  contentRenderer={({ props: { values } }) =>
                    values.length > 0 ? (
                      <div className={styles.collection}>
                        <img
                          src={`https://cloudflare-ipfs.com/ipfs/${values[0].logoImageHash}`}
                          className={styles.collectionLogo}
                        />
                        <div className={styles.collectionName}>
                          {values[0].collectionName}
                        </div>
                      </div>
                    ) : (
                      <div className={styles.collection} />
                    )
                  }
                />
              </div>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>Name</p>
                <input
                  className={styles.formInput}
                  maxLength={40}
                  placeholder="Name"
                  value={name}
                  onChange={e => setName(e.target.value)}
                  disabled={isMinting}
                />
                <div className={styles.lengthIndicator}>{name.length}/40</div>
              </div>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>Symbol</p>
                <input
                  className={styles.formInput}
                  maxLength={20}
                  placeholder="Symbol"
                  value={symbol}
                  onChange={e => setSymbol(e.target.value)}
                  disabled={isMinting}
                />
                <div className={styles.lengthIndicator}>{symbol.length}/20</div>
              </div>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>Description</p>
                <textarea
                  className={cx(styles.formInput, styles.longInput)}
                  maxLength={120}
                  placeholder="Description"
                  value={description}
                  onChange={e => setDescription(e.target.value)}
                  disabled={isMinting}
                />
                <div className={styles.lengthIndicator}>
                  {description.length}/120
                </div>
              </div>
            </div>
            <div className={styles.panelRight}>
              {type === 1155 && (
                <div className={styles.formGroup}>
                  <p className={styles.formLabel}>Supply</p>
                  <PriceInput
                    className={styles.formInput}
                    placeholder="Supply"
                    decimals={0}
                    value={'' + supply}
                    onChange={setSupply}
                    disabled={isMinting}
                  />
                </div>
              )}
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>
                  Royalty (%)&nbsp;
                  <BootstrapTooltip
                    title="If you set a royalty here, you will get X percent of sales price each time an NFT is sold on our platform."
                    placement="top"
                  >
                    <HelpOutlineIcon />
                  </BootstrapTooltip>
                </p>
                <PriceInput
                  className={styles.formInput}
                  placeholder="Royalty"
                  decimals={2}
                  value={'' + royalty}
                  onChange={val =>
                    val[val.length - 1] === '.'
                      ? setRoyalty(val)
                      : setRoyalty(Math.min(100, +val))
                  }
                  disabled={isMinting}
                />
              </div>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>
                  Link to IP Rights Document (Optional)&nbsp;
                  <BootstrapTooltip
                    title="Link to the document which proves your ownership of this image."
                    placement="top"
                  >
                    <HelpOutlineIcon />
                  </BootstrapTooltip>
                </p>
                <input
                  className={styles.formInput}
                  placeholder="Enter Link"
                  value={xtra}
                  onChange={e => setXtra(e.target.value)}
                  disabled={isMinting}
                />
              </div>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>
                  Unlockable Content&nbsp;
                  <PurpleSwitch
                    checked={hasUnlockableContent}
                    onChange={e => {
                      setHasUnlockableContent(e.target.checked);
                      setUnlockableContent('');
                    }}
                    name="unlockableContent"
                  />
                </p>
                {hasUnlockableContent && (
                  <textarea
                    className={cx(styles.formInput, styles.longInput)}
                    maxLength={500}
                    placeholder="Unlockable Content"
                    value={unlockableContent}
                    onChange={e => setUnlockableContent(e.target.value)}
                    disabled={isMinting}
                  />
                )}
              </div>
            </div>
          </div>

          {isMinting && (
            <div>
              <Stepper activeStep={currentMintingStep} alternativeLabel>
                {mintSteps.map(label => (
                  <Step key={label}>
                    <StepLabel>{label}</StepLabel>
                  </Step>
                ))}
              </Stepper>
            </div>
          )}
          <div
            className={cx(
              styles.button,
              (isMinting || !account || !validateMetadata()) && styles.disabled
            )}
            onClick={
              isMinting || !account || !validateMetadata() ? null : mintNFT
            }
          >
            {isMinting ? (
              <ClipLoader size="16" color="white"></ClipLoader>
            ) : (
              'Mint'
            )}
          </div>
          <div className={styles.fee}>
            {fee !== null ? (
              <>
                <InfoIcon />
                &nbsp;{fee} FTM are charged to create a new NFT.
              </>
            ) : (
              <Skeleton width={330} height={22} />
            )}
          </div>
          <div className={styles.mintStatusContainer}>
            {lastMintedTnxId !== '' && (
              <a
                className={styles.tnxAnchor}
                target="_blank"
                rel="noopener noreferrer"
                href={`${explorerUrl}/tx/${lastMintedTnxId}`}
              >
                You can track the last transaction here ...
              </a>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}
Example #9
Source File: index.js    From flame-coach-web with MIT License 4 votes vote down vote up
UIWizard = ({
    steps,
    getStepContent,
    result,
    isWizardValid,
    handleFinish,
    handleResetValidator,
}) => {

    const classes = useStyles();
    const [activeStep, setActiveStep] = React.useState(0);

    const handleNext = () => {
        setActiveStep((prevActiveStep) => prevActiveStep + 1);
    };

    const handleBack = () => {
        handleResetValidator();
        setActiveStep((prevActiveStep) => prevActiveStep - 1);
    };

    const handleReset = () => {
        setActiveStep(0);
    };

    return (
        <div className={classes.root}>
            <Stepper activeStep={activeStep} orientation="vertical">
                {steps.map((label, index) => (
                    <Step key={label}>
                        <StepLabel>{label}</StepLabel>
                        <StepContent>
                            {getStepContent(index)}
                            <div className={classes.actionsContainer}>
                                <div>
                                    <Button
                                        disabled={activeStep === 0}
                                        onClick={handleBack}
                                        className={classes.button}>
                                        Back
                                    </Button>
                                    {activeStep === steps.length - 1 && (
                                        <Button
                                            variant="contained"
                                            color="primary"
                                            onClick={() => {
                                                handleNext();
                                                handleFinish();
                                            }}
                                            className={classes.button}
                                            disabled={!isWizardValid}>
                                            Finish
                                        </Button>)}
                                    {activeStep !== steps.length - 1 && (
                                        <Button
                                            variant="contained"
                                            color="primary"
                                            onClick={handleNext}
                                            className={classes.button}
                                            disabled={!isWizardValid}>
                                            Next
                                        </Button>
                                    )}
                                </div>
                            </div>
                        </StepContent>
                    </Step>
                ))}
            </Stepper>
            {activeStep === steps.length && (
                <Paper square elevation={0} className={classes.resetContainer}>
                    {result}
                    <Button onClick={handleReset}
                        variant="contained"
                        color="primary"
                        className={classes.button}>
                        Reset
                    </Button>
                </Paper>
            )}
        </div>
    );

}
Example #10
Source File: JoinForm.jsx    From simplQ-frontend with GNU General Public License v3.0 4 votes vote down vote up
export function JoinQueueForm({ queueId, isAdminPage, buttonText }) {
  const [name, setName] = useState('');
  const [invalidName, setInvalidName] = useState(false);
  const [contactNumber, setContactNumber] = useState('');
  const [invalidContactNumber, setInvalidContactNumber] = useState(false);
  const [emailId, setEmailId] = useState('');
  const [invalidEmailId, setInvalidEmailId] = useState(false);
  const joinQueueActionStatus = useSelector((state) => state.actionStatus['joinQueue']);
  const prevActionStatus = useRef();
  const [activeStep, setActiveStep] = React.useState(0);
  const queueInfo = useSelector(selectQueueInfo);
  const [saveToLocalStorage, setSaveToLocalStorage] = useState(true);
  const getTokenByContactNumber = useCallback(useGetTokenByContactNumber(), []);

  const { notifyByEmail } = useSelector(selectQueueInfo);
  const collectEmail = !!notifyByEmail;

  const joinQueue = useJoinQueue();
  const dispatch = useDispatch();

  const joinQueueHandler = () => {
    dispatch(
      joinQueue({
        name,
        contactNumber,
        queueId,
        emailId: collectEmail ? emailId : undefined,
        goToStatusPage: !isAdminPage,
      })
    );
  };

  const onSubmitGetToken = () => {
    dispatch(
      getTokenByContactNumber({ queueId, contactNumber, redirectToTokenPageOnSuccess: true })
    );
  };

  const handleNext = async () => {
    if (invalidContactNumber) return;
    if (contactNumber === '') {
      setInvalidContactNumber(true);
      return;
    }

    // check if user is on admin page (pages/Admin/AddMember.jsx) where each step (contact + name) is necessary
    if (!isAdminPage) {
      setActiveStep((prevActiveStep) => prevActiveStep + 1);
      return;
    }
    onSubmitGetToken(contactNumber);
    if (queueInfo.selfJoinAllowed) setActiveStep((prevActiveStep) => prevActiveStep + 1);
  };

  const handleBack = () => {
    setActiveStep((prevActiveStep) => prevActiveStep - 1);
  };

  useEffect(() => {
    // Reset form only after successful action
    if (prevActionStatus.current === 'pending' && joinQueueActionStatus === 'fulfilled') {
      setContactNumber('');
      setName('');
      setEmailId('');
    }

    // Set previous action status for next render
    prevActionStatus.current = joinQueueActionStatus;
  }, [joinQueueActionStatus]);

  useEffect(() => {
    const localStorageName = localStorage.getItem('name');
    const localStorageContact = localStorage.getItem('contact');
    const localStorageEmail = localStorage.getItem('email');
    if (localStorageName) {
      setName(localStorageName);
    }
    if (localStorageContact) {
      setContactNumber(localStorageContact);
    }
    if (localStorageEmail) {
      setEmailId(localStorageEmail);
    }
  }, []);

  function handleNameChange(e) {
    if (name.match('^[A-Za-z0-9 ]*$')) {
      setName(e.target.value);
      setInvalidName(false);
    } else {
      setInvalidName(true);
    }
  }

  function handleEmailChange(e) {
    setEmailId(e.target.value);
  }

  const onSubmit = () => {
    if (invalidContactNumber || invalidName) return;
    if (name === '') {
      setInvalidName(true);
      return;
    }
    if (contactNumber === '') {
      setInvalidContactNumber(true);
      return;
    }

    if (collectEmail && emailId === '') {
      setInvalidEmailId(true);
      return;
    }

    if (saveToLocalStorage) {
      localStorage.setItem('contact', contactNumber);
      localStorage.setItem('name', name);
      localStorage.setItem('email', emailId);
    } else {
      localStorage.removeItem('contact');
      localStorage.removeItem('name');
      localStorage.removeItem('email');
    }

    joinQueueHandler();
    // reset to first step on queue page (pages/Admin/AddMember.jsx)
    if (isAdminPage) setActiveStep(0);
  };

  const checkJoinDisabled = () => {
    return (
      invalidContactNumber ||
      invalidName ||
      contactNumber === '' ||
      name === '' ||
      (collectEmail && (emailId === '' || invalidEmailId))
    );
  };

  const checkNextDisabled = () => {
    return invalidContactNumber || contactNumber === '';
  };

  const steps = [
    {
      id: 'phone',
      label: 'Enter phone number',
      item: (
        <div className={styles.formItem}>
          <PhoneInput
            isValid={!invalidContactNumber}
            setInvalidContact={setInvalidContactNumber}
            contact={contactNumber}
            onChange={(val) => setContactNumber(val)}
            onKeyDown={handleNext}
          />
        </div>
      ),
    },
    {
      id: 'rest-info',
      label: 'Enter name',
      item: (
        <>
          <div className={styles.formItem}>
            <InputField
              placeholder="Name"
              value={name}
              onKeyPress={(e) => handleEnterPress(e, onSubmit)}
              onChange={handleNameChange}
              error={invalidName}
              helperText={invalidName ? 'Enter a valid name' : ''}
              autoFocus
            />
          </div>
          {collectEmail ? (
            <div className={styles.formItem}>
              <InputField
                placeholder="Email"
                value={emailId}
                onKeyPress={(e) => handleEnterPress(e, onSubmit)}
                onChange={handleEmailChange}
                error={invalidEmailId}
                helperText={invalidEmailId ? 'Enter a valid name' : ''}
              />
            </div>
          ) : null}
        </>
      ),
    },
  ];
  const renderBox = (index) => {
    const backButton =
      index === 0 ? null : (
        <StandardButton outlined disabled={index === 0} onClick={handleBack}>
          Back
        </StandardButton>
      );
    const isSubmitStep = index === steps.length - 1 && (queueInfo.selfJoinAllowed || isAdminPage);
    const boxContent = isSubmitStep ? (
      <>
        <Checkbox
          name="saveToLocalStorage"
          label="Save for later use"
          checked={saveToLocalStorage}
          onChange={() => {
            setSaveToLocalStorage(!saveToLocalStorage);
          }}
        />
        <div className={styles.formBoxVerticalButtons}>
          <LoadingStatus dependsOn="joinQueue">
            <StandardButton disabled={checkJoinDisabled()} onClick={onSubmit}>
              {buttonText}
            </StandardButton>
          </LoadingStatus>
          <span className={styles.formButtonsSpace} />
          {backButton}
        </div>
      </>
    ) : (
      <>
        <StandardButton disabled={checkNextDisabled()} variant="contained" onClick={handleNext}>
          Next
        </StandardButton>
        <span className={styles.formButtonsSpace} />
        {backButton}
      </>
    );
    const boxClasses = isSubmitStep
      ? `${styles.formBox} ${styles.formBoxVertical}`
      : `${styles.formBox}`;
    return <Box className={boxClasses}>{boxContent}</Box>;
  };
  return (
    <Box>
      <Stepper activeStep={activeStep} orientation="vertical">
        {steps.map((step, index) => (
          <Step key={step.id}>
            <StepLabel
              optional={index === 2 ? <Typography variant="caption">Last step</Typography> : null}
            >
              {step.label}
            </StepLabel>
            <StepContent className={styles.stepTopSpace}>
              {step.item}
              {renderBox(index)}
            </StepContent>
          </Step>
        ))}
      </Stepper>
    </Box>
  );
}
Example #11
Source File: App.js    From cloud-dapr-demo with MIT License 4 votes vote down vote up
export default function App() {
  const classes = useStyles();
  const [activeStep, setActiveStep] = useState(0);
  const [food, setFood] = useState('');
  const [drink, setDrink] = useState('');
  const [loading, setLoading] = useState(false);
  const [orderId, setOrderId] = useState(null);
  const [status, setStatus] = useState(null);

  const steps = getSteps();

  function submitOrder() {
    setLoading(true);
    axios.post(`${baseUrl}/order`, {
      food, drink
    }).then((res) => {
      setOrderId(res.data.id);
    }).finally(() => setLoading(false));
  }

  useEffect(() => {
    if (orderId) {
      pollStatus(orderId);
    }
  }, [orderId]);

  useEffect(() => {
    if (status) {
      let activeIndex = 0;
      switch (status) {
        case 'OrderReceived':
          activeIndex = 0;
          break;
        case 'Processing':
          activeIndex = 1;
          break;
        case 'ReadyToPickup':
          activeIndex = 2;
          break;
        case 'DeliveryOnWay':
          activeIndex = 3;
          break;
        case 'Delivered':
          activeIndex = 4;
          break;
      }
      setActiveStep(activeIndex);
    }
  }, [status]);

  function pollStatus(id) {
    setTimeout(async () => {
      const status = await fetchStatus(id);
      setStatus(status);
      if (status !== 'Delivered') {
        pollStatus(id);
      }
    }, 500);
  }

  async function fetchStatus(id) {
    return axios.get(`${baseUrl}/order/${id}`)
      .then(res => res.data)
      .then(data => data.status)
      .catch((e) => console.error(e));
  }

  return (
    <div className={classes.root}>
      <AppBar position="static">
        <Toolbar>
          <IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" className={classes.title}>
            Demo: Event Driven Apps with Dapr in Kubernetes
          </Typography>
        </Toolbar>
      </AppBar>
      <Container maxWidth="sm">
        <Grid container style={{ marginTop: 40 }}>
          <Grid item xs={6} spacing={3}>
            <FormControl component="fieldset" className={classes.formControl}>
              <FormLabel component="legend">Food</FormLabel>
              <RadioGroup aria-label="food" name="food" value={food}
                onChange={(e) => setFood(e.target.value)}>
                <FormControlLabel value="pizza" control={<Radio />} label="Pizza ?" />
                <FormControlLabel value="burger" control={<Radio />} label="Burger ?" />
                <FormControlLabel value="sandwich" control={<Radio />} label="Sandwich ?" />
                <FormControlLabel value="hotdog" control={<Radio />} label="HotDog ?" />
                <FormControlLabel value="fries" control={<Radio />} label="Fries ?" />
              </RadioGroup>
            </FormControl>
          </Grid>
          <Grid item xs={6}>
            <FormControl component="fieldset" className={classes.formControl}>
              <FormLabel component="legend">Drink</FormLabel>
              <RadioGroup aria-label="drink" name="drink" value={drink}
                onChange={(e) => setDrink(e.target.value)}>
                <FormControlLabel value="drink1" control={<Radio />} label="Diet Coke" />
                <FormControlLabel value="drink2" control={<Radio />} label="Coke" />
                <FormControlLabel value="drink3" control={<Radio />} label="Coffee" />
                <FormControlLabel value="drink4" control={<Radio />} label="Iced Tea" />
                <FormControlLabel value="drink5" control={<Radio />} label="Beer" />
                <FormControlLabel value="drink6" control={<Radio />} label="Orange Juice" />
              </RadioGroup>
              <FormHelperText></FormHelperText>
            </FormControl>
          </Grid>
          <Button type="submit" variant="outlined" disabled={!(food && drink)}
            color="primary" className={classes.button}
            onClick={submitOrder}>
            {loading && <CircularProgress
              className={classes.spinner}
              size={20}
            />}
            Submit Order
          </Button>
        </Grid>
        {orderId && <Grid container style={{ marginTop: 50 }}>
          <Grid item>
            <Typography variant="h6" className={classes.title}>
              Order ID: {orderId}
            </Typography>
          </Grid>
          <Grid item>
            <Stepper activeStep={activeStep} alternativeLabel>
              {steps.map((label) => (
                <Step key={label}>
                  <StepLabel StepIconComponent={QontoStepIcon}>{label}</StepLabel>
                </Step>
              ))}
            </Stepper>
          </Grid>
        </Grid>
        }
      </Container>
    </div >
  );
}
Example #12
Source File: UploadStepper.js    From youtube-clone with MIT License 4 votes vote down vote up
export default function HorizontalLinearStepper() {
  const classes = useStyles();
  const formRef = useRef();
  const [activeStep, setActiveStep] = React.useState(0);
  const dispatch = useDispatch();

  const isLoading = useSelector(({ upload }) => upload.isLoading);
  const thumbnails = useSelector(({ upload }) => upload.thumbnails);
  const steps = getSteps();

  const handleNext = () => {
    formRef.current.submitForm();
    if (!Object.keys(formRef.current.errors).length) {
      setActiveStep((prevActiveStep) => prevActiveStep + 1);
    }
  };

  const handleFinish = () => {
    formRef.current.submitForm();
  };

  const submitInfo = ({ visibility }) => {
    dispatch(setVisibilitySubmit(visibility));
  };

  const setDetailsRx = (details) => {
    dispatch(setDetails(details));
  };

  const handleBack = () => {
    setActiveStep((prevActiveStep) => prevActiveStep - 1);
  };

  return (
    <div>
      <Stepper activeStep={activeStep}>
        {steps.map((label) => {
          const stepProps = {};
          const labelProps = {};

          return (
            <Step key={label} {...stepProps}>
              <StepLabel {...labelProps}>{label}</StepLabel>
            </Step>
          );
        })}
      </Stepper>
      <div>
        {activeStep === steps.length - 1 ? (
          <div>
            <Typography className={classes.instructions}>
              {
                <UploadForm
                  type="visibility"
                  formRef={formRef}
                  onSubmit={submitInfo}
                />
              }
            </Typography>
            <div>
              <Button
                disabled={activeStep === 0}
                onClick={handleBack}
                className={classes.button}
              >
                Back
              </Button>

              <Button
                variant="contained"
                color="primary"
                onClick={handleFinish}
                className={classes.button}
              >
                Finish
              </Button>
            </div>
          </div>
        ) : (
          <div>
            <div className={classes.content}>
              <UploadForm
                type="details"
                formRef={formRef}
                onSubmit={setDetailsRx}
              />
              <Typography variant="body1" className={classes.instructions}>
                Pick an thumbnail:
              </Typography>
              <ImagePicker list={thumbnails || new Array(3).fill({})} />
            </div>
            <div>
              <Button
                disabled={activeStep === 0}
                onClick={handleBack}
                className={classes.button}
              >
                Back
              </Button>

              <Button
                variant="contained"
                color="primary"
                onClick={handleNext}
                disabled={isLoading}
                className={classes.button}
              >
                Next
              </Button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
Example #13
Source File: ClaimStepper.js    From lrc-staking-dapp with MIT License 4 votes vote down vote up
ClaimStepper = React.memo(({
  classes, messages, pendingReward, onClaim, onDone, claim,
}) => {
  const [step, setStep] = useState(0);
  const [isClaiming, setIsClaiming] = useState(false);
  const [isDone, setIsDone] = useState(false);

  useEffect(() => {
    checkAsyncClaimIsDone(step, isClaiming, claim, setIsClaiming, setIsDone, setStep);
  }, [step, isClaiming, claim, setIsClaiming, setIsDone, setStep]);

  useEffect(() => {
    autoRedirect(isDone, onDone);
  }, [isDone, onDone]);

  return (
    <div className={classes.root}>
      <Stepper activeStep={step} orientation="vertical">
        <Step>
          <StepLabel>{messages['Are you sure?']}</StepLabel>
          <StepContent>
            <Typography>{messages['All your pending reward will be transferred to your stake and your stake age will be reset to today (this does not affect the age to withdraw).']}</Typography>
            <div className={classes.actionsContainer}>
              <div>
                <Button
                  disabled
                  className={classes.button}
                >
                  {messages.Back}
                </Button>
                <Button
                  disabled={!pendingReward}
                  variant="contained"
                  color="primary"
                  onClick={() => setStep(STEP.CLAIM)}
                  className={classes.button}
                >
                  {messages['I understand']}
                </Button>
              </div>
            </div>
          </StepContent>
        </Step>
        <Step>
          <StepLabel>{messages.Claim}</StepLabel>
          <StepContent>
            <Typography>
              <span className={`font-weight-bold ${classes.spanAmount}`}>
                {numeral(pendingReward).format('(0.00a)')}
                {' '}
                LRC
              </span>
              {messages['$LRC_AMOUNT will be transferred from your pending reward to your current stake.'].split('$LRC_AMOUNT')[1]}
            </Typography>
            <div className={classes.actionsContainer}>
              <div className={classes.divBackAndConfirm}>
                <Button
                  onClick={() => setStep(STEP.DISCLAIMER)}
                  className={classes.button}
                >
                  {messages.Back}
                </Button>
                <div className={classes.wrapper}>
                  <Button
                    disabled={claim.isLoading}
                    variant="contained"
                    color="primary"
                    onClick={onClaim}
                    className={classes.button}
                  >
                    { claim.isLoading && messages.Claiming }
                    { !claim.isLoading && messages.Claim }
                  </Button>
                  { claim.isLoading
                  && (<CircularProgress size={24} className={classes.buttonProgress} />)}
                </div>
              </div>
            </div>
          </StepContent>
        </Step>
        <Step>
          <StepLabel>{messages.Done}</StepLabel>
          <StepContent>
            <Typography color="primary">
              {messages['Your pending rewards are now staked.']}
            </Typography>
          </StepContent>
        </Step>
      </Stepper>
    </div>
  );
})
Example #14
Source File: DepositStepper.js    From lrc-staking-dapp with MIT License 4 votes vote down vote up
DepositStepper = React.memo(({
  classes, messages, maxAmount, onApprove, onStake, allowance, stake, approve, onDone,
}) => {
  const [step, setStep] = useState(0);
  const [amount, setAmount] = useState('0');
  const [isStaking, setIsStaking] = useState(false);
  const [isDone, setIsDone] = useState(false);
  const { width, height } = useWindowSize();

  useEffect(() => {
    checkEnoughAllowanceRedirectToStakeStep(amount, allowance, step, setStep);
  }, [amount, allowance, step, setStep]);

  useEffect(() => {
    checkAsyncStakeIsDone(step, isStaking, stake, setIsStaking, setIsDone, setStep);
  }, [step, isStaking, stake, setIsStaking, setIsDone, setStep]);

  useEffect(() => {
    timeoutConfetti(isDone, onDone);
  }, [isDone, onDone]);

  return (
    <div className={classes.root}>
      <Stepper activeStep={step} orientation="vertical">
        <Step>
          <StepLabel>{messages['Are you sure?']}</StepLabel>
          <StepContent>
            <Typography>{messages['Your tokens will be locked until your stake age is older than 90 day. If you add new tokens into your stake, your age will be weighted by the amount of tokens.']}</Typography>
            <div className={classes.actionsContainer}>
              <div>
                <Button
                  disabled
                  className={classes.button}
                >
                  {messages.Back}
                </Button>
                <Button
                  variant="contained"
                  color="primary"
                  onClick={() => setStep(STEP.AMOUNT)}
                  className={classes.button}
                >
                  {messages['I understand']}
                </Button>
              </div>
            </div>
          </StepContent>
        </Step>
        <Step>
          <StepLabel>{messages['Select amount']}</StepLabel>
          <StepContent>
            <Typography>{messages['Please fill in the amount of LRC you want to stake.']}</Typography>
            <TextField
              value={amount}
              variant="outlined"
              label="Amount"
              fullWidth
              type="number"
              placeholder={safeAmountToPrint(maxAmount)}
              className={classes.inputLRC}
              onChange={(e) => setAmount(safeAmount(e.target.value || 0)
                .isLessThanOrEqualTo(maxAmount)
                ? e.target.value : safeAmountToPrint(maxAmount))}
            />
            <Slider
              value={safeAmount(maxAmount).isZero()
                ? 0 : safeAmount(amount).div(maxAmount).multipliedBy(100).toFixed(0) * 1}
              defaultValue={0}
              valueLabelFormat={(value) => `${value}%`}
              getAriaValueText={() => '%'}
              aria-labelledby="discrete-slider-restrict"
              step={null}
              valueLabelDisplay="auto"
              marks={[{ label: '0%', value: 0 }, { label: '25%', value: 25 }, { label: '50%', value: 50 }, { label: '75%', value: 75 }, { label: '100%', value: 100 }]}
              className={classes.sliderAmount}
              onChange={(_, value) => setAmount(safeAmountToPrint(safeAmount(maxAmount)
                .multipliedBy(value / 100)))}
            />
            <div className={classes.actionsContainer}>
              <div>
                <Button
                  onClick={() => setStep(STEP.DISCLAIMER)}
                  className={classes.button}
                >
                  {messages.Back}
                </Button>
                <Button
                  disabled={safeAmount(amount).isLessThanOrEqualTo(0)}
                  variant="contained"
                  color="primary"
                  onClick={() => setStep(STEP.APPROVAL)}
                  className={classes.button}
                >
                  {messages.Next}
                </Button>
              </div>
            </div>
          </StepContent>
        </Step>
        <Step>
          <StepLabel>{messages.Approve}</StepLabel>
          <StepContent>
            <Typography>
              {messages['You need to allow the staking pool to take $LRC_AMOUNT from your wallet.'].split('$LRC_AMOUNT')[0]}
              <span className={`font-weight-bold ${classes.spanAmount}`}>
                {numeral(amount).format('(0.00a)')}
                {' '}
                LRC
              </span>
              {messages['You need to allow the staking pool to take $LRC_AMOUNT from your wallet.'].split('$LRC_AMOUNT')[1]}
            </Typography>
            <div className={classes.actionsContainer}>
              <div className={classes.divBackAndConfirm}>
                <Button
                  onClick={() => setStep(STEP.AMOUNT)}
                  className={classes.button}
                >
                  {messages.Back}
                </Button>
                <div className={classes.wrapper}>
                  <Button
                    disabled={approve.isLoading}
                    variant="contained"
                    color="primary"
                    onClick={() => onApprove(safeAmountFixed(amount))}
                    className={classes.button}
                  >
                    { approve.isLoading && messages.Approving }
                    { !approve.isLoading && messages.Approve }
                  </Button>
                  { approve.isLoading
                  && (<CircularProgress size={24} className={classes.buttonProgress} />)}
                </div>
              </div>
            </div>
          </StepContent>
        </Step>
        <Step>
          <StepLabel>{messages.Stake}</StepLabel>
          <StepContent>
            <Typography>{messages['You can now deposit your LRC to the staking pool.']}</Typography>
            <div className={classes.actionsContainer}>
              <div className={classes.divBackAndConfirm}>
                <Button
                  onClick={() => setStep(STEP.AMOUNT)}
                  className={classes.button}
                >
                  {messages.Back}
                </Button>
                <div className={classes.wrapper}>
                  <Button
                    disabled={stake.isLoading}
                    variant="contained"
                    color="primary"
                    onClick={() => onStake(safeAmountFixed(amount))}
                    className={classes.button}
                  >
                    { stake.isLoading && messages.Staking }
                    { !stake.isLoading && messages.Stake }
                  </Button>
                  { stake.isLoading
                  && (<CircularProgress size={24} className={classes.buttonProgress} />)}
                </div>
              </div>
            </div>
          </StepContent>
        </Step>
        <Step>
          <StepLabel>{messages.Done}</StepLabel>
          <StepContent>
            <Typography color="primary" className="animated infinite heartBeat delay-1s">
              {messages['Your Loopring token are now staked and you will start collecting fees on all trades !']}
            </Typography>
            <div className={classes.divConfetti}>
              <Confetti
                width={width}
                height={height}
              />
            </div>
          </StepContent>
        </Step>
      </Stepper>
    </div>
  );
})
Example #15
Source File: WithdrawStepper.js    From lrc-staking-dapp with MIT License 4 votes vote down vote up
WithdrawStepper = React.memo(({
  classes, messages, maxAmount, onWithdraw, withdraw, onDone,
}) => {
  const [step, setStep] = useState(0);
  const [amount, setAmount] = useState('0');
  const [isWithdrawing, setIsWithdrawing] = useState(false);
  const [isDone, setIsDone] = useState(false);

  useEffect(() => {
    checkAsyncWithdrawIsDone(step, isWithdrawing, withdraw, setIsWithdrawing, setIsDone, setStep);
  }, [step, isWithdrawing, withdraw, setIsWithdrawing, setIsDone, setStep]);

  useEffect(() => {
    timeoutRedirect(isDone, onDone);
  }, [isDone, onDone]);

  return (
    <div className={classes.root}>
      <Stepper activeStep={step} orientation="vertical">
        <Step>
          <StepLabel>{messages['Are you sure?']}</StepLabel>
          <StepContent>
            <Typography>{messages['When you make a withdrawal, the pending rewards will automatically be added to your stake which will result in resetting the age of your stake to today (this does not impact the age to make a withdrawal).']}</Typography>
            <div className={classes.actionsContainer}>
              <div>
                <Button
                  disabled
                  className={classes.button}
                >
                  {messages.Back}
                </Button>
                <Button
                  variant="contained"
                  color="primary"
                  onClick={() => setStep(STEP.AMOUNT)}
                  className={classes.button}
                >
                  {messages['I understand']}
                </Button>
              </div>
            </div>
          </StepContent>
        </Step>
        <Step>
          <StepLabel>{messages['Select amount']}</StepLabel>
          <StepContent>
            <Typography>{messages['Please fill in the amount of LRC you want to withdraw.']}</Typography>
            <TextField
              value={amount}
              variant="outlined"
              label="Amount"
              fullWidth
              type="number"
              placeholder={safeAmountToPrint(maxAmount)}
              className={classes.inputLRC}
              onChange={(e) => setAmount(safeAmount(e.target.value || 0)
                .isLessThanOrEqualTo(maxAmount)
                ? e.target.value : safeAmountToPrint(maxAmount))}
            />
            <Slider
              value={safeAmount(maxAmount).isZero()
                ? 0 : safeAmount(amount).div(maxAmount).multipliedBy(100).toFixed(0) * 1}
              defaultValue={0}
              valueLabelFormat={(value) => `${value}%`}
              getAriaValueText={() => '%'}
              aria-labelledby="discrete-slider-restrict"
              step={null}
              valueLabelDisplay="auto"
              marks={[{ label: '0%', value: 0 }, { label: '25%', value: 25 }, { label: '50%', value: 50 }, { label: '75%', value: 75 }, { label: '100%', value: 100 }]}
              className={classes.sliderAmount}
              onChange={(_, value) => setAmount(safeAmountToPrint(safeAmount(maxAmount)
                .multipliedBy(value / 100)))}
            />
            <div className={classes.actionsContainer}>
              <div>
                <Button
                  onClick={() => setStep(STEP.DISCLAIMER)}
                  className={classes.button}
                >
                  {messages.Back}
                </Button>
                <Button
                  disabled={safeAmount(amount).isLessThanOrEqualTo(0)}
                  variant="contained"
                  color="primary"
                  onClick={() => setStep(STEP.WITHDRAW)}
                  className={classes.button}
                >
                  {messages.Next}
                </Button>
              </div>
            </div>
          </StepContent>
        </Step>
        <Step>
          <StepLabel>{messages.Withdraw}</StepLabel>
          <StepContent>
            <Typography>
              <span className={`font-weight-bold ${classes.spanAmount}`}>
                {numeral(amount).format('(0.00a)')}
                {' '}
                LRC
              </span>
              {messages['$LRC_AMOUNT will be transferred from your stake to your wallet.'].split('$LRC_AMOUNT')[1]}
            </Typography>
            <div className={classes.actionsContainer}>
              <div className={classes.divBackAndConfirm}>
                <Button
                  onClick={() => setStep(STEP.AMOUNT)}
                  className={classes.button}
                >
                  {messages.Back}
                </Button>
                <div className={classes.wrapper}>
                  <Button
                    disabled={withdraw.isLoading}
                    variant="contained"
                    color="primary"
                    onClick={() => onWithdraw(safeAmountFixed(amount))}
                    className={classes.button}
                  >
                    { withdraw.isLoading && messages.Withdrawing }
                    { !withdraw.isLoading && messages.Withdraw }
                  </Button>
                  { withdraw.isLoading
                  && (<CircularProgress size={24} className={classes.buttonProgress} />)}
                </div>
              </div>
            </div>
          </StepContent>
        </Step>
        <Step>
          <StepLabel>{messages.Done}</StepLabel>
          <StepContent>
            <Typography color="primary">
              {messages['Your withdrawal has been processed, we hope to see you soon :(']}
            </Typography>
          </StepContent>
        </Step>
      </Stepper>
    </div>
  );
})