committed by
GitHub
7 changed files with 111 additions and 14 deletions
@ -1,13 +1,14 @@ |
|||
<!doctype html> |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|||
<title>Vite + React + TS</title> |
|||
<title>Full Stack Project Generator</title> |
|||
<link rel="icon" type="image/x-icon" href="./src/assets/images/favicon.png" /> |
|||
</head> |
|||
<body> |
|||
<div id="root"></div> |
|||
<script type="module" src="/src/main.tsx"></script> |
|||
<script type="module" src="./src/main.tsx"></script> |
|||
</body> |
|||
</html> |
|||
|
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 412 B |
@ -1,10 +1,21 @@ |
|||
import React from 'react' |
|||
import ReactDOM from 'react-dom/client' |
|||
import App from './App.tsx' |
|||
import './index.css' |
|||
import React from 'react'; |
|||
import ReactDOM from 'react-dom/client'; |
|||
|
|||
import { ChakraProvider } from '@chakra-ui/react'; |
|||
|
|||
import App from './App'; |
|||
import { OpenAPI } from './client'; |
|||
|
|||
OpenAPI.BASE = import.meta.env.VITE_API_URL; |
|||
OpenAPI.TOKEN = async () => { |
|||
return localStorage.getItem('access_token') || ''; |
|||
} |
|||
|
|||
ReactDOM.createRoot(document.getElementById('root')!).render( |
|||
<React.StrictMode> |
|||
<App /> |
|||
<ChakraProvider> |
|||
<App /> |
|||
</ChakraProvider> |
|||
</React.StrictMode>, |
|||
) |
|||
|
|||
|
@ -0,0 +1,72 @@ |
|||
import React from "react"; |
|||
|
|||
import { ViewIcon, ViewOffIcon } from "@chakra-ui/icons"; |
|||
import { Button, Center, Container, FormControl, Icon, Image, Input, InputGroup, InputRightElement, Link, useBoolean } from "@chakra-ui/react"; |
|||
import { SubmitHandler, useForm } from "react-hook-form"; |
|||
import { Link as ReactRouterLink, useNavigate } from "react-router-dom"; |
|||
|
|||
import Logo from "../../assets/images/fastapi-logo.png"; |
|||
import { LoginService } from "../../client"; |
|||
import { Body_login_login_access_token as AccessToken } from "../../client/models/Body_login_login_access_token"; |
|||
|
|||
const Login: React.FC = () => { |
|||
const [show, setShow] = useBoolean(); |
|||
const navigate = useNavigate(); |
|||
const { register, handleSubmit } = useForm<AccessToken>(); |
|||
|
|||
const onSubmit: SubmitHandler<AccessToken> = async (data) => { |
|||
const response = await LoginService.loginAccessToken({ |
|||
formData: data, |
|||
}); |
|||
localStorage.setItem("access_token", response.access_token); |
|||
navigate("/"); |
|||
}; |
|||
|
|||
return ( |
|||
<Container |
|||
as="form" |
|||
onSubmit={handleSubmit(onSubmit)} |
|||
h="100vh" |
|||
maxW="sm" |
|||
alignItems="stretch" |
|||
justifyContent="center" |
|||
gap={4} |
|||
centerContent |
|||
> |
|||
<Image src={Logo} alt="FastAPI logo" height="auto" maxW="2xs" alignSelf="center" /> |
|||
<FormControl id="email"> |
|||
<Input {...register("username")} focusBorderColor="blue.200" placeholder="Email" type="text" /> |
|||
</FormControl> |
|||
<FormControl id="password"> |
|||
<InputGroup> |
|||
<Input |
|||
{...register("password")} |
|||
type={show ? "text" : "password"} |
|||
focusBorderColor="blue.200" |
|||
placeholder="Password" |
|||
/> |
|||
<InputRightElement |
|||
color="gray.500" |
|||
_hover={{ |
|||
cursor: "pointer", |
|||
}} |
|||
> |
|||
<Icon onClick={setShow.toggle} aria-label={show ? "Hide password" : "Show password"}> |
|||
{show ? <ViewOffIcon /> : <ViewIcon />} |
|||
</Icon> |
|||
</InputRightElement> |
|||
</InputGroup> |
|||
<Center> |
|||
<Link as={ReactRouterLink} to="/recover-password" color="blue.500" mt={2}> |
|||
Forgot password? |
|||
</Link> |
|||
</Center> |
|||
</FormControl> |
|||
<Button colorScheme="teal" type="submit"> |
|||
Log In |
|||
</Button> |
|||
</Container> |
|||
); |
|||
}; |
|||
|
|||
export default Login; |
Loading…
Reference in new issue