Skip to content

Commit bc95928

Browse files
committed
Next todo app
1 parent 95d6c0a commit bc95928

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3869
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "next/core-web-vitals"
3+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
.pnpm-debug.log*
27+
28+
# local env files
29+
.env*.local
30+
31+
# vercel
32+
.vercel
33+
34+
# typescript
35+
*.tsbuildinfo
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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.tsx`. 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.ts`.
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.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"telemetry": {
3+
"notifiedAt": "1653884454163",
4+
"enabled": false
5+
}
6+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useRouter } from 'next/router';
2+
import { useContext, useEffect } from 'react'
3+
import AuthContext from '../store/auth.context'
4+
import Loading from './Loading';
5+
import Login from './Login';
6+
7+
function AuthCheck({children}: any) {
8+
const {user, loading} = useContext(AuthContext);
9+
const router = useRouter();
10+
11+
useEffect(() => {
12+
if(user && !loading && router.pathname === '/') {
13+
router.replace('/todo');
14+
}
15+
16+
}, [loading]);
17+
18+
19+
if(user && !loading && router.pathname !== '/') {
20+
return children;
21+
}
22+
else if (!user && !loading) {
23+
return <Login/>;
24+
}else {
25+
return <Loading/>;
26+
}
27+
}
28+
29+
export default AuthCheck
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Player } from '@lottiefiles/react-lottie-player';
2+
import Link from 'next/link';
3+
import React, { useEffect, useState } from 'react';
4+
5+
function EmptyTodo({ tab }: any) {
6+
7+
return (
8+
<div className='h-full flex flex-col justify-center items-center md:w-1/2 md:m-auto'>
9+
<Player
10+
autoplay
11+
loop
12+
src="https://assets6.lottiefiles.com/packages/lf20_gctatsbh.json"
13+
style={{ height: '300px', width: '300px' }}
14+
></Player>
15+
<p className='align-middle text-center mt-4 mb-6 px-6'>{tab.message}</p>
16+
{
17+
tab.title === 'In Progress' &&
18+
<Link href="/todo/new-task">
19+
<a className='h-12 w-52 flex items-center justify-center bg-black text-white rounded-md'>
20+
<i className='bi bi-plus-lg mr-2'></i>
21+
<span className='capitalize'>Add new task</span>
22+
</a>
23+
</Link>
24+
}
25+
</div>
26+
);
27+
}
28+
29+
export default EmptyTodo;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Player } from '@lottiefiles/react-lottie-player'
2+
import React from 'react'
3+
4+
function Loading() {
5+
6+
return (
7+
<div className='h-screen w-screen flex flex-col items-center justify-center'>
8+
<Player
9+
autoplay
10+
loop
11+
src="https://assets5.lottiefiles.com/packages/lf20_3gl6z75q.json"
12+
style={{ height: '300px', width: '300px' }}
13+
></Player>
14+
</div>
15+
)
16+
}
17+
18+
export default Loading
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import React from 'react';
2+
import {Player} from '@lottiefiles/react-lottie-player';
3+
import { signInAnonymous, signInWithGoogle } from '../firebase/authentification';
4+
import { useRouter } from 'next/router';
5+
import toast, { Toaster } from 'react-hot-toast';
6+
7+
function Login() {
8+
9+
const router = useRouter();
10+
11+
const LoginWithGoogle = () => {
12+
signInWithGoogle().then(
13+
() => {
14+
router.push('/todo')
15+
}
16+
).catch(
17+
error => {
18+
toast(error.message, {
19+
icon: '⛔️'
20+
});
21+
}
22+
)
23+
}
24+
25+
const LoginAnonymously = () => {
26+
signInAnonymous().then(
27+
() => {
28+
router.push('/todo')
29+
}
30+
).catch(
31+
error => {
32+
toast(error.message, {
33+
icon: '⛔️'
34+
})
35+
}
36+
)
37+
}
38+
39+
return (
40+
<div className='flex flex-col h-full items-center justify-center'>
41+
<p className='font-normal text-5xl mb-6'>todos</p>
42+
<Player
43+
autoplay
44+
loop
45+
src="https://assets5.lottiefiles.com/packages/lf20_ipcfpsml.json"
46+
style={{ height: '300px', width: '300px' }}
47+
></Player>
48+
<p className='text-base my-6'>Work Less, Achieve More</p>
49+
<div className='flex '>
50+
<button className='flex items-center justify-center border-2 py-2 px-6 rounded-md mr-4'
51+
onClick={LoginWithGoogle}
52+
>
53+
<i className='bi bi-google mr-2'></i>
54+
<span>Google</span>
55+
</button>
56+
<button className='bg-black text-white flex items-center justify-center py-2 px-6 rounded-md'
57+
onClick={LoginAnonymously}
58+
>
59+
<i className='bi bi-person mr-2'></i>
60+
<span>Anonymous</span>
61+
</button>
62+
</div>
63+
<Toaster
64+
position="bottom-center"
65+
toastOptions={{
66+
// Define default options
67+
duration: 5000,
68+
style: {
69+
background: '#363636',
70+
color: '#fff',
71+
}
72+
}}
73+
/>
74+
</div>
75+
);
76+
77+
}
78+
79+
export default Login;
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import Link from 'next/link';
2+
import React, { FormEvent, useContext, useRef } from 'react';
3+
import toast, { Toaster } from 'react-hot-toast';
4+
import { addTask } from '../firebase/task.firestore';
5+
import Task from '../models/Task';
6+
import AuthContext from '../store/auth.context';
7+
8+
function NewTodo() {
9+
10+
const {user} = useContext(AuthContext);
11+
let titleRef = useRef(null);
12+
let descriptionRef = useRef(null);
13+
let dueOnRef = useRef(null);
14+
const minDate = new Date().getFullYear() + '-' + (`0${new Date().getMonth() + 1}`.slice(-2)) + '-' + (`0${(new Date().getDate())}`.slice(-2));
15+
16+
function newTask(event: FormEvent) {
17+
event.preventDefault()
18+
19+
const task : Task = {
20+
//@ts-ignore
21+
title: titleRef?.current?.value,
22+
//@ts-ignore
23+
description: descriptionRef?.current?.value,
24+
complete: false,
25+
createdAt: new Date(),
26+
updatedAt: null,
27+
//@ts-ignore
28+
dueAt: new Date(dueOnRef?.current?.value),
29+
uidUser: user.uid,
30+
}
31+
32+
if(task.title.length >= 5 && task.description.length >= 5) {
33+
addTask(task).then(
34+
() => {
35+
toast.success('Task Added', {
36+
icon: '✅'
37+
})
38+
//@ts-ignore
39+
titleRef?.current?.value = '';
40+
//@ts-ignore
41+
descriptionRef?.current?.value = '';
42+
//@ts-ignore
43+
dueOnRef?.current?.value = '';
44+
}
45+
)
46+
}else {
47+
toast('An error occured in the form', {
48+
icon: '⛔️'
49+
})
50+
}
51+
52+
}
53+
54+
return (
55+
<div className='flex flex-col px-6 py-4 md:w-1/2 md:m-auto'>
56+
<h3 className='mb-4 text-2xl font-semibold'>
57+
New Task
58+
</h3>
59+
<form className='flex flex-col' onSubmit={newTask}>
60+
<label className='mb-2 text-[#383c43]' htmlFor="title">Title</label>
61+
<input ref={titleRef} minLength={5} required={true} className='border border-[#404647] px-3 mb-4 h-12 outline-none' placeholder='Mention the title of your task.' type="text" name="title" id="title" />
62+
<label className='mb-2 text-[#383c43]' htmlFor="description">Description</label>
63+
<textarea ref={descriptionRef} minLength={5} required={true} className='border border-[#404647] p-3 outline-none border-3 resize-none mb-4' name="description" id="description" cols={25} rows={10} placeholder="Describe your task here, it's useful !">
64+
</textarea>
65+
<div className='flex'>
66+
<label htmlFor='dueOn' className='mr-3'>Due On</label>
67+
<input ref={dueOnRef} min={minDate} required={true} type="date" name="due" id="dueOn" className='border border-[#404647] px-3 mb-4 h-12 outline-none w-full' />
68+
</div>
69+
<button type={'submit'} className='py-3 bg-black text-white rounded-md mb-4'>Save</button>
70+
</form>
71+
<Link href={'/todo'}>
72+
<a className='py-3 border rounded-md text-center'>
73+
Cancel
74+
</a>
75+
</Link>
76+
<Toaster
77+
position="top-right"
78+
toastOptions={{
79+
// Define default options
80+
duration: 5000
81+
}}
82+
/>
83+
</div>
84+
)
85+
}
86+
87+
export default NewTodo;

0 commit comments

Comments
 (0)