154 lines
4.0 KiB
TypeScript
154 lines
4.0 KiB
TypeScript
/* eslint-disable react/jsx-curly-newline */
|
||
/* eslint-disable sonarjs/no-small-switch */
|
||
import TelegramIcon from '../public/assets/images/telegram.svg';
|
||
import styles from './Form.module.scss';
|
||
import { publicRuntimeConfig } from '@/config/runtime';
|
||
import { FormStateContext } from '@/context/form-state';
|
||
import type { LdapUser } from '@/types/user';
|
||
import axios from 'axios';
|
||
import Image from 'next/image';
|
||
import type { PropsWithChildren } from 'react';
|
||
import { useContext } from 'react';
|
||
import { useForm } from 'react-hook-form';
|
||
|
||
const ERROR_INVALID_CREDENTIALS = 'Неверный логин или пароль';
|
||
const ERROR_SERVER = 'Не удалось войти. Повторите попытку позже';
|
||
|
||
const { APP_BASE_PATH } = publicRuntimeConfig;
|
||
|
||
type FormData = {
|
||
readonly login: string;
|
||
readonly password: string;
|
||
};
|
||
|
||
type FormProps = {
|
||
readonly onSubmit: (data: FormData) => void;
|
||
};
|
||
|
||
function BaseForm({ children, onSubmit }: FormProps & PropsWithChildren) {
|
||
const { handleSubmit, register } = useForm<FormData>();
|
||
const {
|
||
state: { error, step },
|
||
} = useContext(FormStateContext);
|
||
|
||
return (
|
||
<form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
|
||
<input
|
||
disabled={step === 'telegram'}
|
||
type="text"
|
||
placeholder="Логин"
|
||
required
|
||
autoComplete="on"
|
||
{...register('login', { required: true })}
|
||
/>
|
||
<input
|
||
disabled={step === 'telegram'}
|
||
type="password"
|
||
placeholder="Пароль"
|
||
required
|
||
autoComplete="on"
|
||
{...register('password', { required: true })}
|
||
/>
|
||
{error ? <span className="error">{error}</span> : null}
|
||
{children}
|
||
</form>
|
||
);
|
||
}
|
||
|
||
export const Form = {
|
||
Default() {
|
||
const { dispatch } = useContext(FormStateContext);
|
||
|
||
function handleLogin(data: FormData) {
|
||
const redirectUrl =
|
||
(window.location.pathname.replace(APP_BASE_PATH, '') || '/') +
|
||
(window.location.search || '');
|
||
|
||
return axios
|
||
.post('/login', data)
|
||
.then(() => window.location.replace(redirectUrl))
|
||
.catch(() =>
|
||
dispatch({
|
||
payload: { error: ERROR_INVALID_CREDENTIALS },
|
||
type: 'set-error',
|
||
})
|
||
);
|
||
}
|
||
|
||
return (
|
||
<BaseForm onSubmit={(data) => handleLogin(data)}>
|
||
<button className={styles['button-submit']} type="submit">
|
||
Войти
|
||
</button>
|
||
</BaseForm>
|
||
);
|
||
},
|
||
|
||
Telegram() {
|
||
const {
|
||
dispatch,
|
||
state: { step, user },
|
||
} = useContext(FormStateContext);
|
||
|
||
function handleLogin(data: FormData) {
|
||
axios
|
||
.post<LdapUser>('/login', data)
|
||
.then((res) => {
|
||
dispatch({
|
||
payload: {
|
||
step: 'telegram',
|
||
user: res.data,
|
||
},
|
||
type: 'set-step',
|
||
});
|
||
})
|
||
.catch(() =>
|
||
dispatch({
|
||
payload: { error: ERROR_INVALID_CREDENTIALS },
|
||
type: 'set-error',
|
||
})
|
||
);
|
||
}
|
||
|
||
function handleTelegramLogin() {
|
||
axios
|
||
.post<LdapUser>('/login-telegram')
|
||
.then((res) => {
|
||
// eslint-disable-next-line no-console
|
||
console.log('🚀 ~ .then ~ res:', res);
|
||
})
|
||
.catch(() =>
|
||
dispatch({
|
||
payload: { error: ERROR_SERVER },
|
||
type: 'set-error',
|
||
})
|
||
);
|
||
}
|
||
|
||
if (step === 'telegram') {
|
||
return (
|
||
<BaseForm onSubmit={(data) => handleLogin(data)}>
|
||
<button type="button" className={styles['button-telegram']}>
|
||
<Image
|
||
className={styles['button-telegram-icon']}
|
||
src={TelegramIcon}
|
||
width={24}
|
||
height={22}
|
||
alt="Telegram icon"
|
||
/>
|
||
Войти как <b>{user?.displayName}</b>
|
||
</button>
|
||
</BaseForm>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<BaseForm onSubmit={() => handleTelegramLogin()}>
|
||
<button className={styles['button-submit']} type="submit">
|
||
Войти
|
||
</button>
|
||
</BaseForm>
|
||
);
|
||
},
|
||
};
|