From ba4d0bc7ef4874edd5a9034895f4f2eb20eb8d93 Mon Sep 17 00:00:00 2001 From: Adrito-M Date: Tue, 5 Jul 2022 19:29:45 +0530 Subject: [PATCH 1/5] basic functionality added --- components/AddTask.js | 34 ++++++++++++++---- components/LoginForm.js | 30 ++++++++++++---- components/Nav.js | 9 ++--- components/TodoListItem.js | 63 +++++++++++++++++++-------------- context/auth.js | 16 ++++++--- middlewares/auth_required.js | 6 ++-- middlewares/no_auth_required.js | 6 ++-- pages/index.js | 45 ++++++++++++++++++----- pages/login.js | 12 +++++++ pages/register.js | 10 ++++++ 10 files changed, 169 insertions(+), 62 deletions(-) diff --git a/components/AddTask.js b/components/AddTask.js index 9652adb..e4f5968 100644 --- a/components/AddTask.js +++ b/components/AddTask.js @@ -1,17 +1,37 @@ -export default function AddTask() { - const addTask = () => { - /** - * @todo Complete this function. - * @todo 1. Send the request to add the task to the backend server. - * @todo 2. Add the task in the dom. - */ +import axios from "../utils/axios" +import { useState } from "react" +import { useAuth } from "../context/auth" + +export default function AddTask({tasks, setTasks}) { + const {token} = useAuth() + const [_title, setTitle] = useState('') + + const addTask = async () => { + await axios({ + method: 'POST', + url: 'todo/create/', + headers: {Authorization: `Token ${token}`}, + data: {title: _title} + }) + + const newTask = await axios({ + method: 'GET', + url: 'todo/', + headers: {Authorization: `token ${token}`} + }).then(res => res.data.pop()) + + setTasks([...tasks, newTask]) + setTitle('') } + return (
setTitle(e.target.value)} />
- + } ) diff --git a/components/TodoListItem.js b/components/TodoListItem.js index 7965f3b..6b440b5 100644 --- a/components/TodoListItem.js +++ b/components/TodoListItem.js @@ -1,27 +1,36 @@ /* eslint-disable @next/next/no-img-element */ -export default function TodoListItem() { - const editTask = (id) => { - /** - * @todo Complete this function. - * @todo 1. Update the dom accordingly - */ +import { useState } from "react" +import { useAuth } from "../context/auth" +import axios from "../utils/axios" + +export default function TodoListItem({title, id, index, tasks, setTasks}) { + const {token} = useAuth() + const [editing, setEditing] = useState(false) + const [_title, setTitle] = useState(title) + + const editTask = () => { + setEditing(true) } - const deleteTask = (id) => { - /** - * @todo Complete this function. - * @todo 1. Send the request to delete the task to the backend server. - * @todo 2. Remove the task from the dom. - */ + const deleteTask = () => { + axios({ + method: 'DELETE', + url: `todo/${id}/`, + headers: {Authorization: `token ${token}`} + }) + .then(setTasks(tasks.filter(task => task.id !== id))) } - const updateTask = (id) => { - /** - * @todo Complete this function. - * @todo 1. Send the request to update the task to the backend server. - * @todo 2. Update the task in the dom. - */ + const updateTask = () => { + axios({ + method: 'PUT', + url: `todo/${id}/`, + headers: {Authorization: `token ${token}`}, + data: {title: _title} + }) + .then(setTasks([...tasks.slice(0, index), {title: title, id: id}, ...tasks.slice(index+1)])) + .then(setEditing(false)) } return ( @@ -30,26 +39,28 @@ export default function TodoListItem() { setTitle(e.target.value)} + value={_title} /> -
+
-
- Sample Task 1 +
+ {_title}
- +
-
} + ) diff --git a/components/Search.js b/components/Search.js new file mode 100644 index 0000000..1aeed9e --- /dev/null +++ b/components/Search.js @@ -0,0 +1,21 @@ +import { useState } from "react" + +export default function Search({ allTasks, setTasks, setQuery }) { + + const onChange = (e) => { + const a = e.target.value + setTasks(allTasks.filter(({title}) => title.toLowerCase().indexOf(a.toLowerCase()) !== -1)) + setQuery(a.toLowerCase()) + } + + return ( +
+ +
+ ) +} \ No newline at end of file diff --git a/components/TodoListItem.js b/components/TodoListItem.js index 6b440b5..a1f0087 100644 --- a/components/TodoListItem.js +++ b/components/TodoListItem.js @@ -4,7 +4,7 @@ import { useState } from "react" import { useAuth } from "../context/auth" import axios from "../utils/axios" -export default function TodoListItem({title, id, index, tasks, setTasks}) { +export default function TodoListItem({title, id, index, actualIndex, tasks, allTasks, setTasks, setAllTasks}) { const {token} = useAuth() const [editing, setEditing] = useState(false) const [_title, setTitle] = useState(title) @@ -19,7 +19,10 @@ export default function TodoListItem({title, id, index, tasks, setTasks}) { url: `todo/${id}/`, headers: {Authorization: `token ${token}`} }) - .then(setTasks(tasks.filter(task => task.id !== id))) + .then(() => { + setTasks(tasks.filter(task => task.id !== id)) + setAllTasks(allTasks.filter(task => task.id !== id)) + }) } const updateTask = () => { @@ -29,8 +32,12 @@ export default function TodoListItem({title, id, index, tasks, setTasks}) { headers: {Authorization: `token ${token}`}, data: {title: _title} }) - .then(setTasks([...tasks.slice(0, index), {title: title, id: id}, ...tasks.slice(index+1)])) - .then(setEditing(false)) + .then(() => { + console.log(index, actualIndex, id, _title, allTasks) + setTasks([...tasks.slice(0, index), {title: _title, id: id}, ...tasks.slice(index+1)]) + setAllTasks([...allTasks.slice(0, actualIndex), {title: _title, id: id}, ...allTasks.slice(actualIndex+1)]) + setEditing(false) + }) } return ( diff --git a/pages/index.js b/pages/index.js index 6e727c5..0849948 100644 --- a/pages/index.js +++ b/pages/index.js @@ -6,40 +6,45 @@ import { useAuth } from '../context/auth' import { auth_required } from '../middlewares/auth_required' import { useRouter } from 'next/router' import { data } from 'autoprefixer' +import Search from '../components/Search' export default function Home() { const route = useRouter() const { token } = useAuth() const [tasks, setTasks] = useState([]) + const [allTasks, setAllTasks] = useState([]) + const [query, setQuery] = useState('') useEffect(() => { auth_required(token, route) getTasks() },[]) - const index = (id, data) => data.findIndex(task => task.id === id) - async function getTasks() { const {data} = await axios({ method: 'GET', url: 'todo/', headers: {Authorization: `token ${token}`} }) - setTasks(data) - } - - function onAddTask(id, title) { - setTasks([...tasks, {title: title, id: id}]) + setTasks(Array.from(data)) + setAllTasks(Array.from(data)) } - return (
+ + setAllTasks={setAllTasks} + query={query} + />
    Available Tasks @@ -50,8 +55,11 @@ export default function Home() { id={id} key={id} index={index} + actualIndex={allTasks.findIndex((task) => task.id === id)} tasks={tasks} + allTasks={allTasks} setTasks={setTasks} + setAllTasks={setAllTasks} /> )}
From 65c1ae33eb20ce85e62b0e1c13710fb8f1c892ec Mon Sep 17 00:00:00 2001 From: Adrito-M Date: Wed, 6 Jul 2022 18:26:53 +0530 Subject: [PATCH 3/5] animation added --- components/TodoListItem.js | 1 - package.json | 1 + pages/index.js | 33 +++++++++++++++++++-------------- styles/globals.css | 22 ++++++++++++++++++++++ yarn.lock | 36 +++++++++++++++++++++++++++++++++++- 5 files changed, 77 insertions(+), 16 deletions(-) diff --git a/components/TodoListItem.js b/components/TodoListItem.js index a1f0087..2113ce7 100644 --- a/components/TodoListItem.js +++ b/components/TodoListItem.js @@ -33,7 +33,6 @@ export default function TodoListItem({title, id, index, actualIndex, tasks, allT data: {title: _title} }) .then(() => { - console.log(index, actualIndex, id, _title, allTasks) setTasks([...tasks.slice(0, index), {title: _title, id: id}, ...tasks.slice(index+1)]) setAllTasks([...allTasks.slice(0, actualIndex), {title: _title, id: id}, ...allTasks.slice(actualIndex+1)]) setEditing(false) diff --git a/package.json b/package.json index 98b7437..e3aa1d2 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "react": "17.0.2", "react-cookie": "^4.0.3", "react-dom": "17.0.2", + "react-transition-group": "^4.4.2", "tailwindcss": "^2.2.2" }, "devDependencies": { diff --git a/pages/index.js b/pages/index.js index 0849948..57e87f9 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,12 +1,13 @@ import TodoListItem from '../components/TodoListItem' import AddTask from '../components/AddTask' -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import axios from '../utils/axios' import { useAuth } from '../context/auth' import { auth_required } from '../middlewares/auth_required' import { useRouter } from 'next/router' -import { data } from 'autoprefixer' +// import { data } from 'autoprefixer' import Search from '../components/Search' +import { CSSTransition, TransitionGroup } from 'react-transition-group' export default function Home() { const route = useRouter() @@ -46,22 +47,26 @@ export default function Home() { query={query} />
    - + Available Tasks + {tasks.map(({title, id}, index) => - task.id === id)} - tasks={tasks} - allTasks={allTasks} - setTasks={setTasks} - setAllTasks={setAllTasks} - /> + + task.id === id)} + tasks={tasks} + allTasks={allTasks} + setTasks={setTasks} + setAllTasks={setAllTasks} + /> + )} +
diff --git a/styles/globals.css b/styles/globals.css index 872cd43..8c03a52 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -22,3 +22,25 @@ .todo-task { max-width: 260px; } + +.item-exit { + opacity: 1; + transform: scale(1); +} + +.item-exit-active { + opacity: 0.5; + transform: scale(0.5); + transition: all 500ms ease; +} + +.item-enter { + opacity: 0.5; + transform: scale(0.5); +} + +.item-enter-active { + opacity: 1; + transform: scale(1); + transition: all 500ms ease; +} diff --git a/yarn.lock b/yarn.lock index 11dbcb7..a58e0e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -52,6 +52,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580" + integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/types@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" @@ -1024,6 +1031,14 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-helpers@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + domain-browser@4.19.0: version "4.19.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.19.0.tgz#1093e17c0a17dbd521182fe90d49ac1370054af1" @@ -2676,6 +2691,15 @@ prop-types@15.7.2, prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.8.1" +prop-types@^15.6.2: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" @@ -2793,7 +2817,7 @@ react-is@17.0.2: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-is@^16.7.0, react-is@^16.8.1: +react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -2803,6 +2827,16 @@ react-refresh@0.8.3: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== +react-transition-group@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470" + integrity sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react@17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" From 6c36fdb1ee29fcd7bc15201106bb96bc68e2b922 Mon Sep 17 00:00:00 2001 From: Adrito-M Date: Wed, 6 Jul 2022 18:35:16 +0530 Subject: [PATCH 4/5] minor bug fixes --- .eslintrc | 2 +- pages/register.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index a2ceebe..dffe840 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,3 +1,3 @@ { - "extends": ["next/babel", "next/core-web-vitals"] + "extends": ["next"] } diff --git a/pages/register.js b/pages/register.js index d38df64..a6a278d 100644 --- a/pages/register.js +++ b/pages/register.js @@ -1,5 +1,7 @@ +import { useRouter } from 'next/router' import { useEffect } from 'react' import RegisterForm from '../components/RegisterForm' +import { useAuth } from '../context/auth' import { no_auth_required } from '../middlewares/no_auth_required' export default function Register() { From b668d93ab6c171b46e7627e33103d69d7f35a327 Mon Sep 17 00:00:00 2001 From: Adrito-M Date: Sun, 10 Jul 2022 20:25:31 +0530 Subject: [PATCH 5/5] toast notifications added --- components/AddTask.js | 48 +++++++++++++++++++++++++++++- components/LoginForm.js | 39 +++++++++++++++++++++++-- components/RegisterForm.js | 60 +++++++++++++++++++++++++++++++++----- components/TodoListItem.js | 59 +++++++++++++++++++++++++++++++++++++ context/auth.js | 12 ++++++++ package.json | 1 + pages/_app.js | 3 ++ pages/index.js | 1 - yarn.lock | 12 ++++++++ 9 files changed, 224 insertions(+), 11 deletions(-) diff --git a/components/AddTask.js b/components/AddTask.js index 8299347..50eed94 100644 --- a/components/AddTask.js +++ b/components/AddTask.js @@ -1,6 +1,8 @@ import axios from "../utils/axios" import { useState } from "react" import { useAuth } from "../context/auth" +import {toast} from "react-toastify" +import 'react-toastify/dist/ReactToastify.css'; export default function AddTask({tasks, allTasks, setTasks, setAllTasks, query}) { const {token} = useAuth() @@ -8,14 +10,58 @@ export default function AddTask({tasks, allTasks, setTasks, setAllTasks, query}) let adding = false const addTask = async () => { if (adding) return - if (_title === '') return + if (_title === '') { + toast.error('Task title cannot be empty', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) + return + } adding = true + toast.info('Adding task', { + position: "bottom-right", + autoClose: 500, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) await axios({ method: 'POST', url: 'todo/create/', headers: {Authorization: `Token ${token}`}, data: {title: _title} + }).catch( () => { + toast.error('Something went wrong', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }); + return }) + toast.success('Task added successfully!', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }); setTitle('') const newTask = await axios({ method: 'GET', diff --git a/components/LoginForm.js b/components/LoginForm.js index 4379dbc..3cbeaeb 100644 --- a/components/LoginForm.js +++ b/components/LoginForm.js @@ -2,21 +2,56 @@ import { useRouter } from "next/router"; import { useState } from "react"; import { useAuth } from "../context/auth"; import axiosInstance from "../utils/axios"; +import {toast} from "react-toastify" +import 'react-toastify/dist/ReactToastify.css'; export default function LoginForm() { const auth = useAuth() const route = useRouter() const login = () => { - if (username === '' || password === '') return + if (username === '' || password === '') { + toast.error('Username or Password cannot be empty', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) + return + } axiosInstance.post('auth/login/',{username: username, password: password}) .then(ret => ret.data.token) .then((token) => { auth.setToken(token) + toast.success('Login successful', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) route.push('/') }) - .catch(err => {console.log(err)}) + .catch(() => { + toast.error('Invalid username or password', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) + }) } const [username, setUsername] = useState('') diff --git a/components/RegisterForm.js b/components/RegisterForm.js index a6ef2e3..a145fbc 100644 --- a/components/RegisterForm.js +++ b/components/RegisterForm.js @@ -2,6 +2,8 @@ import React, { useState } from 'react' import axios from '../utils/axios' import { useAuth } from '../context/auth' import { useRouter } from 'next/router' +import {toast} from "react-toastify" +import 'react-toastify/dist/ReactToastify.css'; export default function Register() { const { setToken } = useAuth() @@ -27,11 +29,29 @@ export default function Register() { username === '' || password === '' ) { - console.log('Please fill all the fields correctly.') + toast.error('Please fill all the fields correctly.', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) return false } if (!/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) { - console.log('Please enter a valid email address.') + toast.error('Please enter a valid email address.', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) return false } return true @@ -43,7 +63,16 @@ export default function Register() { if ( registerFieldsAreValid(firstName, lastName, email, username, password) ) { - console.log('Please wait...') + toast.info('Please wait...', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) const dataForApiRequest = { name: firstName + ' ' + lastName, @@ -56,14 +85,31 @@ export default function Register() { 'auth/register/', dataForApiRequest, ) - .then(function ({ data, status }) { + .then(function ({ data }) { setToken(data.token) router.push('/') + toast.success('Login successful', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) }) .catch(function (err) { - console.log( - 'An account using same email or username is already created' - ) + toast.warn('An account using same email or username is already created', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) }) } } diff --git a/components/TodoListItem.js b/components/TodoListItem.js index 2113ce7..449e897 100644 --- a/components/TodoListItem.js +++ b/components/TodoListItem.js @@ -3,6 +3,8 @@ import { useState } from "react" import { useAuth } from "../context/auth" import axios from "../utils/axios" +import {toast} from "react-toastify" +import 'react-toastify/dist/ReactToastify.css'; export default function TodoListItem({title, id, index, actualIndex, tasks, allTasks, setTasks, setAllTasks}) { const {token} = useAuth() @@ -20,12 +22,47 @@ export default function TodoListItem({title, id, index, actualIndex, tasks, allT headers: {Authorization: `token ${token}`} }) .then(() => { + toast.success('Task deleted successfully', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) setTasks(tasks.filter(task => task.id !== id)) setAllTasks(allTasks.filter(task => task.id !== id)) }) + .catch(() => { + toast.error('Something went wrong', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) + }) } const updateTask = () => { + if (_title === '') { + toast.error('Task title cannot be empty', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) + return + } axios({ method: 'PUT', url: `todo/${id}/`, @@ -33,10 +70,32 @@ export default function TodoListItem({title, id, index, actualIndex, tasks, allT data: {title: _title} }) .then(() => { + toast.success('Task updated successfully', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) setTasks([...tasks.slice(0, index), {title: _title, id: id}, ...tasks.slice(index+1)]) setAllTasks([...allTasks.slice(0, actualIndex), {title: _title, id: id}, ...allTasks.slice(actualIndex+1)]) setEditing(false) }) + .catch(() => { + toast.error('Something went wrong', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) + }) } return ( diff --git a/context/auth.js b/context/auth.js index 6065fb4..8dc5a0e 100644 --- a/context/auth.js +++ b/context/auth.js @@ -2,6 +2,8 @@ import { useEffect, useState, useContext, createContext } from 'react' import { useCookies } from 'react-cookie' import axios from '../utils/axios' import { useRouter } from 'next/router' +import {toast} from "react-toastify" +import 'react-toastify/dist/ReactToastify.css'; export const AuthContext = createContext({}) @@ -24,6 +26,16 @@ export const AuthProvider = ({ children }) => { const logout = () => { deleteToken() + toast.warn('You have been logged out', { + position: "bottom-right", + autoClose: 2000, + hideProgressBar: true, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "colored", + }) router.push('/login') } diff --git a/package.json b/package.json index e3aa1d2..d15a3aa 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "react": "17.0.2", "react-cookie": "^4.0.3", "react-dom": "17.0.2", + "react-toastify": "^9.0.5", "react-transition-group": "^4.4.2", "tailwindcss": "^2.2.2" }, diff --git a/pages/_app.js b/pages/_app.js index 9fc71da..d96b19a 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -1,10 +1,13 @@ import '../styles/globals.css' import { AuthProvider } from '../context/auth' import Nav from '../components/Nav' +import { ToastContainer } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; function MyApp({ Component, pageProps }) { return ( +