├── vite.config.js ├── src ├── supabase │ └── supabase-client.jsx ├── components │ ├── Secret.jsx │ ├── EmptyComponent.jsx │ ├── Home.jsx │ ├── UserStatus.jsx │ ├── About.jsx │ ├── Login.jsx │ └── Register.jsx ├── index.css ├── context │ └── AuthContext.jsx ├── App.jsx ├── App.css └── main.jsx ├── .gitignore ├── index.html └── .eslintrc.cjs /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /src/supabase/supabase-client.jsx: -------------------------------------------------------------------------------- 1 | import { createClient } from "@supabase/supabase-js"; 2 | 3 | export const supabase = createClient( 4 | import.meta.env.VITE_SUPABASE_URL, 5 | import.meta.env.VITE_SUPABASE_API_KEY 6 | ) -------------------------------------------------------------------------------- /src/components/Secret.jsx: -------------------------------------------------------------------------------- 1 | export const Secret = () => { 2 | 3 | return ( 4 | <> 5 |

Tajemství

6 | 7 |

Tajná stránka jen pro registrované uživatele.

8 | 9 | ); 10 | } 11 | 12 | export default Secret; -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 3 | line-height: 1.5; 4 | font-weight: 400; 5 | 6 | font-synthesis: none; 7 | text-rendering: optimizeLegibility; 8 | -webkit-font-smoothing: antialiased; 9 | -moz-osx-font-smoothing: grayscale; 10 | } 11 | -------------------------------------------------------------------------------- /src/components/EmptyComponent.jsx: -------------------------------------------------------------------------------- 1 | export function EmptyComponent() { 2 | return ( 3 |
4 |

Component

5 |

value

6 | 7 |
8 | ); 9 | } 10 | 11 | export default EmptyComponent; -------------------------------------------------------------------------------- /src/components/Home.jsx: -------------------------------------------------------------------------------- 1 | export function Home() { 2 | 3 | return ( 4 | <> 5 |

Úvod / Homepage

6 | 7 |

Lorem ipsum, dolor sit amet consectetur adipisicing elit. Magnam provident iusto deleniti nulla nihil quasi quae pariatur, architecto hic aspernatur.

8 | 9 | ); 10 | } 11 | 12 | export default Home; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/components/UserStatus.jsx: -------------------------------------------------------------------------------- 1 | import {useAuth} from '../context/AuthContext' 2 | 3 | export function UserStatus() { 4 | 5 | const {user, isAuth} = useAuth() 6 | 7 | return ( 8 |
9 | 10 | {isAuth 11 | ?

{user.firstName} {user.lastName}

12 | :

Neni prihlaseny

13 | } 14 | 15 |
16 | ); 17 | } 18 | 19 | export default UserStatus; -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/components/About.jsx: -------------------------------------------------------------------------------- 1 | export function About() { 2 | 3 | return ( 4 | <> 5 |

O nás

6 | 7 | 14 | 15 | 16 | ); 17 | } 18 | 19 | export default About; -------------------------------------------------------------------------------- /src/context/AuthContext.jsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext, useEffect, useState } from "react" 2 | import { supabase } from "../supabase/supabase-client" 3 | 4 | const AuthContext = createContext({}); 5 | 6 | export const useAuth = () => useContext(AuthContext) 7 | 8 | 9 | 10 | 11 | export function AuthProvider({children}) { 12 | 13 | const [user, setUser] = useState(null) 14 | const [isAuth, setIsAuth] = useState(false) 15 | 16 | return ( 17 | 21 | {children} 22 | 23 | ) 24 | 25 | } 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react/prop-types': 0, 16 | 'react/jsx-no-target-blank': 'off', 17 | 'react-refresh/only-export-components': [ 18 | 'warn', 19 | { allowConstantExport: true }, 20 | ], 21 | }, 22 | } 23 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import './App.css' 2 | 3 | import {NavLink, Outlet} from 'react-router-dom' 4 | 5 | import UserStatus from './components/UserStatus' 6 | function App() { 7 | return ( 8 | <> 9 |

Supabase + Auth + Router

10 | 11 |
12 | 19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 | 27 |
28 | 29 | 30 | ) 31 | } 32 | 33 | export default App 34 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .header { 2 | display: flex; 3 | justify-content: space-between; 4 | align-items: center; 5 | } 6 | 7 | .menu { 8 | display: flex; 9 | gap: 5px; 10 | } 11 | 12 | .menu a { 13 | padding: 10px 20px; 14 | background: #d5d5d5; 15 | text-decoration: none; 16 | color: navy; 17 | } 18 | 19 | .menu a:hover { 20 | background: #b5b5b5; 21 | } 22 | 23 | .menu a.active { 24 | background: dodgerblue; 25 | color: white; 26 | } 27 | 28 | 29 | .user-status { 30 | padding: 10px 20px; 31 | border: 5px solid dodgerblue; 32 | } 33 | 34 | 35 | 36 | .main { 37 | margin: 2em 0; 38 | padding: 1em; 39 | border: 5px solid silver; 40 | } 41 | 42 | 43 | .form-field { 44 | display: flex; 45 | align-items: baseline; 46 | max-width: 350px; 47 | } 48 | 49 | .form-field label { 50 | flex: 0 1 30%; 51 | display: block; 52 | margin-bottom: 10px; 53 | } 54 | 55 | .form-field input { 56 | flex: 0 1 70%; 57 | padding: 5px; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import './index.css' 4 | 5 | import {BrowserRouter, Routes, Route} from 'react-router-dom' 6 | 7 | import {AuthProvider} from './context/AuthContext' 8 | 9 | import App from './App.jsx' 10 | import Home from './components/Home' 11 | import About from './components/About' 12 | import Secret from './components/Secret' 13 | import Login from './components/Login' 14 | import Register from './components/Register' 15 | 16 | ReactDOM.createRoot(document.getElementById('root')).render( 17 | 18 | 19 | 20 | 21 | }> 22 | } /> 23 | } /> 24 | } /> 25 | } /> 26 | } /> 27 | 28 | 29 | 30 | 31 | , 32 | ) 33 | -------------------------------------------------------------------------------- /src/components/Login.jsx: -------------------------------------------------------------------------------- 1 | import {useState} from 'react' 2 | import {Link} from 'react-router-dom' 3 | 4 | import {supabase} from '../supabase/supabase-client' 5 | 6 | export const Login = () => { 7 | 8 | const [email, setEmail] = useState('') 9 | const [password, setPassword] = useState('') 10 | 11 | const handleSubmit = async (e) =>{ 12 | e.preventDefault() 13 | console.log('Prihlasuji...', email, password) 14 | 15 | const {data, error} = await supabase.auth.signInWithPassword({ email, password }); 16 | 17 | if (!error && data) { 18 | console.log(data) 19 | } 20 | 21 | if (error) { 22 | console.log(error) 23 | } 24 | } 25 | 26 | return ( 27 | <> 28 |

Přihlášení

29 | 30 |
31 | 32 |
33 | 34 | setEmail(e.target.value)} 38 | /> 39 |
40 | 41 |
42 | 43 | setPassword(e.target.value)} 47 | /> 48 |
49 | 50 | 51 | 52 |

Ještě nemáš účet? Zaregistruj se.

53 |
54 | 55 | ) 56 | } 57 | 58 | export default Login -------------------------------------------------------------------------------- /src/components/Register.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | 3 | import {supabase} from './../supabase/supabase-client' 4 | 5 | export function Register() { 6 | const [email, setEmail] = useState('') 7 | const [password, setPassword] = useState('') 8 | const [firstName, setFirstName] = useState('') 9 | const [lastName, setLastName] = useState('') 10 | const [age, setAge] = useState('') 11 | 12 | const [message, setMessage] = useState(null) 13 | 14 | const handleSubmit = async (e) =>{ 15 | e.preventDefault() 16 | 17 | setMessage(null) 18 | 19 | if (email === '' || password === '') { 20 | return 21 | } 22 | 23 | const { data, error } = await supabase.auth.signUp({ 24 | email, 25 | password, 26 | options: { 27 | data: { 28 | firstName, 29 | lastName, 30 | age, 31 | } 32 | } 33 | }); 34 | 35 | if (!error && data) { 36 | setMessage("Registration Successful. Check your email to confirm your account"); 37 | console.log(data) 38 | } 39 | 40 | if (error) { 41 | console.log(error) 42 | } 43 | 44 | } 45 | 46 | return ( 47 | <> 48 |

Registrace

49 | 50 | {message &&

{message}

} 51 | 52 |
53 | 54 |
55 | 56 | setEmail(e.target.value)} 60 | /> 61 |
62 | 63 |
64 | 65 | setPassword(e.target.value)} 69 | /> 70 |
71 | 72 |
73 | 74 |
75 | 76 | setFirstName(e.target.value)} 80 | /> 81 |
82 | 83 |
84 | 85 | setLastName(e.target.value)} 89 | /> 90 |
91 | 92 |
93 | 94 | setAge(e.target.value)} 98 | /> 99 |
100 | 101 | 102 |
103 | 104 | ) 105 | } 106 | 107 | export default Register; --------------------------------------------------------------------------------