gitscope
https://dev.kronoz.win/r/marzneshin.git
app/dashboard/src/pages/login/index.tsx · v0.1.1
Source
1 a47eb4c Dawsh 2y ago import {
2 a47eb4c Dawsh 2y ago Alert,
3 a47eb4c Dawsh 2y ago AlertDescription,
4 a47eb4c Dawsh 2y ago AlertIcon,
5 a47eb4c Dawsh 2y ago Box,
6 a47eb4c Dawsh 2y ago Button,
7 a47eb4c Dawsh 2y ago chakra,
8 a47eb4c Dawsh 2y ago FormControl,
9 a47eb4c Dawsh 2y ago HStack,
10 a47eb4c Dawsh 2y ago Text,
11 a47eb4c Dawsh 2y ago VStack,
12 bf7c131 Mardin 2y ago } from '@chakra-ui/react';
13 bedeeff Mardin 2y ago import { ArrowRightStartOnRectangleIcon } from '@heroicons/react/24/outline';
14 bf7c131 Mardin 2y ago import { zodResolver } from '@hookform/resolvers/zod';
15 bf7c131 Mardin 2y ago import { FC, useEffect, useState } from 'react';
16 bf7c131 Mardin 2y ago import { FieldValues, useForm } from 'react-hook-form';
17 bf7c131 Mardin 2y ago import { useLocation, useNavigate } from 'react-router-dom';
18 bf7c131 Mardin 2y ago import { z } from 'zod';
19 5825ea4 Mardin 2y ago import { Footer } from 'components/footer';
20 5825ea4 Mardin 2y ago import { Input } from 'components/input';
21 bf7c131 Mardin 2y ago import { fetch } from 'service/http';
22 bf7c131 Mardin 2y ago import { ReactComponent as Logo } from 'assets/logo.svg';
23 bf7c131 Mardin 2y ago import { useTranslation } from 'react-i18next';
24 5825ea4 Mardin 2y ago import { Language } from 'components/language';
25 89f8f93 Mardin 2y ago import { useAdmin } from 'stores';
26 a47eb4c Dawsh 2y ago
27 a47eb4c Dawsh 2y ago const schema = z.object({
28 bf7c131 Mardin 2y ago username: z.string().min(1, 'login.fieldRequired'),
29 bf7c131 Mardin 2y ago password: z.string().min(1, 'login.fieldRequired'),
30 a47eb4c Dawsh 2y ago });
31 a47eb4c Dawsh 2y ago
32 a47eb4c Dawsh 2y ago export const LogoIcon = chakra(Logo, {
33 a47eb4c Dawsh 2y ago baseStyle: {
34 bf7c131 Mardin 2y ago strokeWidth: '10px',
35 a47eb4c Dawsh 2y ago w: 12,
36 a47eb4c Dawsh 2y ago h: 12,
37 a47eb4c Dawsh 2y ago },
38 a47eb4c Dawsh 2y ago });
39 a47eb4c Dawsh 2y ago
40 bedeeff Mardin 2y ago const LoginIcon = chakra(ArrowRightStartOnRectangleIcon, {
41 a47eb4c Dawsh 2y ago baseStyle: {
42 a47eb4c Dawsh 2y ago w: 5,
43 a47eb4c Dawsh 2y ago h: 5,
44 bf7c131 Mardin 2y ago strokeWidth: '2px',
45 a47eb4c Dawsh 2y ago },
46 a47eb4c Dawsh 2y ago });
47 a47eb4c Dawsh 2y ago
48 a47eb4c Dawsh 2y ago export const Login: FC = () => {
49 bf7c131 Mardin 2y ago const [error, setError] = useState('');
50 a47eb4c Dawsh 2y ago const [loading, setLoading] = useState(false);
51 a47eb4c Dawsh 2y ago const navigate = useNavigate();
52 d459492 Mardin 2y ago const { setAuthToken, removeAuthToken } = useAdmin();
53 a47eb4c Dawsh 2y ago const { t } = useTranslation();
54 a47eb4c Dawsh 2y ago let location = useLocation();
55 a47eb4c Dawsh 2y ago const {
56 a47eb4c Dawsh 2y ago register,
57 a47eb4c Dawsh 2y ago formState: { errors },
58 a47eb4c Dawsh 2y ago handleSubmit,
59 a47eb4c Dawsh 2y ago } = useForm({
60 a47eb4c Dawsh 2y ago resolver: zodResolver(schema),
61 a47eb4c Dawsh 2y ago });
62 a47eb4c Dawsh 2y ago useEffect(() => {
63 a47eb4c Dawsh 2y ago removeAuthToken();
64 bf7c131 Mardin 2y ago if (location.pathname !== '/login') {
65 bf7c131 Mardin 2y ago navigate('/login', { replace: true });
66 a47eb4c Dawsh 2y ago }
67 a47eb4c Dawsh 2y ago }, []);
68 a47eb4c Dawsh 2y ago const login = (values: FieldValues) => {
69 bf7c131 Mardin 2y ago setError('');
70 a47eb4c Dawsh 2y ago const formData = new FormData();
71 bf7c131 Mardin 2y ago formData.append('username', values.username);
72 bf7c131 Mardin 2y ago formData.append('password', values.password);
73 bf7c131 Mardin 2y ago formData.append('grant_type', 'password');
74 a47eb4c Dawsh 2y ago setLoading(true);
75 5bb2712 Mardin 2y ago fetch('/admins/token', { method: 'post', body: formData })
76 a47eb4c Dawsh 2y ago .then(({ access_token: token }) => {
77 a47eb4c Dawsh 2y ago setAuthToken(token);
78 bf7c131 Mardin 2y ago navigate('/');
79 a47eb4c Dawsh 2y ago })
80 a47eb4c Dawsh 2y ago .catch((err) => {
81 a47eb4c Dawsh 2y ago setError(err.response._data.detail);
82 a47eb4c Dawsh 2y ago })
83 a47eb4c Dawsh 2y ago .finally(setLoading.bind(null, false));
84 a47eb4c Dawsh 2y ago };
85 a47eb4c Dawsh 2y ago return (
86 a47eb4c Dawsh 2y ago <VStack justifyContent="space-between" minH="100vh" p="6" w="full">
87 a47eb4c Dawsh 2y ago <Box w="full">
88 a47eb4c Dawsh 2y ago <HStack justifyContent="end" w="full">
89 a47eb4c Dawsh 2y ago <Language />
90 a47eb4c Dawsh 2y ago </HStack>
91 a47eb4c Dawsh 2y ago <HStack w="full" justifyContent="center" alignItems="center">
92 a47eb4c Dawsh 2y ago <Box w="full" maxW="340px" mt="6">
93 a47eb4c Dawsh 2y ago <VStack alignItems="center" w="full">
94 a47eb4c Dawsh 2y ago <LogoIcon />
95 a47eb4c Dawsh 2y ago <Text fontSize="2xl" fontWeight="semibold">
96 bf7c131 Mardin 2y ago {t('login.loginYourAccount')}
97 a47eb4c Dawsh 2y ago </Text>
98 bf7c131 Mardin 2y ago <Text color="gray.600" _dark={{ color: 'gray.400' }}>
99 bf7c131 Mardin 2y ago {t('login.welcomeBack')}
100 a47eb4c Dawsh 2y ago </Text>
101 a47eb4c Dawsh 2y ago </VStack>
102 a47eb4c Dawsh 2y ago <Box w="full" maxW="300px" m="auto" pt="4">
103 a47eb4c Dawsh 2y ago <form onSubmit={handleSubmit(login)}>
104 a47eb4c Dawsh 2y ago <VStack mt={4} rowGap={2}>
105 a47eb4c Dawsh 2y ago <FormControl>
106 a47eb4c Dawsh 2y ago <Input
107 a47eb4c Dawsh 2y ago w="full"
108 bf7c131 Mardin 2y ago placeholder={t('username')}
109 bf7c131 Mardin 2y ago {...register('username')}
110 a47eb4c Dawsh 2y ago error={t(errors?.username?.message as string)}
111 a47eb4c Dawsh 2y ago />
112 a47eb4c Dawsh 2y ago </FormControl>
113 a47eb4c Dawsh 2y ago <FormControl>
114 a47eb4c Dawsh 2y ago <Input
115 a47eb4c Dawsh 2y ago w="full"
116 a47eb4c Dawsh 2y ago type="password"
117 bf7c131 Mardin 2y ago placeholder={t('password')}
118 bf7c131 Mardin 2y ago {...register('password')}
119 a47eb4c Dawsh 2y ago error={t(errors?.password?.message as string)}
120 a47eb4c Dawsh 2y ago />
121 a47eb4c Dawsh 2y ago </FormControl>
122 a47eb4c Dawsh 2y ago {error && (
123 a47eb4c Dawsh 2y ago <Alert status="error" rounded="md">
124 a47eb4c Dawsh 2y ago <AlertIcon />
125 a47eb4c Dawsh 2y ago <AlertDescription>{error}</AlertDescription>
126 a47eb4c Dawsh 2y ago </Alert>
127 a47eb4c Dawsh 2y ago )}
128 a47eb4c Dawsh 2y ago <Button
129 a47eb4c Dawsh 2y ago isLoading={loading}
130 a47eb4c Dawsh 2y ago type="submit"
131 a47eb4c Dawsh 2y ago w="full"
132 a47eb4c Dawsh 2y ago colorScheme="primary"
133 a47eb4c Dawsh 2y ago >
134 a47eb4c Dawsh 2y ago {<LoginIcon marginRight={1} />}
135 912788f Mardin 2y ago {t('login.login')}
136 a47eb4c Dawsh 2y ago </Button>
137 a47eb4c Dawsh 2y ago </VStack>
138 a47eb4c Dawsh 2y ago </form>
139 a47eb4c Dawsh 2y ago </Box>
140 a47eb4c Dawsh 2y ago </Box>
141 a47eb4c Dawsh 2y ago </HStack>
142 a47eb4c Dawsh 2y ago </Box>
143 57a4cf7 Mrdn 2y ago <Footer bottom={3} />
144 a47eb4c Dawsh 2y ago </VStack>
145 a47eb4c Dawsh 2y ago );
146 a47eb4c Dawsh 2y ago };
147 a47eb4c Dawsh 2y ago
148 a47eb4c Dawsh 2y ago export default Login;