blob: 5cd291767200178c7dc8451f3430263893d887fa [file] [log] [blame]
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -04001/*
2 * Copyright (C) 2022 Savoir-faire Linux Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
18import { Box, Button, Stack, Typography, useMediaQuery } from '@mui/material';
19import { Theme, useTheme } from '@mui/material/styles';
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040020import { ChangeEvent, FormEvent, MouseEvent, ReactNode, useState } from 'react';
21import { useTranslation } from 'react-i18next';
22import { Form, useNavigate } from 'react-router-dom';
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040023
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040024import { AlertSnackbar } from '../components/AlertSnackbar';
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040025import { PasswordInput, UsernameInput } from '../components/Input';
26import ProcessingRequest from '../components/ProcessingRequest';
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040027import { loginUser, setAccessToken } from '../utils/auth';
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040028import { inputWidth } from '../utils/constants';
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040029import { InvalidPassword, UsernameNotFound } from '../utils/errors';
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040030
31type JamiLoginProps = {
32 register: () => void;
33};
34
35export default function JamiLogin(props: JamiLoginProps) {
36 const theme: Theme = useTheme();
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040037 const navigate = useNavigate();
38 const { t } = useTranslation();
39
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040040 const [username, setUsername] = useState<string>('');
41 const [password, setPassword] = useState<string>('');
42 const [isLoggingInUser, setIsLoggingInUser] = useState<boolean>(false);
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040043 const [errorAlertContent, setErrorAlertContent] = useState<ReactNode>(undefined);
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040044
45 const handleUsername = (event: ChangeEvent<HTMLInputElement>) => {
46 setUsername(event.target.value);
47 };
48
49 const handlePassword = (event: ChangeEvent<HTMLInputElement>) => {
50 setPassword(event.target.value);
51 };
52
53 const register = (event: MouseEvent<HTMLAnchorElement>) => {
54 event.preventDefault();
55 props.register();
56 };
57
58 const authenticateUser = async (event: FormEvent) => {
59 event.preventDefault();
60 if (username.length > 0 && password.length > 0) {
61 setIsLoggingInUser(true);
62
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040063 try {
64 const accessToken = await loginUser(username, password);
65 setAccessToken(accessToken);
66 navigate('/settings', { replace: true });
67 } catch (err) {
68 setIsLoggingInUser(false);
69 if (err instanceof UsernameNotFound) {
70 setErrorAlertContent(t('login_username_not_found'));
71 } else if (err instanceof InvalidPassword) {
72 setErrorAlertContent(t('login_invalid_password'));
73 } else {
74 throw err;
75 }
76 }
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040077 }
78 };
79
80 const isMobile: boolean = useMediaQuery(theme.breakpoints.only('xs'));
81
82 return (
83 <>
84 <ProcessingRequest open={isLoggingInUser} />
85
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040086 <AlertSnackbar severity={'error'} open={!!errorAlertContent} onClose={() => setErrorAlertContent(undefined)}>
87 {errorAlertContent}
88 </AlertSnackbar>
89
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040090 <Stack
91 sx={{
92 minHeight: `${isMobile ? 'auto' : '100%'}`,
93 display: 'flex',
94 alignItems: 'center',
95 justifyContent: 'center',
96 }}
97 >
98 <Box sx={{ mt: theme.typography.pxToRem(50), mb: theme.typography.pxToRem(20) }}>
99 <Typography component={'span'} variant="h2">
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400100 {t('login_form_title')}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400101 </Typography>
102 </Box>
103
104 <Form method="post" id="login-form">
105 <div>
106 <UsernameInput
107 onChange={handleUsername}
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400108 tooltipTitle={t('login_form_username_tooltip')}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400109 sx={{ width: theme.typography.pxToRem(inputWidth) }}
110 />
111 </div>
112 <div>
113 <PasswordInput
114 onChange={handlePassword}
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400115 tooltipTitle={t('login_form_password_tooltip')}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400116 sx={{ width: theme.typography.pxToRem(inputWidth) }}
117 />
118 </div>
119
120 <Button
121 variant="contained"
122 type="submit"
123 onClick={authenticateUser}
124 sx={{ width: theme.typography.pxToRem(inputWidth), mt: theme.typography.pxToRem(20) }}
125 >
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400126 {t('login_form_submit_button')}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400127 </Button>
128 </Form>
129
130 <Box sx={{ mt: theme.typography.pxToRem(50), mb: theme.typography.pxToRem(50) }}>
131 <Typography variant="body1">
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400132 {t('login_form_to_registration_text')} &nbsp;
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400133 <a href="" onClick={register}>
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400134 {t('login_form_to_registration_link')}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400135 </a>
136 </Typography>
137 </Box>
138 </Stack>
139 </>
140 );
141}