├── .gitignore ├── package.json ├── public └── index.html ├── src ├── App.tsx ├── contexts │ └── auth.tsx ├── index.tsx ├── pages │ ├── Home │ │ └── index.tsx │ └── Login │ │ └── index.tsx ├── react-app-env.d.ts ├── routes │ ├── OtherRoutes.tsx │ ├── SignRoutes.tsx │ └── index.tsx └── services │ └── api.ts ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "authapp", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "@types/jest": "^24.0.0", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^16.9.0", 12 | "@types/react-dom": "^16.9.0", 13 | "react": "^16.13.1", 14 | "react-dom": "^16.13.1", 15 | "react-router-dom": "^5.2.0", 16 | "react-scripts": "3.4.3", 17 | "typescript": "~3.7.2" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": "react-app" 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | }, 40 | "devDependencies": { 41 | "@types/react-router-dom": "^5.1.5" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | React App 11 | 12 | 13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Routes from './routes'; 3 | import { AuthProvider } from './contexts/auth'; 4 | 5 | function App() { 6 | return ( 7 |
8 | 9 | 10 | 11 |
12 | ); 13 | } 14 | 15 | export default App; 16 | -------------------------------------------------------------------------------- /src/contexts/auth.tsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, useState, useEffect, useContext } from 'react'; 2 | 3 | import * as api from '../services/api'; 4 | 5 | interface AuthContextData { 6 | signed: boolean; 7 | user: object | null; 8 | Login(user: object): Promise; 9 | Logout(): void; 10 | } 11 | 12 | const AuthContext = createContext({} as AuthContextData); 13 | 14 | export const AuthProvider: React.FC = ({ children }) => { 15 | const [user, setUser] = useState(null); 16 | 17 | useEffect(() => { 18 | const storagedUser = sessionStorage.getItem('@App:user'); 19 | const storagedToken = sessionStorage.getItem('@App:token'); 20 | 21 | if (storagedToken && storagedUser) { 22 | setUser(JSON.parse(storagedUser)); 23 | api.defaults.headers.Authorization = `Bearer ${storagedToken}`; 24 | } 25 | }, []); 26 | 27 | async function Login(userData: object) { 28 | const response = await api.post('https://localhost:3000', userData); 29 | 30 | setUser(response.data.user); 31 | api.defaults.headers.Authorization = `Bearer ${response.data.token}`; 32 | 33 | sessionStorage.setItem('@App:user', JSON.stringify(response.data.user)); 34 | sessionStorage.setItem('@App:token', response.data.token); 35 | } 36 | 37 | function Logout() { 38 | setUser(null); 39 | } 40 | 41 | return ( 42 | 45 | {children} 46 | 47 | ); 48 | }; 49 | 50 | export function useAuth() { 51 | const context = useContext(AuthContext); 52 | 53 | return context; 54 | } 55 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /src/pages/Home/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useAuth } from '../../contexts/auth'; 3 | 4 | // import { Container } from './styles'; 5 | 6 | const Home: React.FC = () => { 7 | const { signed, Logout } = useAuth(); 8 | 9 | console.log(signed); 10 | 11 | async function handleLogout() { 12 | Logout(); 13 | } 14 | 15 | return ( 16 |
17 |

Home

18 | 19 |
20 | ); 21 | }; 22 | 23 | export default Home; 24 | -------------------------------------------------------------------------------- /src/pages/Login/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useAuth } from '../../contexts/auth'; 3 | 4 | // import { Container } from './styles'; 5 | 6 | const Login: React.FC = () => { 7 | const { signed, Login } = useAuth(); 8 | 9 | console.log(signed); 10 | 11 | async function handleLogin() { 12 | await Login({ 13 | email: 'rafaelcodomingues@gmail.com', 14 | password: '123456', 15 | }); 16 | } 17 | 18 | return ( 19 |
20 | 21 |
22 | ); 23 | }; 24 | 25 | export default Login; 26 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/routes/OtherRoutes.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter, Route } from 'react-router-dom'; 3 | 4 | import Home from '../pages/Home'; 5 | 6 | const OtherRoutes: React.FC = () => { 7 | return ( 8 | 9 | 10 | 11 | ); 12 | }; 13 | 14 | export default OtherRoutes; 15 | -------------------------------------------------------------------------------- /src/routes/SignRoutes.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter, Route } from 'react-router-dom'; 3 | 4 | import Login from '../pages/Login'; 5 | 6 | const SignRoutes: React.FC = () => { 7 | return ( 8 | 9 | 10 | 11 | ); 12 | }; 13 | 14 | export default SignRoutes; 15 | -------------------------------------------------------------------------------- /src/routes/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useAuth } from '../contexts/auth'; 3 | 4 | import SignRoutes from './SignRoutes'; 5 | import OtherRoutes from './OtherRoutes'; 6 | 7 | const Routes: React.FC = () => { 8 | const { signed } = useAuth(); 9 | 10 | return signed ? : ; 11 | }; 12 | 13 | export default Routes; 14 | -------------------------------------------------------------------------------- /src/services/api.ts: -------------------------------------------------------------------------------- 1 | interface Response { 2 | data: { 3 | user: { 4 | name: string; 5 | email: string; 6 | }; 7 | token: string; 8 | }; 9 | } 10 | 11 | export function post(text: string, user: object): Promise { 12 | return new Promise((resolve) => { 13 | setTimeout(() => { 14 | resolve({ 15 | data: { 16 | token: 17 | '91j893h281h9nf98fnf2309jd09jkkd0as98238j9fr8j98f9j8f298r829r-f', 18 | user: { 19 | name: 'Rafael', 20 | email: 'rafaelcodomingues@gmail.com', 21 | }, 22 | }, 23 | }); 24 | }, 2000); 25 | }); 26 | } 27 | 28 | export const defaults = { 29 | headers: { 30 | Authorization: '', 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "noEmit": true, 20 | "jsx": "react" 21 | }, 22 | "include": [ 23 | "src" 24 | ] 25 | } 26 | --------------------------------------------------------------------------------