All files / app/features/auth/signup ChangeSignupEmail.tsx

100% Statements 29/29
85.71% Branches 12/14
100% Functions 5/5
100% Lines 28/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 1082x 2x 2x 2x 2x 2x   2x 2x 2x 2x 2x 2x   62x                           5x 63x 63x   63x               63x 63x   63x       63x 3x 3x               63x   3x 3x       1x     1x                                                                                
import { styled, Typography } from "@mui/material";
import { useMutation } from "@tanstack/react-query";
import Alert from "components/Alert";
import Button from "components/Button";
import TextField from "components/TextField";
import { useAuthContext } from "features/auth/AuthProvider";
import { RpcError } from "grpc-web";
import { useTranslation } from "i18n";
import { AUTH, GLOBAL } from "i18n/namespaces";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { service } from "service";
import { emailValidationPattern, lowercaseAndTrimField } from "utils/validation";
 
const StyledForm = styled("form")(({ theme }) => ({
  marginTop: theme.spacing(2),
  marginBottom: theme.spacing(2),
  display: "flex",
  flexDirection: "column",
  gap: theme.spacing(1),
  alignItems: "flex-start",
  width: "100%",
}));
 
interface ChangeSignupEmailFormData {
  newSignupEmail: string;
}
 
export default function ChangeSignupEmail() {
  const { t } = useTranslation([AUTH, GLOBAL]);
  const { authActions, authState } = useAuthContext();
 
  const [changedEmail, setChangedEmail] = useState<boolean>(false);
 
  const {
    formState: { errors },
    handleSubmit,
    register,
    reset: resetForm,
    watch,
  } = useForm<ChangeSignupEmailFormData>({ mode: "onBlur" });
  const newSignupEmail = watch("newSignupEmail", "");
  const isSubmitDisabled =
    !newSignupEmail.trim() ||
    !!errors.newSignupEmail ||
    lowercaseAndTrimField(newSignupEmail) === lowercaseAndTrimField(authState.flowState!.email);
 
  const onSubmit = handleSubmit(({ newSignupEmail }) => {
    const sanitizedEmail = lowercaseAndTrimField(newSignupEmail || "");
    changeSignupEmail({ newSignupEmail: sanitizedEmail || "" });
  });
 
  const {
    error: changeSignupEmailError,
    isPending: isChangeSignupEmailLoading,
    isSuccess: isChangeSignupEmailSuccess,
    mutate: changeSignupEmail,
  } = useMutation<void, RpcError, ChangeSignupEmailFormData>({
    mutationFn: async ({ newSignupEmail }) => {
      resetForm();
      const state = await service.auth.signupFlowChangeEmail(
        authState.flowState!.flowToken,
        lowercaseAndTrimField(newSignupEmail),
      );
      authActions.updateSignupState(state);
    },
    onSuccess: () => {
      setChangedEmail(true);
    },
  });
 
  return (
    <div>
      <Typography variant="body1" gutterBottom>
        {!changedEmail ? t("auth:sign_up_change_email") : ""}
      </Typography>
      <>
        {changeSignupEmailError && <Alert severity="error">{changeSignupEmailError.message}</Alert>}
        {isChangeSignupEmailSuccess && (
          <Alert severity="success">{t("auth:change_signup_email_form.success_message")}</Alert>
        )}
        {!changedEmail && (
          <StyledForm onSubmit={onSubmit}>
            <TextField
              id="newSignupEmail"
              {...register("newSignupEmail", {
                pattern: {
                  message: t("auth:basic_form.email.empty_error"),
                  value: emailValidationPattern,
                },
                required: true,
              })}
              placeholder={"you@couchers.org"}
              name="newSignupEmail"
              fullWidth
              error={!!errors.newSignupEmail}
              helperText={errors.newSignupEmail?.message ?? " "}
            />
            <Button fullWidth={true} loading={isChangeSignupEmailLoading} type="submit" disabled={isSubmitDisabled}>
              {t("auth:change_signup_email_form.signup_change_email")}
            </Button>
          </StyledForm>
        )}
      </>
    </div>
  );
}