diff --git a/README.md b/README.md
index d93fd98..d4c30ef 100644
--- a/README.md
+++ b/README.md
@@ -98,7 +98,7 @@ Here is the breakdown of the points related to each task.
Judging would be done on the basis of your implementation and authenticity.
## Deadline
-You'll have a week to complete this task. Hence, the deadline of this task is **26th June, 2022** i.e. till the end of this month.
+You'll have a week to complete this task. Hence, the deadline of this task is **26th June, 2022**.
## Submission
* Follow the instructions to setup this project.
diff --git a/components/AddTask.js b/components/AddTask.js
index 9652adb..349b4ba 100644
--- a/components/AddTask.js
+++ b/components/AddTask.js
@@ -1,25 +1,70 @@
-export default function AddTask() {
+import { useState } from "react";
+import axios from "../utils/axios";
+import { useAuth } from "../context/auth";
+import { API_URL } from "../utils/constants";
+import {
+ displayErrorToast,
+ displaySuccessToast,
+ displayWarningToast,
+} from "../pages/toast";
+import TodoListItem from "../components/TodoListItem";
+
+export default function AddTask(props) {
+ /**
+ * @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.
+ */
+
+ const { token } = useAuth();
+ const [task, setTask] = useState("");
+
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.
- */
- }
+ if (task == "") {
+ displayWarningToast("Task title is required!");
+ return;
+ } else {
+ const dataForApiRequest = {
+ title: task,
+ };
+ axios({
+ headers: {
+ Authorization: "Token " + token,
+ },
+ url: API_URL + "todo/create/",
+ method: "POST",
+ data: dataForApiRequest,
+ })
+ .then((res) => {
+ setTask("");
+ props.renderTasks();
+
+ displaySuccessToast("Task added successfully");
+ })
+ .catch(function (err) {
+ displayErrorToast("Error!! Task could not be added!");
+ });
+ }
+ };
+
return (
-
-
-
- Add Task
-
+
- )
+ );
}
diff --git a/components/LoginForm.js b/components/LoginForm.js
index fa28f9e..a3ec611 100644
--- a/components/LoginForm.js
+++ b/components/LoginForm.js
@@ -1,4 +1,37 @@
+import React from "react";
+import axios from "../utils/axios";
+import { API_URL } from "../utils/constants";
+import { useAuth } from "../context/auth";
+import { useRouter } from "next/router";
+import { no_auth_required } from "../middlewares/no_auth_required";
+import { ToastContainer, toast } from "react-toastify";
+import "react-toastify/dist/ReactToastify.css";
+import {
+ displayErrorToast,
+ displaySuccessToast,
+ displayWarningToast,
+} from "../pages/toast";
+
export default function RegisterForm() {
+ no_auth_required();
+ const router = useRouter();
+ const { setToken } = useAuth();
+
+ const [loginData, setLoginData] = React.useState({
+ usernameInput: "",
+ passwordInput: "",
+ });
+
+ function handleChange(e) {
+ const { name, value } = e.target;
+ setLoginData((prev) => {
+ return {
+ ...prev,
+ [name]: value,
+ };
+ });
+ }
+
const login = () => {
/***
* @todo Complete this function.
@@ -6,38 +39,81 @@ export default function RegisterForm() {
* @todo 2. Fetch the auth token from backend and login the user.
* @todo 3. Set the token in the context (See context/auth.js)
*/
- }
+
+ const inputData = {
+ username: loginData.usernameInput,
+ password: loginData.passwordInput,
+ };
+
+ if (inputData.username == "" || inputData.password == "") {
+ displayWarningToast("Please fill all required fields!");
+ return;
+ }
+
+ axios({
+ url: API_URL + "auth/login/",
+ method: "POST",
+ data: inputData,
+ })
+ .then((res) => {
+ displaySuccessToast("User logged in successfully");
+ const token = res.data.token;
+ setToken(token);
+ router.push("LOGIN", "/");
+ })
+ .catch(function (err) {
+ displayErrorToast("Invalid credentials! Please try again.");
+ setLoginData({
+ usernameInput: "",
+ passwordInput: "",
+ });
+ });
+ };
return (
-
-
-
-
Login
-
-
-
-
-
- Login
-
+ <>
+
-
- )
+
+ >
+ );
}
diff --git a/components/Nav.js b/components/Nav.js
index e03cb0f..23c9362 100644
--- a/components/Nav.js
+++ b/components/Nav.js
@@ -1,62 +1,113 @@
/* eslint-disable jsx-a11y/alt-text */
/* eslint-disable @next/next/no-img-element */
-import Link from 'next/link'
-import { useAuth } from '../context/auth'
+import Link from "next/link";
+import { useAuth } from "../context/auth";
+import TaskIcon from "@mui/icons-material/Task";
+import LoginIcon from "@mui/icons-material/Login";
+import HowToRegIcon from "@mui/icons-material/HowToReg";
+import LightModeIcon from "@mui/icons-material/LightMode";
+import DarkModeIcon from "@mui/icons-material/DarkMode";
+import LogoutIcon from "@mui/icons-material/Logout";
+import useDarkMode from "../pages/useDarkMode";
/**
*
* @todo Condtionally render login/register and Profile name in NavBar
*/
export default function Nav() {
- const { logout, profileName, avatarImage } = useAuth()
-
+ const { logout, profileName, avatarImage, token } = useAuth();
+ const [darkTheme, setDarkTheme] = useDarkMode();
+ const ThemeIcon = () => {
+ const handleMode = () => setDarkTheme(!darkTheme);
+ return (
+
+ {darkTheme ? (
+
+ ) : (
+
+ )}
+
+ );
+ };
return (
-
-
-
-
-
- Login
-
-
- Register
-
-
-
-
-
-
- {profileName}
-
-
-
-
-
-
-
- )
+ ) : (
+
+
+
+
+
+
+
+
+
+ {token === undefined || token === null ? null : profileName}
+
+
+
+
+
+
+
+
+ )}
+
+
+
+ );
}
diff --git a/components/RegisterForm.js b/components/RegisterForm.js
index a6ef2e3..702f23c 100644
--- a/components/RegisterForm.js
+++ b/components/RegisterForm.js
@@ -1,17 +1,24 @@
-import React, { useState } from 'react'
-import axios from '../utils/axios'
-import { useAuth } from '../context/auth'
-import { useRouter } from 'next/router'
+import React, { useState } from "react";
+import axios from "../utils/axios";
+import { useAuth } from "../context/auth";
+import { useRouter } from "next/router";
+import { ToastContainer, toast } from "react-toastify";
+import "react-toastify/dist/ReactToastify.css";
+import {
+ displaySuccessToast,
+ displayErrorToast,
+ displayWarningToast,
+} from "../pages/toast";
export default function Register() {
- const { setToken } = useAuth()
- const router = useRouter()
+ const { setToken } = useAuth();
+ const router = useRouter();
- const [firstName, setFirstName] = useState('')
- const [lastName, setLastName] = useState('')
- const [email, setEmail] = useState('')
- const [password, setPassword] = useState('')
- const [username, setUsername] = useState('')
+ const [firstName, setFirstName] = useState("");
+ const [lastName, setLastName] = useState("");
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+ const [username, setUsername] = useState("");
const registerFieldsAreValid = (
firstName,
@@ -21,116 +28,123 @@ export default function Register() {
password
) => {
if (
- firstName === '' ||
- lastName === '' ||
- email === '' ||
- username === '' ||
- password === ''
+ firstName === "" ||
+ lastName === "" ||
+ email === "" ||
+ username === "" ||
+ password === ""
) {
- console.log('Please fill all the fields correctly.')
- return false
+ displayWarningToast("Please fill all required fields!");
+ return false;
}
if (!/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) {
- console.log('Please enter a valid email address.')
- return false
+ displayWarningToast("Please enter a valid email address.");
+
+ return false;
}
- return true
- }
+ return true;
+ };
const register = (e) => {
- e.preventDefault()
+ e.preventDefault();
if (
registerFieldsAreValid(firstName, lastName, email, username, password)
) {
- console.log('Please wait...')
-
const dataForApiRequest = {
- name: firstName + ' ' + lastName,
+ name: firstName + " " + lastName,
email: email,
username: username,
password: password,
- }
+ };
- axios.post(
- 'auth/register/',
- dataForApiRequest,
- )
+ axios
+ .post("auth/register/", dataForApiRequest)
.then(function ({ data, status }) {
- setToken(data.token)
- router.push('/')
+ setToken(data.token);
+ router.push("LOGIN", "/");
})
.catch(function (err) {
- console.log(
- 'An account using same email or username is already created'
- )
- })
+ displayErrorToast("Account with same Username already exists!");
+ setUsername("");
+ setPassword("");
+ });
}
- }
+ };
return (
-
-
-
- )
+
+ >
+ );
}
diff --git a/components/TodoListItem.js b/components/TodoListItem.js
index 7965f3b..b39fcb0 100644
--- a/components/TodoListItem.js
+++ b/components/TodoListItem.js
@@ -1,12 +1,41 @@
/* eslint-disable @next/next/no-img-element */
-export default function TodoListItem() {
+import React, { useState } from "react";
+import { useAuth } from "../context/auth";
+import axios from "../utils/axios";
+import { API_URL } from "../utils/constants";
+import {
+ displayErrorToast,
+ displaySuccessToast,
+ displayWarningToast,
+} from "../pages/toast";
+import useDarkMode from "../pages/useDarkMode";
+
+import DeleteIcon from "@mui/icons-material/Delete";
+import ModeEditIcon from "@mui/icons-material/ModeEdit";
+
+export default function TodoListItem(props) {
+ const [task, setTask] = useState(props.task);
+ const { token } = useAuth();
+
+ const [darkTheme, setDarkTheme] = useDarkMode();
+
+ const inputId = "input-button-" + props.id;
+ const doneId = "done-button-" + props.id;
+ const taskId = "task-" + props.id;
+ const taskActionsId = "task-actions-" + props.id;
+
const editTask = (id) => {
/**
* @todo Complete this function.
* @todo 1. Update the dom accordingly
*/
- }
+ document.getElementById("done-button-" + id).classList.remove("hideme");
+ document.getElementById("input-button-" + id).classList.remove("hideme");
+
+ document.getElementById("task-actions-" + id).classList.add("hideme");
+ document.getElementById("task-" + id).classList.add("hideme");
+ };
const deleteTask = (id) => {
/**
@@ -14,7 +43,21 @@ export default function TodoListItem() {
* @todo 1. Send the request to delete the task to the backend server.
* @todo 2. Remove the task from the dom.
*/
- }
+ axios({
+ headers: {
+ Authorization: "Token " + token,
+ },
+ url: API_URL + "todo/" + id + "/",
+ method: "DELETE",
+ })
+ .then(() => {
+ displaySuccessToast("Task deleted successfully!");
+ props.renderTasks();
+ })
+ .catch((err) => {
+ displayErrorToast("Something went wrong!");
+ });
+ };
const updateTask = (id) => {
/**
@@ -22,57 +65,92 @@ export default function TodoListItem() {
* @todo 1. Send the request to update the task to the backend server.
* @todo 2. Update the task in the dom.
*/
- }
+ if (task === "") {
+ displayWarningToast("Task title cannot be empty!");
+ } else {
+ axios({
+ headers: {
+ Authorization: "Token " + token,
+ },
+ url: API_URL + "todo/" + id + "/",
+ method: "PUT",
+ data: {
+ title: task,
+ },
+ })
+ .then(() => {
+ displaySuccessToast("Todo has been successfully updated...");
+ document
+ .getElementById("input-button-" + props.id)
+ .classList.add("hideme");
+ document
+ .getElementById("done-button-" + props.id)
+ .classList.add("hideme");
+ document
+ .getElementById("task-" + props.id)
+ .classList.remove("hideme");
+ document
+ .getElementById("task-actions-" + props.id)
+ .classList.remove("hideme");
+ props.renderTasks();
+ })
+ .catch(function (err) {
+ displayErrorToast("Something went wrong!");
+ });
+ }
+ };
return (
<>
-
+
setTask(e.target.value)}
+ id={inputId}
+ type="text"
+ className="hideme appearance-none dark:bg-gray-500 rounded w-full py-2 px-3 dark:text-gray-100 text-gray-700 leading-tight focus:outline-none focus:ring todo-edit-task-input"
+ placeholder="Edit The Task"
+ value={task}
/>
-