mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
Update login styles
This commit is contained in:
@@ -1,122 +1,130 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
TextInput,
|
||||
PasswordInput,
|
||||
Button,
|
||||
Stack,
|
||||
Title,
|
||||
Loader,
|
||||
Alert,
|
||||
Box,
|
||||
} from '@mantine/core';
|
||||
import { useDebouncedValue } from '@mantine/hooks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RiCheckboxCircleFill } from 'react-icons/ri';
|
||||
import { Stack, Alert, Box, Center, Group } from '@mantine/core';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
import { Button, PasswordInput, Text, TextInput } from '@/renderer/components';
|
||||
import { ErrorFallback } from '@/renderer/features/action-required';
|
||||
import { useLogin } from '@/renderer/features/auth/queries/use-login';
|
||||
import { usePingServer } from '@/renderer/features/auth/queries/use-ping-server';
|
||||
import { normalizeServerUrl } from '@/renderer/utils';
|
||||
|
||||
const Container = styled(Box)`
|
||||
min-width: 400px;
|
||||
max-width: 50%;
|
||||
margin: auto;
|
||||
padding: 3rem;
|
||||
background: rgba(50, 50, 50, 40%);
|
||||
border-radius: 5px;
|
||||
width: 100%;
|
||||
background: var(--main-bg);
|
||||
`;
|
||||
|
||||
export const LoginRoute = () => {
|
||||
const { t } = useTranslation();
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
const [errorMessage, setErrorMessage] = useState('');
|
||||
const [username, setUsername] = useState(searchParams.get('username') || '');
|
||||
const [password, setPassword] = useState(searchParams.get('password') || '');
|
||||
const [server, setServer] = useState(
|
||||
searchParams.get('server') || 'http://localhost:8843'
|
||||
);
|
||||
const [debouncedServer] = useDebouncedValue(server, 500);
|
||||
|
||||
const {
|
||||
mutate: handleLogin,
|
||||
isLoading,
|
||||
isError,
|
||||
} = useLogin(normalizeServerUrl(server), {
|
||||
password,
|
||||
username,
|
||||
});
|
||||
|
||||
const {
|
||||
isLoading: isCheckingServer,
|
||||
isSuccess: isValidServer,
|
||||
isFetched,
|
||||
} = usePingServer(normalizeServerUrl(debouncedServer));
|
||||
} = useLogin(
|
||||
normalizeServerUrl(server),
|
||||
{
|
||||
password,
|
||||
username,
|
||||
},
|
||||
{
|
||||
onError: (error) => {
|
||||
setErrorMessage(error?.response?.data?.error || error.message);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Title>{t('auth.login')}</Title>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
handleLogin(undefined, {
|
||||
onError: () => {},
|
||||
onSuccess: () => {},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Stack spacing="md">
|
||||
<TextInput
|
||||
required
|
||||
disabled={isLoading}
|
||||
error={!isValidServer && isFetched}
|
||||
label={t('auth.server.label')}
|
||||
placeholder={t('auth.server.placeholder')}
|
||||
rightSection={
|
||||
isCheckingServer ? (
|
||||
<Loader size="xs" />
|
||||
) : isValidServer ? (
|
||||
<RiCheckboxCircleFill size={20} />
|
||||
) : null
|
||||
}
|
||||
value={server}
|
||||
variant="default"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setServer(e.currentTarget.value)
|
||||
}
|
||||
/>
|
||||
<TextInput
|
||||
required
|
||||
disabled={isLoading}
|
||||
label={`${t('auth.username.label')}`}
|
||||
placeholder={`${t('auth.username.placeholder')}`}
|
||||
value={username}
|
||||
variant="default"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setUsername(e.currentTarget.value)
|
||||
}
|
||||
/>
|
||||
<PasswordInput
|
||||
required
|
||||
disabled={isLoading}
|
||||
label={`${t('auth.password.label')}`}
|
||||
placeholder={`${t('auth.password.placeholder')}`}
|
||||
value={password}
|
||||
variant="default"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setPassword(e.currentTarget.value)
|
||||
}
|
||||
/>
|
||||
<Button disabled={!isValidServer} type="submit">
|
||||
Login
|
||||
</Button>
|
||||
{isError && (
|
||||
<Alert color="red" variant="outline">
|
||||
{t('Invalid username or password.')}
|
||||
</Alert>
|
||||
)}
|
||||
<Center sx={{ height: '100%' }}>
|
||||
<Stack
|
||||
spacing={0}
|
||||
sx={{
|
||||
filter: 'drop-shadow(0 0 5px var(--generic-border-color))',
|
||||
height: '50%',
|
||||
maxWidth: '800px',
|
||||
minWidth: '500px',
|
||||
width: '40vw',
|
||||
}}
|
||||
>
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
<Group position="center">
|
||||
<form
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
width: '100%',
|
||||
}}
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
handleLogin(undefined, {
|
||||
onError: () => {},
|
||||
onSuccess: () => {},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
p="2rem"
|
||||
spacing="xl"
|
||||
sx={{
|
||||
background: 'var(--main-bg)',
|
||||
borderRadius: '5px',
|
||||
width: '80%',
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
gradient={{ deg: 45, from: 'indigo', to: 'cyan' }}
|
||||
size="xl"
|
||||
variant="gradient"
|
||||
>
|
||||
Login to Feishin
|
||||
</Text>
|
||||
<TextInput
|
||||
disabled={isLoading}
|
||||
label="Server URL"
|
||||
placeholder="http://localhost:8843"
|
||||
value={server}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setServer(e.currentTarget.value)
|
||||
}
|
||||
/>
|
||||
<TextInput
|
||||
disabled={isLoading}
|
||||
label="Username"
|
||||
value={username}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setUsername(e.currentTarget.value)
|
||||
}
|
||||
/>
|
||||
<PasswordInput
|
||||
disabled={isLoading}
|
||||
label="Password"
|
||||
value={password}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setPassword(e.currentTarget.value)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
disabled={!username || !password}
|
||||
loading={isLoading}
|
||||
radius="xl"
|
||||
type="submit"
|
||||
>
|
||||
Login
|
||||
</Button>
|
||||
{isError && <Alert color="red">{errorMessage}</Alert>}
|
||||
</Stack>
|
||||
</form>
|
||||
</Group>
|
||||
</ErrorBoundary>
|
||||
</Stack>
|
||||
</form>
|
||||
</Center>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user