diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..b338f14
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,34 @@
+name: Build on PR
+
+on:
+ pull_request:
+ branches:
+ - '*'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Use Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: '20'
+
+ - name: Install Dependencies in Frontend
+ run: |
+ cd frontend
+ npm install
+
+ - name: Install Dependencies in Backend
+ run: |
+ cd backend
+ npm install
+
+ - name: Run Frontend Build
+ run: |
+ cd frontend
+ npm run build
+
+
diff --git a/backend/config.js b/backend/config.js
index 45fac5b..04163bf 100644
--- a/backend/config.js
+++ b/backend/config.js
@@ -1,3 +1,3 @@
-const JWT_SECRET = "IAMGAYLOL";
-
-module.exports = JWT_SECRET;
+const JWT_SECRET = "IAMGAYLOL";
+
+module.exports = JWT_SECRET;
diff --git a/backend/db.js b/backend/db.js
index 1763e05..7c29252 100644
--- a/backend/db.js
+++ b/backend/db.js
@@ -1,29 +1,29 @@
-const mongoose = require("mongoose");
-mongoose.connect("mongodb://localhost:27017/basicTodoApp");
-
-const UserSchema = mongoose.Schema({
- firstName: String,
- lastName: String,
- username: String,
- password: String,
- todos: [
- {
- type: mongoose.Schema.Types.ObjectId,
- ref: "Todo",
- },
- ],
-});
-
-const TodoSchema = mongoose.Schema({
- title: String,
- description: String,
- completed: Boolean,
-});
-
-const User = mongoose.model("User", UserSchema);
-const Todo = mongoose.model("Todo", TodoSchema);
-
-module.exports = {
- User,
- Todo,
-};
+const mongoose = require("mongoose");
+mongoose.connect("mongodb://localhost:27017/basicTodoApp");
+
+const UserSchema = mongoose.Schema({
+ firstName: String,
+ lastName: String,
+ username: String,
+ password: String,
+ todos: [
+ {
+ type: mongoose.Schema.Types.ObjectId,
+ ref: "Todo",
+ },
+ ],
+});
+
+const TodoSchema = mongoose.Schema({
+ title: String,
+ description: String,
+ completed: Boolean,
+});
+
+const User = mongoose.model("User", UserSchema);
+const Todo = mongoose.model("Todo", TodoSchema);
+
+module.exports = {
+ User,
+ Todo,
+};
diff --git a/backend/index.js b/backend/index.js
index 254aaa9..fbeb24c 100644
--- a/backend/index.js
+++ b/backend/index.js
@@ -1,18 +1,18 @@
-const express = require("express");
-const PORT = 3000;
-const bodyParser = require("body-parser");
-const userRouter = require("./routes/user");
-const cors = require("cors");
-
-const app = express();
-app.use(cors());
-app.use(bodyParser.json());
-app.use("/user", userRouter);
-
-app.get("/", (req, res) => {
- res.send("Hello World! Welcome to Todo");
-});
-
-app.listen(PORT, () => {
- console.log(`Server is running on port ${PORT}`);
-});
+const express = require("express");
+const PORT = 3000;
+const bodyParser = require("body-parser");
+const userRouter = require("./routes/user");
+const cors = require("cors");
+
+const app = express();
+app.use(cors());
+app.use(bodyParser.json());
+app.use("/user", userRouter);
+
+app.get("/", (req, res) => {
+ res.send("Hello World! Welcome to Todo");
+});
+
+app.listen(PORT, () => {
+ console.log(`Server is running on port ${PORT}`);
+});
diff --git a/backend/middleware/authMiddleware.js b/backend/middleware/authMiddleware.js
index 3c432c4..18d6f4d 100644
--- a/backend/middleware/authMiddleware.js
+++ b/backend/middleware/authMiddleware.js
@@ -1,43 +1,43 @@
-const jwt = require("jsonwebtoken");
-const JWT_SECRET = require("../config");
-
-const authMiddleware = (req, res, next) => {
- const authHeader = req.headers.authorization;
-
- if (!authHeader) {
- return res.status(401).json({
- message: "No Authorization Header Found",
- });
- }
-
- const words = authHeader.split(" ");
-
- if (words[0] !== "Bearer" || words.length !== 2) {
- return res.status(401).json({
- message: "Invalid Token Format",
- });
- }
-
- const token = words[1];
-
- try {
- const decoded = jwt.verify(token, JWT_SECRET);
-
- if (decoded.userId) {
- req.userId = decoded.userId;
- next();
- } else {
- res.status(401).json({
- message: "Invalid Token",
- });
- }
- } catch (error) {
- console.error("The Error is " + error);
- res.status(500).json({
- message: "Some Error Occurred",
- error: error.message,
- });
- }
-};
-
-module.exports = authMiddleware; // Ensure this is correct
+const jwt = require("jsonwebtoken");
+const JWT_SECRET = require("../config");
+
+const authMiddleware = (req, res, next) => {
+ const authHeader = req.headers.authorization;
+
+ if (!authHeader) {
+ return res.status(401).json({
+ message: "No Authorization Header Found",
+ });
+ }
+
+ const words = authHeader.split(" ");
+
+ if (words[0] !== "Bearer" || words.length !== 2) {
+ return res.status(401).json({
+ message: "Invalid Token Format",
+ });
+ }
+
+ const token = words[1];
+
+ try {
+ const decoded = jwt.verify(token, JWT_SECRET);
+
+ if (decoded.userId) {
+ req.userId = decoded.userId;
+ next();
+ } else {
+ res.status(401).json({
+ message: "Invalid Token",
+ });
+ }
+ } catch (error) {
+ console.error("The Error is " + error);
+ res.status(500).json({
+ message: "Some Error Occurred",
+ error: error.message,
+ });
+ }
+};
+
+module.exports = authMiddleware; // Ensure this is correct
diff --git a/backend/middleware/validateMiddleware.js b/backend/middleware/validateMiddleware.js
index 0da043b..3854d39 100644
--- a/backend/middleware/validateMiddleware.js
+++ b/backend/middleware/validateMiddleware.js
@@ -1,48 +1,48 @@
-const zod = require("zod");
-const { default: errorMap } = require("zod/locales/en.js");
-
-const validateMiddleware = (schema) => (req, res, next) => {
- try {
- const result = schema.safeParse(req.body);
- if (!result.success) {
- return res.status(400).json({
- message: "Validation Error",
- errors: result.error.errors.map((err) => ({
- path: err.path.join("."), // Path of the field with the error
- message: err.message, // Error message
- })),
- });
- }
- next();
- } catch (error) {
- return res.status(500).json({
- message: "Internal Server Error",
- error: error.message,
- });
- }
-};
-
-const userSchema = zod.object({
- firstName: zod.string().min(1).max(30), // Should not be empty
- lastName: zod.string().min(1).max(30), // Should not be empty
- username: zod.string().email().min(1), // Should not be empty and must be a valid email
- password: zod.string().min(8).max(20), // Length constraints
-});
-
-const signinSchema = zod.object({
- username: zod.string().email(),
- password: zod.string().min(8).max(20),
-});
-
-const todoSchema = zod.object({
- title: zod.string().min(1, "Title is required").max(30),
- description: zod.string().optional(),
- completed: zod.boolean(),
-});
-
-module.exports = {
- userSchema,
- todoSchema,
- signinSchema,
- validateMiddleware,
-};
+const zod = require("zod");
+const { default: errorMap } = require("zod/locales/en.js");
+
+const validateMiddleware = (schema) => (req, res, next) => {
+ try {
+ const result = schema.safeParse(req.body);
+ if (!result.success) {
+ return res.status(400).json({
+ message: "Validation Error",
+ errors: result.error.errors.map((err) => ({
+ path: err.path.join("."), // Path of the field with the error
+ message: err.message, // Error message
+ })),
+ });
+ }
+ next();
+ } catch (error) {
+ return res.status(500).json({
+ message: "Internal Server Error",
+ error: error.message,
+ });
+ }
+};
+
+const userSchema = zod.object({
+ firstName: zod.string().min(1).max(30), // Should not be empty
+ lastName: zod.string().min(1).max(30), // Should not be empty
+ username: zod.string().email().min(1), // Should not be empty and must be a valid email
+ password: zod.string().min(8).max(20), // Length constraints
+});
+
+const signinSchema = zod.object({
+ username: zod.string().email(),
+ password: zod.string().min(8).max(20),
+});
+
+const todoSchema = zod.object({
+ title: zod.string().min(1, "Title is required").max(30),
+ description: zod.string().optional(),
+ completed: zod.boolean().optional(),
+});
+
+module.exports = {
+ userSchema,
+ todoSchema,
+ signinSchema,
+ validateMiddleware,
+};
diff --git a/backend/routes/user.js b/backend/routes/user.js
index a48e670..6b36b6e 100644
--- a/backend/routes/user.js
+++ b/backend/routes/user.js
@@ -1,209 +1,215 @@
-const { Router } = require("express");
-const router = Router();
-const {
- validateMiddleware,
- userSchema,
- todoSchema,
- signinSchema,
-} = require("../middleware/validateMiddleware");
-const authMiddleware = require("../middleware/authMiddleware");
-const jwt = require("jsonwebtoken");
-const { User, Todo } = require("../db");
-const JWT_SECRET = require("../config");
-
-// Signup Route
-router.post("/signup", validateMiddleware(userSchema), async (req, res) => {
- const { firstName, lastName, username, password } = req.body;
- try {
- const response = await User.findOne({ username });
- if (response) {
- return res.status(400).json({
- message: "User Already Exists",
- });
- }
-
- const newUser = await User.create({
- firstName,
- lastName,
- username,
- password,
- });
-
- const token = jwt.sign({ userId: newUser._id }, JWT_SECRET, {});
-
- return res.status(200).json({
- message: "User Created Successfully",
- success: true,
- token: token,
- });
- } catch (error) {
- console.error("Error during signup:", error); // Log the error details
- return res.status(500).json({
- message: "Some Error Occurred",
- success: false,
- error: error.message, // Include error message in response for debugging
- });
- }
-});
-
-// Signin Route
-router.post("/login", validateMiddleware(signinSchema), async (req, res) => {
- const { username, password } = req.body;
-
- try {
- const response = await User.findOne({ username, password });
- if (!response) {
- return res.status(400).json({
- message: "No User Found with the credentials",
- success: false,
- });
- }
-
- const token = jwt.sign({ userId: response._id }, JWT_SECRET, {});
-
- return res.status(200).json({
- message: "User Signed In Successfully",
- success: true,
- token: token,
- });
- } catch (error) {
- return res.status(500).json({
- message: "Some Error Occurred",
- });
- }
-});
-
-// Get Todos Route
-router.get("/todos", authMiddleware, async (req, res) => {
- const userId = req.userId;
-
- try {
- const user = await User.findById(userId).populate("todos"); // Use userId here
-
- if (!user) {
- return res.status(400).json({
- message: "No User found with todos",
- });
- }
-
- return res.status(200).json({
- todos: user.todos,
- });
- } catch (error) {
- console.error("The error is " + error);
- return res.status(500).json({
- message: "Some Error Occurred",
- error: error.message,
- });
- }
-});
-
-// Add Todo Route
-router.post(
- "/addTodo",
- authMiddleware,
- validateMiddleware(todoSchema),
- async (req, res) => {
- const userId = req.userId; // Corrected to match the field set by authMiddleware
- const { title, description, completed } = req.body;
-
- try {
- const newTodo = await Todo.create({
- title,
- description,
- completed,
- });
-
- const user = await User.findByIdAndUpdate(
- userId,
- { $push: { todos: newTodo._id } },
- { new: true }
- );
-
- if (!user) {
- return res.status(404).json({
- message: "User not found",
- });
- }
-
- // Return a success response
- return res.status(201).json({
- message: "Todo added successfully",
- todo: newTodo,
- });
- } catch (error) {
- return res.status(500).json({
- message: "Some Error Occurred",
- });
- }
- }
-);
-
-// Update Todo Route
-router.put(
- "/updateTodo",
- authMiddleware,
- validateMiddleware(todoSchema),
- async (req, res) => {
- const { id, title, description, completed } = req.body;
-
- try {
- // Create an update object based on which fields are present
- const updateData = {};
- if (title !== undefined) updateData.title = title;
- if (description !== undefined) updateData.description = description;
- if (completed !== undefined) updateData.completed = completed;
-
- const updatedTodo = await Todo.findByIdAndUpdate(id, updateData, {
- new: true,
- });
-
- if (!updatedTodo) {
- return res.status(404).json({ error: "Todo not found" });
- }
-
- res.status(200).json(updatedTodo);
- } catch (error) {
- res.status(500).json({ error: "Failed to update todo" });
- }
- }
-);
-
-router.put("/completeTodo/:id", authMiddleware, async (req, res) => {
- const { id } = req.params; // Now getting id from the URL params
-
- try {
- const updatedTodo = await Todo.findByIdAndUpdate(
- id,
- { completed: true },
- { new: true }
- );
-
- if (!updatedTodo) {
- return res.status(404).json({ error: "Todo not found" });
- }
-
- res.status(200).json(updatedTodo);
- } catch (error) {
- res.status(500).json({ error: "Failed to complete todo" });
- }
-});
-
-// Delete Todo Route
-router.delete("/delete/:id", authMiddleware, async (req, res) => {
- const { id } = req.params; // Extract the todo id from the request body
-
- try {
- const deletedTodo = await Todo.findByIdAndDelete(id); // Find and delete the todo by id
-
- if (!deletedTodo) {
- return res.status(404).json({ error: "Todo not found" });
- }
-
- res.status(200).json({ message: "Todo deleted successfully", deletedTodo });
- } catch (error) {
- res.status(500).json({ error: "Failed to delete todo" });
- }
-});
-
-module.exports = router;
+const { Router } = require("express");
+const router = Router();
+const {
+ validateMiddleware,
+ userSchema,
+ todoSchema,
+ signinSchema,
+} = require("../middleware/validateMiddleware");
+const authMiddleware = require("../middleware/authMiddleware");
+const jwt = require("jsonwebtoken");
+const { User, Todo } = require("../db");
+const JWT_SECRET = require("../config");
+
+// Signup Route
+router.post("/signup", validateMiddleware(userSchema), async (req, res) => {
+ const { firstName, lastName, username, password } = req.body;
+ try {
+ const response = await User.findOne({ username });
+ if (response) {
+ return res.status(400).json({
+ message: "User Already Exists",
+ });
+ }
+
+ const newUser = await User.create({
+ firstName,
+ lastName,
+ username,
+ password,
+ });
+
+ const token = jwt.sign({ userId: newUser._id }, JWT_SECRET, {
+ expiresIn: "1h",
+ });
+
+ return res.status(200).json({
+ message: "User Created Successfully",
+ success: true,
+ token: token,
+ });
+ } catch (error) {
+ console.error("Error during signup:", error); // Log the error details
+ return res.status(500).json({
+ message: "Some Error Occurred",
+ success: false,
+ error: error.message, // Include error message in response for debugging
+ });
+ }
+});
+
+// Signin Route
+router.post("/login", validateMiddleware(signinSchema), async (req, res) => {
+ const { username, password } = req.body;
+
+ try {
+ const response = await User.findOne({ username, password });
+ if (!response) {
+ return res.status(400).json({
+ message: "No User Found with the credentials",
+ success: false,
+ });
+ }
+
+ const token = jwt.sign({ userId: response._id }, JWT_SECRET, {
+ expiresIn: "1h",
+ });
+
+ return res.status(200).json({
+ message: "User Signed In Successfully",
+ success: true,
+ token: token,
+ });
+ } catch (error) {
+ return res.status(500).json({
+ message: "Some Error Occurred",
+ });
+ }
+});
+
+// Get Todos Route
+router.get("/todos", authMiddleware, async (req, res) => {
+ const userId = req.userId;
+
+ try {
+ const user = await User.findById(userId).populate("todos"); // Use userId here
+
+ if (!user) {
+ return res.status(400).json({
+ message: "No User found with todos",
+ });
+ }
+
+ return res.status(200).json({
+ todos: user.todos,
+ });
+ } catch (error) {
+ console.error("The error is " + error);
+ return res.status(500).json({
+ message: "Some Error Occurred",
+ error: error.message,
+ });
+ }
+});
+
+// Add Todo Route
+router.post(
+ "/addTodo",
+ authMiddleware,
+ validateMiddleware(todoSchema),
+ async (req, res) => {
+ const userId = req.userId; // Corrected to match the field set by authMiddleware
+ const { title, description, completed } = req.body;
+
+ try {
+ const newTodo = await Todo.create({
+ title,
+ description,
+ completed,
+ });
+
+ const user = await User.findByIdAndUpdate(
+ userId,
+ { $push: { todos: newTodo._id } },
+ { new: true }
+ );
+
+ if (!user) {
+ return res.status(404).json({
+ message: "User not found",
+ });
+ }
+
+ // Return a success response
+ return res.status(201).json({
+ message: "Todo added successfully",
+ todo: newTodo,
+ });
+ } catch (error) {
+ return res.status(500).json({
+ message: "Some Error Occurred",
+ });
+ }
+ }
+);
+
+// Update Todo Route
+router.put(
+ "/updateTodo/:id",
+ authMiddleware,
+ validateMiddleware(todoSchema),
+ async (req, res) => {
+ const { title, description, completed } = req.body;
+ const { id } = req.params;
+
+ try {
+ // Create an update object based on which fields are present
+ const updateData = {};
+ if (title !== undefined) updateData.title = title;
+ if (description !== undefined) updateData.description = description;
+ if (completed !== undefined) updateData.completed = completed;
+
+ const updatedTodo = await Todo.findByIdAndUpdate(id, updateData, {
+ new: true,
+ });
+
+ if (!updatedTodo) {
+ return res.status(404).json({ error: "Todo not found" });
+ }
+
+ res.status(200).json(updatedTodo);
+ } catch (error) {
+ res.status(500).json({ error: "Failed to update todo" });
+ }
+ }
+);
+
+router.put("/completeTodo/:id", authMiddleware, async (req, res) => {
+ const { id } = req.params;
+ const { completed } = req.body; // Get the completed state from the request body
+
+ try {
+ const updatedTodo = await Todo.findByIdAndUpdate(
+ id,
+ { completed }, // Use the completed state from the request
+ { new: true } // Return the updated document
+ );
+
+ if (!updatedTodo) {
+ return res.status(404).json({ error: "Todo not found" });
+ }
+
+ res.status(200).json(updatedTodo);
+ } catch (error) {
+ res.status(500).json({ error: "Failed to update todo" });
+ }
+});
+
+// Delete Todo Route
+router.delete("/delete/:id", authMiddleware, async (req, res) => {
+ const { id } = req.params; // Extract the todo id from the request body
+
+ try {
+ const deletedTodo = await Todo.findByIdAndDelete(id); // Find and delete the todo by id
+
+ if (!deletedTodo) {
+ return res.status(404).json({ error: "Todo not found" });
+ }
+
+ res.status(200).json({ message: "Todo deleted successfully", deletedTodo });
+ } catch (error) {
+ res.status(500).json({ error: "Failed to delete todo" });
+ }
+});
+
+module.exports = router;
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index dc5b560..624de73 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -6,26 +6,23 @@ import { Login } from "./components/Login";
import { AppBar } from "./components/AppBar";
import { Todos } from "./components/Todos";
import { NewHome } from "./components/NewHome";
+import { TodoRender } from "./context";
function App() {
- console.log("App Rerenders");
-
const token = localStorage.getItem("token");
return (
{error}
} + {successMessage && ( +{successMessage}
+ )} +- The best place to manage your tasks and improve your productivity. -
- -+ The best place to manage your tasks and improve your productivity. +
+ +{todo.description}
-- {todo.completed ? "Completed" : "Not Completed"} -
-