sparkletown/sparkle

View on GitHub
src/components/molecules/SecretPasswordForm/SecretPasswordForm.tsx

Summary

Maintainability
A
2 hrs
Test Coverage
import React, { ChangeEventHandler, useCallback, useState } from "react";
import { useHistory } from "react-router-dom";

import { ATTENDEE_STEPPING_PARAM_URL, DEFAULT_ENTER_STEP } from "settings";

import { checkAccess } from "api/auth";

import { setLocalStorageToken } from "utils/localStorage";
import { isDefined, isTruthy } from "utils/types";
import { generateUrl } from "utils/url";

import { useSpaceParams } from "hooks/spaces/useSpaceParams";
import { useWorldAndSpaceBySlug } from "hooks/spaces/useWorldAndSpaceBySlug";

import "./SecretPasswordForm.scss";

const SecretPasswordForm = ({ buttonText = "Join the party" }) => {
  const history = useHistory();
  const { worldSlug, spaceSlug } = useSpaceParams();
  const { spaceId } = useWorldAndSpaceBySlug(worldSlug, spaceSlug);

  const [error, setError] = useState(false);
  const [password, setPassword] = useState<string>();
  const [message, setMessage] = useState<string>();

  const passwordChanged: ChangeEventHandler<HTMLInputElement> = (e) => {
    setPassword(e.target.value);

    if (message !== "") {
      setMessage("");
    }

    if (error) {
      setError(false);
    }
  };

  // @debt replace this with useAsync / useAsyncFn
  const passwordSubmitted = useCallback(
    async (e) => {
      e.preventDefault();

      if (!isDefined(spaceId)) {
        setMessage("Missing venueId");
        setError(true);
        return;
      }

      if (!isDefined(spaceSlug)) {
        setMessage("Missing spaceSlug");
        setError(true);
        return;
      }

      setMessage("Checking password...");

      await checkAccess({
        venueId: spaceId,
        password,
      })
        .then((result) => {
          if (isTruthy(result?.data?.token)) {
            setLocalStorageToken(spaceId, result.data.token);
            history.push(
              generateUrl({
                route: ATTENDEE_STEPPING_PARAM_URL,
                required: ["worldSlug", "spaceSlug", "step"],
                params: { worldSlug, spaceSlug, step: DEFAULT_ENTER_STEP },
              })
            );
          } else {
            setMessage(`Wrong password!`);
            setError(true);
          }
        })
        .catch((err) => {
          setMessage(`Password error: ${err.toString()}`);
          setError(true);
        });
    },
    [history, password, worldSlug, spaceSlug, spaceId]
  );

  return (
    <>
      <form className="secret-password-form" onSubmit={passwordSubmitted}>
        <p className="small-text">
          Got an invite? Join in with the secret password
        </p>
        <input
          className="secret-password-input"
          required
          placeholder="password"
          autoFocus
          onChange={passwordChanged}
          id="password"
        />
        <input
          className="btn btn-primary btn-block btn-centered"
          type="submit"
          value={buttonText}
        />
        <div className="form-group">
          {message && <small>{message}</small>}
          {error && <small className="error-message">An error occured</small>}
        </div>
      </form>
    </>
  );
};

export default SecretPasswordForm;