ctrl-alt-del-world/midway

View on GitHub
web/src/components/auth/activate.tsx

Summary

Maintainability
C
7 hrs
Test Coverage
import React, { useCallback, useState } from "react"
import Helmet from "react-helmet"
import { useDeferredLoads } from "react-loads"
import fetch from "unfetch"
import { Link } from "gatsby"
// @ts-ignore
import { encode } from "shopify-gid"
import { navigate } from "@reach/router"
import Timeout from "await-timeout"
import cx from "classnames"

import { PasswordSchema } from 'src/utils/schema'

const Activate = (props: { id: string; token: string }) => {
  const [passwordField1, setPasswordField1] = useState("")
  const [passwordField2, setPasswordField2] = useState("")
  const [attempts, setAttempts] = useState(0)

  const verifyAccount = useCallback(
    async e => {
      setAttempts(attempts + 1)

      if (passwordField1 !== passwordField2) {
        await Timeout.set(400)
        throw new Error("Passwords do not match.")
      }

      if (!PasswordSchema.validate(passwordField1)) {
        throw new Error(
          "Your password should be between 8 and 100 characters, and have at least one lowercase and one uppercase letter."
        )
      }

      const body = {
        id: encode("Customer", props.id),
        input: {
          activationToken: props.token,
          password: passwordField1,
        },
      }

      const res = await fetch(`/.netlify/functions/activate`, {
        method: "POST",
        body: JSON.stringify(body),
      })

      try {
        const customer = await res.json()

        if (customer.error) {
          const err = new Error("Server Error: Account verification fetch response error.")

          throw err
        } else if (!res.ok) {
          const err = new Error("Server Error: Account verification fetch not OK.")

     
          throw err
        }

        await Timeout.set(400)
        await navigate("/account/login")
      } catch (err) {
        throw err
      }
      // hacky way to get it to run anew every time
      // and maybe in the future redirect them if they
      // need help.
    },
    [passwordField1, passwordField2, attempts]
  )

  const { error, load, isReloading, isPending } = useDeferredLoads(
    "verifyAccount",
    verifyAccount,
    {}
  )

  return (
    <div>
      <Helmet title="activate account" />
      <div className="nav-spacer" />
      <div className="accounts__wrapper f col aic jcc y px1">
        <div className="x">
          <div className="container--xl ma ac">
            <h5 className="pb0 caps sans ls">Activate Account</h5>
            <h2 className="my0">Almost there.</h2>
          </div>
          <div className="x container--s al mxa">
            {error && !isReloading && (
              <div className="studio mt1 error f col">
                <span>{error.message}</span>
              </div>
            )}

            {(isPending || isReloading) && (
              <div className="f jcc p1">
                <span>Loading</span>
              </div>
            )}

            <div
              className={cx(
                "x container--s col mya",
                isPending || isReloading ? "invisible" : "visible"
              )}
            >

              <div className="pb1  x pya">
                <div className="caps sans ls my1">Password</div>
                <input
                  className="py1 px1  x s16 s16"
                  type="password"
                  value={passwordField1}
                  onChange={e => setPasswordField1(e.target.value)}
                  placeholder="Password"
                />
              </div>
              
              <div className="pb1 mb1 x pya">
                <div className="caps sans ls mt1 py05">Confirm Password</div>
                <input
                  className="py1 px1 x mb1 s16"
                  type="password"
                  value={passwordField2}
                  onChange={e => setPasswordField2(e.target.value)}
                  placeholder="Confirm Password"
                />
              </div>
            </div>
            <div className="ac x">
              
              <button
                type="submit"
                className="button button--wide cg ac akz ls-s mt1 inline-block caps s14"
                onClick={load}
              >
                Activate
              </button>

              <div className="container--m mya pt1 aic">
                <p className=" sans s14  pt1 ac">
                  Already have an account?{" "}
                  <Link className="underline active" to="/account/login">
                    Login
                  </Link>
                </p>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

export default Activate