diff --git a/ui/src/LoginPage.tsx b/ui/src/LoginPage.tsx index e044e012f..9cbd37ab8 100644 --- a/ui/src/LoginPage.tsx +++ b/ui/src/LoginPage.tsx @@ -1,29 +1,155 @@ +import { HtmlHTMLAttributes, ReactNode } from 'react'; import { useState } from 'react'; -import { useLogin, useNotify } from 'react-admin'; +import { + Form, + useLogin, + useNotify, + TextInput, + useSafeSetState, +} from 'react-admin'; +import { styled } from '@mui/material/styles'; +import { + Button, + CardContent, + CircularProgress, + Avatar, + Card, + SxProps, +} from '@mui/material'; +import LockIcon from '@mui/icons-material/Lock'; -const LoginPage = ({ theme }) => { +const LoginPage = (props: LoginFormProps) => { const [token, setToken] = useState(''); const login = useLogin(); const notify = useNotify(); + const avatarIcon = ; + const { className } = props; + const [loading, setLoading] = useSafeSetState(false); const handleSubmit = e => { e.preventDefault(); - login({ token }).catch(() => - notify('Invalid token') - ); + setLoading(true); + login({ token }).catch(() => { + setLoading(false); + notify('Invalid token'); + }); }; return ( -
- setToken(e.target.value)} - /> -
+ +
+ {avatarIcon} +
+ + + setToken(e.target.value)} + /> + + + + +
+ ); }; export default LoginPage; +export interface LoginProps extends HtmlHTMLAttributes { + avatarIcon?: ReactNode; + backgroundImage?: string; + children?: ReactNode; + className?: string; + sx?: SxProps; +} + +const PREFIX = 'RaLogin'; +export const LoginClasses = { + card: `${PREFIX}-card`, + avatar: `${PREFIX}-avatar`, + icon: `${PREFIX}-icon`, +}; + +const Root = styled('div', { + name: PREFIX, + overridesResolver: (props, styles) => styles.root, +})(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + minHeight: '100vh', + height: '1px', + alignItems: 'center', + justifyContent: 'flex-start', + backgroundRepeat: 'no-repeat', + backgroundSize: 'cover', + backgroundImage: + 'radial-gradient(circle at 50% 14em, #313264 0%, #00023b 60%, #00023b 100%)', + + [`& .${LoginClasses.card}`]: { + minWidth: 300, + marginTop: '6em', + }, + [`& .${LoginClasses.avatar}`]: { + margin: '1em', + display: 'flex', + justifyContent: 'center', + }, + [`& .${LoginClasses.icon}`]: { + backgroundColor: theme.palette.secondary[500], + }, +})); + +const PREFIXF = 'RaLoginForm'; + +export const LoginFormClasses = { + content: `${PREFIXF}-content`, + button: `${PREFIXF}-button`, + icon: `${PREFIXF + }-icon`, +}; + +const StyledForm = styled(Form, { + name: PREFIXF, + overridesResolver: (props, styles) => styles.root, +})(({ theme }) => ({ + [`& .${LoginFormClasses.content}`]: { + width: 300, + }, + [`& .${LoginFormClasses.button}`]: { + marginTop: theme.spacing(2), + }, + [`& .${LoginFormClasses.icon}`]: { + margin: theme.spacing(0.3), + }, +})); + +export interface LoginFormProps { + redirectTo?: string; + className?: string; +}