+
+
+
+
+
diff --git a/nodeJS/Learning/05/src/lesson.html b/nodeJS/Learning/05/public/html/lesson.html
similarity index 100%
rename from nodeJS/Learning/05/src/lesson.html
rename to nodeJS/Learning/05/public/html/lesson.html
diff --git a/nodeJS/Learning/05/public/js/todo.js b/nodeJS/Learning/05/public/js/todo.js
index fe78ce6..8ffa0b5 100644
--- a/nodeJS/Learning/05/public/js/todo.js
+++ b/nodeJS/Learning/05/public/js/todo.js
@@ -1,15 +1,51 @@
//fetch: send a url request, client side rendering
-//update the list, by default: fetch uses get
-fetch('/get-todos', {method: 'GET'}). then((response) => {
- response.json(). then((data) => {
- const ol = document.querySelector('ol');
- data.forEach((item) => {
- //Create li
- const li = document.createElement('li');
- //add text to li
- li.textContent = item;
- //add li underneath (child) ol
- ol.appendChild(li);
- })
- });
-});
\ No newline at end of file
+//update the list, by default: fetch uses "get"
+fetch("/get-todos", { method: "GET" }).then((response) => {
+ response.json().then((data) => {
+ const ol = document.querySelector("ol");
+ data.forEach((item) => {
+ //Create li
+ const li = document.createElement("li");
+ //add text to li
+ li.textContent = item;
+
+ // Create button
+ const button = document.createElement("button");
+ button.type = "submit";
+
+ // Add icon to button
+ const icon = document.createElement("i");
+ icon.className = "fa-solid fa-delete-left";
+
+ // Append icon to button
+ button.appendChild(icon);
+
+ // Append button to li
+ li.appendChild(button);
+
+ // Add delete functionality
+ button.addEventListener("click", () => {
+ // Send DELETE request
+ fetch(`/delete-todo`, {
+ method: "DELETE",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ todo: item }),
+ })
+ .then((response) => {
+ if (response.ok) {
+ // Remove the item from the DOM
+ li.remove();
+ } else {
+ console.error("Failed to delete to-do item");
+ }
+ })
+ .catch((error) => console.error("Error:", error));
+ });
+
+ // Append li underneath (child) ol
+ ol.appendChild(li);
+ });
+ });
+});
diff --git a/nodeJS/Learning/05/src/index.html b/nodeJS/Learning/05/src/index.html
deleted file mode 100644
index 37b53dd..0000000
--- a/nodeJS/Learning/05/src/index.html
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
- Tiffy's to-do list website
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Tiffy's to-do list website
-
Add something cute to my to-do list!
-
-
-
-
-
-
-
-
-
-
-
To do list
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/nodeJS/Learning/05/src/index.ts b/nodeJS/Learning/05/src/index.ts
index 2911cad..8f562df 100644
--- a/nodeJS/Learning/05/src/index.ts
+++ b/nodeJS/Learning/05/src/index.ts
@@ -1,23 +1,24 @@
//importing the dotenv package (secret file), configuring dotenv for our project
//dotenv, secret file, people cant read
-import dotenv from 'dotenv';
+import dotenv from "dotenv";
dotenv.config({ path: `${__dirname}/../.env` });
//Variable declaration
//we named express as a variable name, usually name same as imported package
//express: designed to easily make a web server
-import express, { Request, Response } from 'express';
+import express, { Application, Request, Response } from "express";
//bodyParser: sending form action to my server, wrap the user's data in "body" to my server, and my server is unwrapping it
-import bodyParser from 'body-parser';
-import fs from 'fs';
+import bodyParser from "body-parser";
+import fs from "fs";
+import path from "path";
-const filePath = 'todolist.txt';
+const filePath: string = "todolist.txt";
//initializing the express web server, everything in express, we want to put in app
-const app = express();
-const port = process.env.PORT || 3000;
+const app: Application = express();
+const port: Number = parseInt(process.env.PORT as string) || 3000;
// Middleware
//unwrap the words
@@ -31,45 +32,93 @@ app.use(bodyParser.json());
//to make icon files, because icon files are always downloaded
app.use(express.static(`${__dirname}/../public`));
-app.get(`/`, (req, res) => {
- res.sendFile(`${__dirname}/index.html`);
+app.get(`/`, (_req: Request, res: Response): void => {
+ res.sendFile(path.join(__dirname, "../public/html/index.html"));
});
-app.post('/form-action', (req, res) => {
- const todo = req.body.todo;
- console.log(todo);
-
- // use fs to add the item to the file
+app.post("/form-action", (req: Request, res: Response): void => {
+ const todo = req.body.todo;
- fs.appendFile(filePath, todo + '\n', (err) => {
- if (err) {
- console.log(err)
- res.send("Hey there is an error.")
- } else {
- res.redirect("/");
- }
- });
-
+ // use fs to add the item to the file
+
+ fs.appendFile(filePath, "\n" + todo, (err) => {
+ if (err) {
+ console.log(err);
+ res.send("Hey there is an error.");
+ } else {
+ res.redirect("/");
+ }
+ });
});
-app.get('/get-todos', (req: Request, res: Response): void => {
- //Using the fs module to read the file
- fs.readFile(filePath, 'utf-8', (err:NodeJS.ErrnoException | null, data: string) => {
- if (err) {
- console.log(err)
- res.send("An error occured.")
- } else {
- //Return the file contents as a response of each list item data.split
- //Send the response back to the client as a json object res.json
- res.json(data.split('\n'))
- }
- })
-})
+app.get("/get-todos", (_req: Request, res: Response): void => {
+ //Using the fs module to read the file
+ fs.readFile(
+ filePath,
+ "utf-8",
+ (err: NodeJS.ErrnoException | null, data: string) => {
+ if (err) {
+ console.log(err);
+ res.send("An error occured.");
+ } else {
+ //Return the file contents as a response of each list item data.split
+ //Send the response back to the client as a json object res.json
+ res.json(data.split("\n").filter((data) => data.trim() !== ""));
+ }
+ }
+ );
+});
+app.delete("/delete-todo", (req: Request, res: Response): void => {
+ const todoToDelete = (req.body.todo || "").trim(); // Ensure input is trimmed
+
+ if (!todoToDelete) {
+ res.status(400).json({ error: "No to-do item provided to delete" });
+ return;
+ }
+
+ // Read the file to get the current list of todos
+ fs.readFile(filePath, "utf8", (err, data) => {
+ if (err) {
+ console.error("Error reading file:", err);
+ res.status(500).json({ error: "Internal Server Error" });
+ return;
+ }
+
+ // Split the content into lines and trim whitespace from each line
+ const todos = data
+ .split("\n")
+ .map((line) => line.trim())
+ .filter((line) => line !== ""); // Remove empty lines
+
+ // Filter out the todo item to delete
+ const updatedTodos = todos.filter((todo) => todo !== todoToDelete);
+
+ if (todos.length === updatedTodos.length) {
+ res.status(404).json({ error: "Todo not found" });
+ return;
+ }
+
+ // Join the updated list back into a string
+ const updatedContent = updatedTodos.join("\n");
+
+ // Write the updated content back to the file
+ fs.writeFile(filePath, updatedContent, "utf8", (writeErr) => {
+ if (writeErr) {
+ console.error("Error writing file:", writeErr);
+ res.status(500).json({ error: "Internal Server Error" });
+ return;
+ }
+
+ console.log(`Deleted todo: ${todoToDelete}`);
+ res.status(200).json({ message: "Todo deleted successfully" });
+ });
+ });
+});
// slash'/' is the home page, /about is the about page
//get, post, put, delete
app.listen(port, () => {
- console.log(`Server is running on http://localhost:${port}`);
-});
\ No newline at end of file
+ console.log(`Server is running on http://localhost:${port}`);
+});
diff --git a/nodeJS/Learning/05/todolist.txt b/nodeJS/Learning/05/todolist.txt
index 55b1898..48d732e 100644
--- a/nodeJS/Learning/05/todolist.txt
+++ b/nodeJS/Learning/05/todolist.txt
@@ -1,6 +1,3 @@
-Learn coding
-Cook dinner
-Make a pretty website
-Delete list items
-Edit list items
-Move items to database!!!
\ No newline at end of file
+ABC
+CDE
+FADDGD
\ No newline at end of file
diff --git a/nodeJS/Learning/05/tsconfig.json b/nodeJS/Learning/05/tsconfig.json
index 774a683..a0270e6 100644
--- a/nodeJS/Learning/05/tsconfig.json
+++ b/nodeJS/Learning/05/tsconfig.json
@@ -30,7 +30,9 @@
"moduleResolution": "node10" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
- "rootDirs": ["./"], /* Allow multiple folders to be treated as one when resolving modules. */
+ "rootDirs": [
+ "./"
+ ] /* Allow multiple folders to be treated as one when resolving modules. */,
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
@@ -85,18 +87,18 @@
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied 'any' type. */,
- // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
- // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+ "strictNullChecks": true /* When type checking, take into account 'null' and 'undefined'. */,
+ "strictFunctionTypes": true /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */,
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */
- // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
+ "noImplicitThis": true /* Enable error reporting when 'this' is given the type 'any'. */,
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
"alwaysStrict": true /* Ensure 'use strict' is always emitted. */,
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
- // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
+ "noUnusedParameters": true /* Raise an error when a function parameter isn't read. */,
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
- // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
+ "noImplicitReturns": true /* Enable error reporting for codepaths that do not explicitly return in a function. */,
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
@@ -108,4 +110,4 @@
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
-}
\ No newline at end of file
+}