blob: f865bb8c5d662f8c930689170beabf673e01539f [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 */
Gabriel Rochon7057b4f2022-11-21 13:28:01 -050018import {
19 Box,
20 Button,
21 FormControl,
22 FormControlLabel,
23 Radio,
24 RadioGroup,
25 Stack,
26 Typography,
27 useMediaQuery,
28} from '@mui/material';
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040029import { Theme, useTheme } from '@mui/material/styles';
Ziwei Wang9b4e2c12023-02-06 14:45:37 -050030import { HttpStatusCode } from 'jami-web-common';
Ziwei Wang49765ec2023-02-13 16:35:32 -050031import { ChangeEvent, FormEvent, useContext, useState } from 'react';
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040032import { useTranslation } from 'react-i18next';
Ziwei Wang3ce1ac02023-02-03 11:59:03 -050033import { Form, Link, useNavigate } from 'react-router-dom';
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040034
35import { PasswordInput, UsernameInput } from '../components/Input';
36import ProcessingRequest from '../components/ProcessingRequest';
Ziwei Wang3ce1ac02023-02-03 11:59:03 -050037import withAuthUI from '../components/WithAuthUI';
Ziwei Wang49765ec2023-02-13 16:35:32 -050038import { AlertSnackbarContext } from '../contexts/AlertSnackbarProvider';
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040039import { loginUser, setAccessToken } from '../utils/auth';
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040040import { inputWidth } from '../utils/constants';
Ziwei Wang3ce1ac02023-02-03 11:59:03 -050041function LoginForm() {
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040042 const theme: Theme = useTheme();
Michelle Sepkap Simee580f422022-10-31 23:27:04 -040043 const navigate = useNavigate();
44 const { t } = useTranslation();
45
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040046 const [username, setUsername] = useState<string>('');
47 const [password, setPassword] = useState<string>('');
Gabriel Rochon7057b4f2022-11-21 13:28:01 -050048 const [isJams, setIsJams] = useState<boolean>(false);
Ziwei Wang9b4e2c12023-02-06 14:45:37 -050049 const [loading, setLoading] = useState<boolean>(false);
Ziwei Wang49765ec2023-02-13 16:35:32 -050050
51 const { setAlertContent } = useContext(AlertSnackbarContext);
52
Ziwei Wang9b4e2c12023-02-06 14:45:37 -050053 const isMobile: boolean = useMediaQuery(theme.breakpoints.only('xs'));
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040054
55 const handleUsername = (event: ChangeEvent<HTMLInputElement>) => {
56 setUsername(event.target.value);
57 };
58
59 const handlePassword = (event: ChangeEvent<HTMLInputElement>) => {
60 setPassword(event.target.value);
61 };
62
Gabriel Rochon7057b4f2022-11-21 13:28:01 -050063 const handleIsJams = (event: ChangeEvent<HTMLInputElement>) => {
64 setIsJams(event.target.value === 'true');
65 };
66
Ziwei Wang49765ec2023-02-13 16:35:32 -050067 const login = (event: FormEvent) => {
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040068 event.preventDefault();
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -040069
Ziwei Wang49765ec2023-02-13 16:35:32 -050070 if (username === '') {
71 setAlertContent({ messageI18nKey: 'username_input_helper_text_empty', severity: 'error', alertOpen: true });
72 return;
73 }
74
75 if (password === '') {
76 setAlertContent({ messageI18nKey: 'password_input_helper_text_empty', severity: 'error', alertOpen: true });
Ziwei Wang9b4e2c12023-02-06 14:45:37 -050077 return;
78 }
79
80 setLoading(true);
81
82 loginUser(username, password, isJams)
83 .then((response) => {
84 if (response.status === HttpStatusCode.Ok) {
85 setAccessToken(response.data.accessToken);
86 navigate('/conversation', { replace: true });
87 }
88 })
89 .catch((e) => {
90 console.log(e);
91 const { status } = e.response;
92 if (status === HttpStatusCode.BadRequest) {
93 //TODO: the only bad request response defined in the server is missing credentials. add the response message to the locale.
94 console.log(e.response.data);
95 // setErrorAlertContent(t('unknown_error_alert'));
96 } else if (status === HttpStatusCode.NotFound) {
97 //TODO: there are two different not found responses that could be returned by the server, use message to differentiate them?
98 console.log(e.response.data);
99 // setErrorAlertContent(t('login_username_not_found'));
100 } else if (status === HttpStatusCode.Unauthorized) {
Ziwei Wang49765ec2023-02-13 16:35:32 -0500101 setAlertContent({ messageI18nKey: 'login_invalid_password', severity: 'error', alertOpen: true });
Michelle Sepkap Simee580f422022-10-31 23:27:04 -0400102 } else {
Ziwei Wang49765ec2023-02-13 16:35:32 -0500103 setAlertContent({ messageI18nKey: 'unknown_error_alert', severity: 'error', alertOpen: true });
Michelle Sepkap Simee580f422022-10-31 23:27:04 -0400104 }
Ziwei Wang9b4e2c12023-02-06 14:45:37 -0500105 })
106 .finally(() => {
107 setLoading(false);
108 });
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400109 };
110
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400111 return (
112 <>
Ziwei Wang9b4e2c12023-02-06 14:45:37 -0500113 <ProcessingRequest open={loading} />
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400114
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400115 <Stack
116 sx={{
117 minHeight: `${isMobile ? 'auto' : '100%'}`,
118 display: 'flex',
119 alignItems: 'center',
120 justifyContent: 'center',
121 }}
122 >
123 <Box sx={{ mt: theme.typography.pxToRem(50), mb: theme.typography.pxToRem(20) }}>
124 <Typography component={'span'} variant="h2">
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400125 {t('login_form_title')}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400126 </Typography>
127 </Box>
128
129 <Form method="post" id="login-form">
130 <div>
131 <UsernameInput
Ziwei Wang9b4e2c12023-02-06 14:45:37 -0500132 value={username}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400133 onChange={handleUsername}
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400134 tooltipTitle={t('login_form_username_tooltip')}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400135 sx={{ width: theme.typography.pxToRem(inputWidth) }}
136 />
137 </div>
138 <div>
139 <PasswordInput
Ziwei Wang9b4e2c12023-02-06 14:45:37 -0500140 value={password}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400141 onChange={handlePassword}
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400142 tooltipTitle={t('login_form_password_tooltip')}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400143 sx={{ width: theme.typography.pxToRem(inputWidth) }}
144 />
145 </div>
Gabriel Rochon7057b4f2022-11-21 13:28:01 -0500146 <div>
147 <FormControl
148 sx={{
149 width: theme.typography.pxToRem(inputWidth),
150 alignItems: 'center',
151 justifyContent: 'space-between',
152 }}
153 >
154 <RadioGroup row onChange={handleIsJams} value={isJams}>
155 <FormControlLabel value="false" control={<Radio />} label={t('jami')} />
156 <FormControlLabel value="true" control={<Radio />} label={t('jams')} />
157 </RadioGroup>
158 </FormControl>
159 </div>
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400160
161 <Button
162 variant="contained"
163 type="submit"
Ziwei Wang9b4e2c12023-02-06 14:45:37 -0500164 onClick={login}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400165 sx={{ width: theme.typography.pxToRem(inputWidth), mt: theme.typography.pxToRem(20) }}
166 >
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400167 {t('login_form_submit_button')}
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400168 </Button>
169 </Form>
170
171 <Box sx={{ mt: theme.typography.pxToRem(50), mb: theme.typography.pxToRem(50) }}>
172 <Typography variant="body1">
Michelle Sepkap Sime559cc802022-11-05 12:06:40 -0400173 {t('login_form_to_registration_text')} &nbsp;
Ziwei Wang3ce1ac02023-02-03 11:59:03 -0500174 <Link to={'/register'}>{t('login_form_to_registration_link')}</Link>
Michelle Sepkap Sime51c00452022-10-31 21:26:38 -0400175 </Typography>
176 </Box>
177 </Stack>
178 </>
179 );
180}
Ziwei Wang3ce1ac02023-02-03 11:59:03 -0500181
182export default withAuthUI(LoginForm);