diff options
Diffstat (limited to 'modern/src/login')
-rw-r--r-- | modern/src/login/LoginLayout.js | 2 | ||||
-rw-r--r-- | modern/src/login/LoginPage.js | 163 | ||||
-rw-r--r-- | modern/src/login/RegisterPage.js | 128 | ||||
-rw-r--r-- | modern/src/login/ResetPasswordPage.js | 115 |
4 files changed, 193 insertions, 215 deletions
diff --git a/modern/src/login/LoginLayout.js b/modern/src/login/LoginLayout.js index cfdd837c..4d86d2f6 100644 --- a/modern/src/login/LoginLayout.js +++ b/modern/src/login/LoginLayout.js @@ -63,7 +63,7 @@ const LoginLayout = ({ children }) => { </div> <Paper className={classes.paper}> <form className={classes.form}> - { children } + {children} </form> </Paper> </main> diff --git a/modern/src/login/LoginPage.js b/modern/src/login/LoginPage.js index cc010427..1d18f2a8 100644 --- a/modern/src/login/LoginPage.js +++ b/modern/src/login/LoginPage.js @@ -1,6 +1,5 @@ import React, { useState } from 'react'; import { - Grid, useMediaQuery, InputLabel, Select, @@ -26,16 +25,29 @@ import usePersistedState from '../common/util/usePersistedState'; const useStyles = makeStyles((theme) => ({ legacy: { - position: 'absolute', + position: 'fixed', top: theme.spacing(1), right: theme.spacing(1), }, + container: { + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(2), + }, logoContainer: { textAlign: 'center', color: theme.palette.primary.main, }, + extraContainer: { + display: 'flex', + gap: theme.spacing(2), + }, + registerButton: { + minWidth: 'unset', + }, resetPassword: { cursor: 'pointer', + textAlign: 'right', }, })); @@ -93,89 +105,82 @@ const LoginPage = () => { <CachedIcon /> </IconButton> </Tooltip> - <Grid container direction="column" spacing={2}> - {useMediaQuery(theme.breakpoints.down('lg')) - && ( - <Grid item className={classes.logoContainer}> - <svg height="64" width="240"> - <use xlinkHref="/logo.svg#img" /> - </svg> - </Grid> - )} - <Grid item> - <TextField - required - fullWidth - error={failed} - label={t('userEmail')} - name="email" - value={email} - autoComplete="email" - autoFocus={!email} - onChange={(e) => setEmail(e.target.value)} - onKeyUp={handleSpecialKey} - helperText={failed && 'Invalid username or password'} - /> - </Grid> - <Grid item> - <TextField - required - fullWidth - error={failed} - label={t('userPassword')} - name="password" - value={password} - type="password" - autoComplete="current-password" - autoFocus={!!email} - onChange={(e) => setPassword(e.target.value)} - onKeyUp={handleSpecialKey} - /> - </Grid> - <Grid item> + <div className={classes.container}> + {useMediaQuery(theme.breakpoints.down('lg')) && ( + <div className={classes.logoContainer}> + <svg height="64" width="240"> + <use xlinkHref="/logo.svg#img" /> + </svg> + </div> + )} + <TextField + required + error={failed} + label={t('userEmail')} + name="email" + value={email} + autoComplete="email" + autoFocus={!email} + onChange={(e) => setEmail(e.target.value)} + onKeyUp={handleSpecialKey} + helperText={failed && 'Invalid username or password'} + /> + <TextField + required + error={failed} + label={t('userPassword')} + name="password" + value={password} + type="password" + autoComplete="current-password" + autoFocus={!!email} + onChange={(e) => setPassword(e.target.value)} + onKeyUp={handleSpecialKey} + /> + <Button + onClick={handleSubmit} + onKeyUp={handleSpecialKey} + variant="contained" + color="secondary" + disabled={!email || !password} + > + {t('loginLogin')} + </Button> + <div className={classes.extraContainer}> <Button - onClick={handleSubmit} - onKeyUp={handleSpecialKey} - variant="contained" + className={classes.registerButton} + onClick={() => navigate('/register')} + disabled={!registrationEnabled} color="secondary" - disabled={!email || !password} - fullWidth > - {t('loginLogin')} + {t('loginRegister')} </Button> - </Grid> - <Grid item container spacing={2}> - <Grid item> - <Button onClick={() => navigate('/register')} disabled={!registrationEnabled} color="secondary"> - {t('loginRegister')} - </Button> - </Grid> - <Grid item xs> - <FormControl fullWidth> - <InputLabel>{t('loginLanguage')}</InputLabel> - <Select label={t('loginLanguage')} value={language} onChange={(e) => setLanguage(e.target.value)}> - {languageList.map((it) => <MenuItem key={it.code} value={it.code}>{it.name}</MenuItem>)} - </Select> - </FormControl> - </Grid> - </Grid> + <FormControl fullWidth> + <InputLabel>{t('loginLanguage')}</InputLabel> + <Select label={t('loginLanguage')} value={language} onChange={(e) => setLanguage(e.target.value)}> + {languageList.map((it) => <MenuItem key={it.code} value={it.code}>{it.name}</MenuItem>)} + </Select> + </FormControl> + </div> {emailEnabled && ( - <Grid item container justifyContent="flex-end"> - <Grid item> - <Link onClick={() => navigate('/reset-password')} className={classes.resetPassword} underline="none">{t('loginReset')}</Link> - </Grid> - </Grid> + <Link + onClick={() => navigate('/reset-password')} + className={classes.resetPassword} + underline="none" + > + {t('loginReset')} + </Link> )} - <Snackbar - open={!!announcement && !announcementShown} - message={announcement} - action={( - <IconButton size="small" color="inherit" onClick={() => setAnnouncementShown(true)}> - <CloseIcon fontSize="small" /> - </IconButton> - )} - /> - </Grid> + </div> + <Snackbar + open={!!announcement && !announcementShown} + message={announcement} + action={( + <IconButton size="small" color="inherit" onClick={() => setAnnouncementShown(true)}> + <CloseIcon fontSize="small" /> + </IconButton> + )} + /> </LoginLayout> ); }; diff --git a/modern/src/login/RegisterPage.js b/modern/src/login/RegisterPage.js index 986bf894..08ff3e8f 100644 --- a/modern/src/login/RegisterPage.js +++ b/modern/src/login/RegisterPage.js @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { - Grid, Button, TextField, Typography, Link, Snackbar, + Button, TextField, Typography, Snackbar, IconButton, } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import { useNavigate } from 'react-router-dom'; @@ -11,18 +11,21 @@ import { snackBarDurationShortMs } from '../common/util/duration'; import { useCatch } from '../reactHelper'; const useStyles = makeStyles((theme) => ({ + container: { + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(2), + }, + header: { + display: 'flex', + alignItems: 'center', + }, title: { fontSize: theme.spacing(3), fontWeight: 500, - marginLeft: theme.spacing(2), + marginLeft: theme.spacing(1), textTransform: 'uppercase', }, - link: { - fontSize: theme.spacing(3), - fontWeight: 500, - marginTop: theme.spacing(0.5), - cursor: 'pointer', - }, })); const RegisterPage = () => { @@ -50,75 +53,58 @@ const RegisterPage = () => { return ( <LoginLayout> + <div className={classes.container}> + <div className={classes.header}> + <IconButton color="primary" onClick={() => navigate('/login')}> + <ArrowBackIcon /> + </IconButton> + <Typography className={classes.title} color="primary"> + {t('loginRegister')} + </Typography> + </div> + <TextField + required + label={t('sharedName')} + name="name" + value={name} + autoComplete="name" + autoFocus + onChange={(event) => setName(event.target.value)} + /> + <TextField + required + type="email" + label={t('userEmail')} + name="email" + value={email} + autoComplete="email" + onChange={(event) => setEmail(event.target.value)} + /> + <TextField + required + label={t('userPassword')} + name="password" + value={password} + type="password" + autoComplete="current-password" + onChange={(event) => setPassword(event.target.value)} + /> + <Button + variant="contained" + color="secondary" + onClick={handleSubmit} + disabled={!name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password} + fullWidth + > + {t('loginRegister')} + </Button> + </div> <Snackbar open={snackbarOpen} onClose={() => navigate('/login')} autoHideDuration={snackBarDurationShortMs} message={t('loginCreated')} /> - <Grid container direction="column" spacing={2}> - <Grid container item> - <Grid item> - <Typography className={classes.link} color="primary"> - <Link onClick={() => navigate('/login')}> - <ArrowBackIcon /> - </Link> - </Typography> - </Grid> - <Grid item xs> - <Typography className={classes.title} color="primary"> - {t('loginRegister')} - </Typography> - </Grid> - </Grid> - <Grid item> - <TextField - required - fullWidth - label={t('sharedName')} - name="name" - value={name} - autoComplete="name" - autoFocus - onChange={(event) => setName(event.target.value)} - /> - </Grid> - <Grid item> - <TextField - required - fullWidth - type="email" - label={t('userEmail')} - name="email" - value={email} - autoComplete="email" - onChange={(event) => setEmail(event.target.value)} - /> - </Grid> - <Grid item> - <TextField - required - fullWidth - label={t('userPassword')} - name="password" - value={password} - type="password" - autoComplete="current-password" - onChange={(event) => setPassword(event.target.value)} - /> - </Grid> - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={handleSubmit} - disabled={!name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password} - fullWidth - > - {t('loginRegister')} - </Button> - </Grid> - </Grid> </LoginLayout> ); }; diff --git a/modern/src/login/ResetPasswordPage.js b/modern/src/login/ResetPasswordPage.js index c3e91fe6..f2f1a132 100644 --- a/modern/src/login/ResetPasswordPage.js +++ b/modern/src/login/ResetPasswordPage.js @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { - Grid, Button, TextField, Typography, Link, Snackbar, + Button, TextField, Typography, Snackbar, IconButton, } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import { useNavigate } from 'react-router-dom'; @@ -12,18 +12,21 @@ import { snackBarDurationShortMs } from '../common/util/duration'; import { useCatch } from '../reactHelper'; const useStyles = makeStyles((theme) => ({ + container: { + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(2), + }, + header: { + display: 'flex', + alignItems: 'center', + }, title: { fontSize: theme.spacing(3), fontWeight: 500, - marginLeft: theme.spacing(2), + marginLeft: theme.spacing(1), textTransform: 'uppercase', }, - link: { - fontSize: theme.spacing(3), - fontWeight: 500, - marginTop: theme.spacing(0.5), - cursor: 'pointer', - }, })); const ResetPasswordPage = () => { @@ -61,68 +64,52 @@ const ResetPasswordPage = () => { return ( <LoginLayout> + <div className={classes.container}> + <div className={classes.header}> + <IconButton color="primary" onClick={() => navigate('/login')}> + <ArrowBackIcon /> + </IconButton> + <Typography className={classes.title} color="primary"> + {t('loginReset')} + </Typography> + </div> + {!token ? ( + <TextField + required + type="email" + label={t('userEmail')} + name="email" + value={email} + autoComplete="email" + onChange={(event) => setEmail(event.target.value)} + /> + ) : ( + <TextField + required + label={t('userPassword')} + name="password" + value={password} + type="password" + autoComplete="current-password" + onChange={(event) => setPassword(event.target.value)} + /> + )} + <Button + variant="contained" + color="secondary" + onClick={handleSubmit} + disabled={!/(.+)@(.+)\.(.{2,})/.test(email) && !password} + fullWidth + > + {t('loginReset')} + </Button> + </div> <Snackbar open={snackbarOpen} onClose={() => navigate('/login')} autoHideDuration={snackBarDurationShortMs} message={!token ? t('loginResetSuccess') : t('loginUpdateSuccess')} /> - <Grid container direction="column" spacing={2}> - <Grid container item> - <Grid item> - <Typography className={classes.link} color="primary"> - <Link onClick={() => navigate('/login')}> - <ArrowBackIcon /> - </Link> - </Typography> - </Grid> - <Grid item xs> - <Typography className={classes.title} color="primary"> - {t('loginReset')} - </Typography> - </Grid> - </Grid> - {!token - ? ( - <Grid item> - <TextField - required - fullWidth - type="email" - label={t('userEmail')} - name="email" - value={email} - autoComplete="email" - onChange={(event) => setEmail(event.target.value)} - /> - </Grid> - ) - : ( - <Grid item> - <TextField - required - fullWidth - label={t('userPassword')} - name="password" - value={password} - type="password" - autoComplete="current-password" - onChange={(event) => setPassword(event.target.value)} - /> - </Grid> - )} - <Grid item> - <Button - variant="contained" - color="secondary" - onClick={handleSubmit} - disabled={!/(.+)@(.+)\.(.{2,})/.test(email) && !password} - fullWidth - > - {t('loginReset')} - </Button> - </Grid> - </Grid> </LoginLayout> ); }; |