Commit 53ba7bb8 authored by AlexandrValgamov's avatar AlexandrValgamov
Browse files

Catalog | feat: add login page

parent e36f1674
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
'use client';

import { Preloader } from '@/vendor';

const Loading = () => {
  return <Preloader colorItem="" />;
};

export default Loading;

src/app/login/page.tsx

0 → 100644
+14 −0
Original line number Diff line number Diff line
import { Suspense } from 'react';

import { LoginPage } from '@/page';

import Loading from './loading';

const Login = () => {
  return (
    <Suspense fallback={<Loading />}>
      <LoginPage />
    </Suspense>
  );
};
export default Login;
+1 −0
Original line number Diff line number Diff line
export * from './login';
+132 −0
Original line number Diff line number Diff line
'use client';

import { Controller, SubmitHandler, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import classNames from 'classnames';
import { PatternFormat } from 'react-number-format';
import { useState } from 'react';
import { AnimatePresence } from 'framer-motion';
import { isAxiosError } from 'axios';
import { useRouter } from 'next/navigation';

import { useLoginMutation } from '@/api-hooks';
import {
  ActionAuthButton,
  BackGroup,
  LayoutModal,
  Overlay,
  Portal,
} from '@/shared';
import { ILoginResponse } from '@/interfaces';
import { useAppDispatch } from '@/hooks';
import { setToken, setUser } from '@/store';

import styled from './styles/input.module.css';
import * as Styled from './styled';
import { LoginSchema, TLoginSchema } from './schema';
import { AuthErrorModal } from './ui';

export const Login = () => {
  const router = useRouter();
  const dispatch = useAppDispatch();
  const [localError, setLocalError] = useState<Error | null>(null);

  const handleBackClick = () => {
    router.push('/');
  };

  const { control, handleSubmit, reset } = useForm<TLoginSchema>({
    resolver: zodResolver(LoginSchema),
    defaultValues: {
      phone: '',
    },
  });

  const handleSuccess = (data: ILoginResponse) => {
    if (data?.success) {
      dispatch(setUser({ data: data.user }));
      dispatch(setToken({ data: data.accessToken }));
      router.replace('/profile');
    }
  };

  const handleError = (error: Error) => {
    if (isAxiosError(error) && error.code === '404') router.replace('/404');
    if (isAxiosError(error) && error.code === '500')
      router.replace('/server-error');
    setLocalError(error);
  };

  const { mutate, isPending } = useLoginMutation(handleError, handleSuccess);

  const onSubmit: SubmitHandler<TLoginSchema> = (dataForm) => {
    mutate(dataForm);
  };

  const handleCloseModal = () => {
    reset();
    setLocalError(null);
  };

  return (
    <Styled.Login>
      <BackGroup handleBackClick={handleBackClick} title="Вход" />

      <Styled.FormWrapper>
        <Styled.LoginForm onSubmit={handleSubmit(onSubmit)}>
          <Styled.Title>Введите номер</Styled.Title>
          <Styled.Fieldset>
            <Controller
              control={control}
              name="phone"
              render={({
                field: { onChange, onBlur, value, name, ref },
                fieldState: { error },
              }) => (
                <Styled.AuthInputWrapper>
                  <PatternFormat
                    format="+7 (###) ###-####"
                    getInputRef={ref}
                    mask="_"
                    name={name}
                    placeholder="Телефон"
                    value={value}
                    className={classNames(`${styled.input}`, {
                      [`${styled.inputError}`]: error,
                    })}
                    onBlur={onBlur}
                    onChange={onChange}
                  />
                  {error?.message && (
                    <Styled.InputError>{error.message}</Styled.InputError>
                  )}
                </Styled.AuthInputWrapper>
              )}
            />
          </Styled.Fieldset>
          <Styled.GoButtonWrapper>
            <ActionAuthButton
              disabled={isPending}
              title={isPending ? 'Loading...' : 'Go'}
              type="submit"
            />
          </Styled.GoButtonWrapper>
        </Styled.LoginForm>
      </Styled.FormWrapper>
      <AnimatePresence>
        {localError && (
          <Portal selector="#modals">
            <Overlay handleClose={handleCloseModal}>
              <LayoutModal>
                <AuthErrorModal
                  handleClose={handleCloseModal}
                  message={localError?.message}
                />
              </LayoutModal>
            </Overlay>
          </Portal>
        )}
      </AnimatePresence>
    </Styled.Login>
  );
};
+1 −0
Original line number Diff line number Diff line
export * from './schema-login-form';
Loading