├── .eslintrc.json ├── public ├── favicon.ico └── vercel.svg ├── next.config.js ├── postcss.config.js ├── lib ├── axios.js └── useAuth.js ├── components ├── label.js ├── input.js ├── button.js └── errors.js ├── tailwind.config.js ├── .gitignore ├── package.json ├── pages ├── _document.js ├── index.js ├── offices │ └── [id].js ├── _app.js ├── profile.js ├── register.js └── login.js └── README.md /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/themsaid/ergodnc-nextjs/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | reactStrictMode: true, 3 | images: { 4 | domains: [], 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /lib/axios.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export default axios.create({ 4 | baseURL: 'http://api.ergodnc.test', 5 | headers: { 6 | 'X-Requested-With': 'XMLHttpRequest', 7 | }, 8 | withCredentials: true, 9 | }); -------------------------------------------------------------------------------- /components/label.js: -------------------------------------------------------------------------------- 1 | export default function Label({ children, className = '', ...props }) { 2 | return ( 3 | 8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /components/input.js: -------------------------------------------------------------------------------- 1 | export default function Input({ disabled = false, className = '', ...props }) { 2 | return ( 3 | 8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | const defaultTheme = require('tailwindcss/defaultTheme') 2 | 3 | module.exports = { 4 | purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'], 5 | darkMode: false, // or 'media' or 'class' 6 | theme: { 7 | extend: { 8 | fontFamily: { 9 | sans: ['Nunito', ...defaultTheme.fontFamily.sans], 10 | }, 11 | }, 12 | }, 13 | variants: { 14 | extend: {}, 15 | }, 16 | plugins: [], 17 | } 18 | -------------------------------------------------------------------------------- /.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 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /components/button.js: -------------------------------------------------------------------------------- 1 | export default function Button({ type = 'submit', className = '', ...props }) { 2 | return ( 3 | 28 | 29 | 30 | 31 | ) 32 | } 33 | 34 | export async function getStaticPaths() { 35 | const response = await axios.get('/offices'); 36 | 37 | return { 38 | fallback: false, 39 | paths: response.data.data.map(office => ({ 40 | params: {id: office.id.toString()} 41 | })) 42 | }; 43 | } 44 | 45 | export async function getStaticProps({params}) { 46 | const response = await axios.get(`/offices/${params.id}`); 47 | 48 | return { 49 | props: { 50 | office: response.data.data 51 | }, 52 | } 53 | } -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import 'tailwindcss/tailwind.css' 2 | import Link from 'next/link' 3 | import Button from '../components/button' 4 | import useAuth from '../lib/useAuth' 5 | 6 | function MyApp({Component, pageProps}) { 7 | const {user, logout} = useAuth() 8 | 9 | return ( 10 | <> 11 |
12 |
13 |
14 | 15 | 16 |

17 | ergodnc 18 |

19 |
20 | 21 | 22 |
23 | {user ? 24 | <> 25 | Log Out 26 | 27 | Profile 28 | 29 | 30 | : 31 | <> 32 | 33 | Sign In 34 | 35 | 36 | Create Account 37 | 38 | 39 | } 40 |
41 |
42 |
43 |
44 | 45 |
46 | 47 |
48 | 49 | ) 50 | } 51 | 52 | export default MyApp 53 | -------------------------------------------------------------------------------- /pages/profile.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head' 2 | import Link from 'next/link' 3 | import axios from "../lib/axios"; 4 | import useAuth from "../lib/useAuth"; 5 | import useSWR from "swr"; 6 | 7 | let user = { 8 | name: 'Some User' 9 | }; 10 | 11 | 12 | 13 | export default function Profile() { 14 | const {user, isLoading} = useAuth({middleware: 'auth'}) 15 | 16 | const {data: reservations, error, mutate} = useSWR('/reservations', () => 17 | axios.get('/reservations') 18 | .then(response => response.data.data), 19 | ) 20 | 21 | if (isLoading || !user){ 22 | return <>Loading... 23 | } 24 | 25 | return ( 26 | <> 27 | 28 | ergodnc — Account 29 | 30 | 31 |

32 | Hello {user.name}! 33 |

34 | 35 |
36 | Here is a list of your previous reservations! 37 |
38 | 39 | {reservations ? reservations.map((reservation, index) => ( 40 |
41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

{reservation.office.title}

49 | Total ${reservation.price / 100} 50 |
51 |

52 | 53 | From {reservation.start_date.split('T')[0]} To {reservation.end_date.split('T')[0]} 54 | 55 |

56 |

57 | {reservation.office.description} 58 |

59 | 60 | More details... 61 | 62 |
63 |
64 | )) : ''} 65 | 66 | ) 67 | } 68 | -------------------------------------------------------------------------------- /pages/register.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head' 2 | import Link from 'next/link' 3 | import Label from '../components/label' 4 | import Input from '../components/input' 5 | import Button from '../components/button' 6 | import Errors from '../components/errors' 7 | import {useState} from 'react' 8 | 9 | export default function Register() { 10 | const [name, setName] = useState('') 11 | const [email, setEmail] = useState('') 12 | const [password, setPassword] = useState('') 13 | const [password_confirmation, setPasswordConfirmation] = useState('') 14 | const [errors, setErrors] = useState([]) 15 | 16 | const submitForm = async event => { 17 | event.preventDefault() 18 | } 19 | 20 | return ( 21 | <> 22 | 23 | ergodnc — Register 24 | 25 | 26 |
27 | 28 | 29 |
30 |
31 | 32 | 33 | setName(event.target.value)} 39 | required 40 | autoFocus 41 | autoComplete="off" 42 | /> 43 |
44 | 45 |
46 | 47 | 48 | setEmail(event.target.value)} 54 | required 55 | /> 56 |
57 | 58 |
59 | 60 | 61 | setPassword(event.target.value)} 67 | required 68 | /> 69 |
70 | 71 |
72 | 73 | 74 | setPasswordConfirmation(event.target.value)} 80 | required 81 | /> 82 |
83 | 84 |
85 | 86 | 87 | Already registered? 88 | 89 | 90 | 91 | 92 |
93 |
94 |
95 | 96 | ) 97 | } 98 | -------------------------------------------------------------------------------- /pages/login.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head' 2 | import Link from 'next/link' 3 | import Label from '../components/label' 4 | import Input from '../components/input' 5 | import Button from '../components/button' 6 | import Errors from '../components/errors' 7 | import {useState} from 'react' 8 | import useAuth from '../lib/useAuth' 9 | 10 | export default function Login() { 11 | const [email, setEmail] = useState('') 12 | const [password, setPassword] = useState('') 13 | const [remember, setRemember] = useState(false) 14 | const [errors, setErrors] = useState([]) 15 | 16 | const {login, isLoading, user} = useAuth({middleware: 'guest'}) 17 | 18 | const submitForm = async event => { 19 | event.preventDefault() 20 | 21 | login({email, password, remember, setErrors}); 22 | } 23 | 24 | if (isLoading || user) { 25 | return <>Loading... 26 | } 27 | 28 | return ( 29 | <> 30 | 31 | ergodnc — Login 32 | 33 | 34 |
35 | 36 | 37 |
38 |
39 | 40 | 41 | setEmail(event.target.value)} 47 | required 48 | autoFocus 49 | autoComplete="off" 50 | /> 51 |
52 | 53 |
54 | 55 | 56 | setPassword(event.target.value)} 62 | required 63 | autoComplete="current-password" 64 | /> 65 |
66 | 67 |
68 | 84 |
85 | 86 |
87 | 88 | 89 | Forgot your password? 90 | 91 | 92 | 93 | 94 |
95 |
96 |
97 | 98 | ) 99 | } 100 | --------------------------------------------------------------------------------