├── .eslintrc.json
├── .gitignore
├── README.md
├── components
├── button.js
├── errors.js
├── input.js
└── label.js
├── lib
├── axios.js
└── useAuth.js
├── next.config.js
├── package-lock.json
├── package.json
├── pages
├── _app.js
├── _document.js
├── index.js
├── login.js
├── offices
│ └── [id].js
├── profile.js
└── register.js
├── postcss.config.js
├── public
├── favicon.ico
└── vercel.svg
└── tailwind.config.js
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2 |
3 | ## Getting Started
4 |
5 | First, run the development server:
6 |
7 | ```bash
8 | npm run dev
9 | # or
10 | yarn dev
11 | ```
12 |
13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
14 |
15 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
16 |
17 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
18 |
19 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
20 |
21 | ## Learn More
22 |
23 | To learn more about Next.js, take a look at the following resources:
24 |
25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
27 |
28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
29 |
30 | ## Deploy on Vercel
31 |
32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
33 |
34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
35 |
--------------------------------------------------------------------------------
/components/button.js:
--------------------------------------------------------------------------------
1 | export default function Button({ type = 'submit', className = '', ...props }) {
2 | return (
3 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/components/errors.js:
--------------------------------------------------------------------------------
1 | export default function Label({ errors = [], ...props }) {
2 | return (
3 | <>
4 | {errors.length > 0 && (
5 |
6 |
7 | Whoops! Something went wrong.
8 |
9 |
10 |
11 | {errors.map(error => (
12 | - {error}
13 | ))}
14 |
15 |
16 | )}
17 | >
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/components/input.js:
--------------------------------------------------------------------------------
1 | export default function Input({ disabled = false, className = '', ...props }) {
2 | return (
3 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/components/label.js:
--------------------------------------------------------------------------------
1 | export default function Label({ children, className = '', ...props }) {
2 | return (
3 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/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 | });
--------------------------------------------------------------------------------
/lib/useAuth.js:
--------------------------------------------------------------------------------
1 | import useSWR from 'swr'
2 | import axios from './axios'
3 | import {useRouter} from 'next/router'
4 | import {useEffect, useState} from 'react'
5 |
6 | export default function useAuth({middleware} = {}) {
7 | const router = useRouter()
8 |
9 | const [isLoading, setIsLoading] = useState(true);
10 |
11 | useEffect(() => {
12 | if (user || error) {
13 | setIsLoading(false);
14 | }
15 |
16 | if (middleware == 'guest' && user) router.push('/')
17 | if (middleware == 'auth' && !user && error) router.push('/login')
18 | })
19 |
20 | const {data: user, error, mutate} = useSWR('/user',
21 | () => axios.get('/user').then(response => response.data.data)
22 | )
23 |
24 | const csrf = () => axios.get('/sanctum/csrf-cookie')
25 |
26 | const login = async ({setErrors, ...props}) => {
27 | setErrors([])
28 |
29 | await csrf()
30 |
31 | axios
32 | .post('/login', props)
33 | .then(() => mutate() && router.push('/'))
34 | .catch(error => {
35 | if (error.response.status != 422) throw error
36 |
37 | setErrors(Object.values(error.response.data.errors).flat())
38 | })
39 | }
40 |
41 | const logout = async () => {
42 | await axios.post('/logout')
43 |
44 | mutate(null)
45 |
46 | router.push('/login')
47 | }
48 |
49 | return {
50 | user,
51 | csrf,
52 | login,
53 | logout,
54 | isLoading
55 | }
56 | }
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | reactStrictMode: true,
3 | images: {
4 | domains: [],
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nextapp",
3 | "private": true,
4 | "scripts": {
5 | "dev": "next dev",
6 | "build": "next build",
7 | "start": "next start",
8 | "lint": "next lint"
9 | },
10 | "dependencies": {
11 | "next": "12.0.4",
12 | "react": "17.0.2",
13 | "react-dom": "17.0.2"
14 | },
15 | "devDependencies": {
16 | "autoprefixer": "^10.4.0",
17 | "eslint": "7.32.0",
18 | "eslint-config-next": "12.0.4",
19 | "postcss": "^8.3.11",
20 | "tailwindcss": "^2.2.19",
21 | "swr": "^1.0.1",
22 | "axios": "^0.24.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/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 |
44 |
45 |
46 |
47 |
48 | >
49 | )
50 | }
51 |
52 | export default MyApp
53 |
--------------------------------------------------------------------------------
/pages/_document.js:
--------------------------------------------------------------------------------
1 | import Document, { Html, Head, Main, NextScript } from 'next/document'
2 |
3 | class MyDocument extends Document {
4 | render() {
5 | return (
6 |
7 |
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | )
19 | }
20 | }
21 |
22 | export default MyDocument
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import Head from 'next/head'
2 | import Link from 'next/link'
3 | import axios from '../lib/axios'
4 |
5 |
6 | export default function Home({offices}) {
7 | return (
8 | <>
9 |
10 | ergodnc
11 |
12 |
13 | {offices.map((office, index) => (
14 |
15 |
16 |

17 |
18 |
19 |
20 |
21 |
{office.title}
22 | ${office.price_per_day / 100} per day
23 |
24 |
25 | {office.description}
26 |
27 |
28 |
More details...
29 |
30 |
31 |
32 | ))}
33 | >
34 | )
35 | }
36 |
37 | export async function getStaticProps() {
38 | const response = await axios.get('/offices');
39 |
40 | return {
41 | props: {
42 | offices: response.data.data
43 | },
44 | }
45 | }
--------------------------------------------------------------------------------
/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 |
97 | >
98 | )
99 | }
100 |
--------------------------------------------------------------------------------
/pages/offices/[id].js:
--------------------------------------------------------------------------------
1 | import Head from 'next/head'
2 | import Link from 'next/link'
3 | import Button from '../../components/button'
4 | import axios from '../../lib/axios'
5 |
6 |
7 | export default function Office({office}) {
8 | return (
9 | <>
10 |
11 | ergodnc — {office.title}
12 |
13 |
14 |
15 |
16 |

17 |
18 |
19 |
20 |
21 |
{office.title}
22 | ${office.price_per_day / 100} per day
23 |
24 |
25 | {office.description}
26 |
27 |
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/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 |
95 | >
96 | )
97 | }
98 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/themsaid/ergodnc-nextjs/6ff68c43e3c01b6ad496442020dc1cccd267cf81/public/favicon.ico
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------