From fb1f85ac720f4c3d9bcaff76b93f2913d2af542f Mon Sep 17 00:00:00 2001 From: Mershelle Rivera Date: Mon, 13 Oct 2025 19:48:17 -0700 Subject: [PATCH 1/3] provide comments for each line of code --- .vscode/settings.json | 3 ++ public/css/style.css | 18 ++++--- public/js/main.js | 117 +++++++++++++++++++++++++----------------- 3 files changed, 84 insertions(+), 54 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index c3c81b8b..0c7ffd3b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,7 @@ +// This file contains settings set for the project workspace { + // Sets the font size in the code editor to 42px "editor.fontSize": 42, + // Set the font size in the terminal to 62px "terminal.integrated.fontSize": 62 } \ No newline at end of file diff --git a/public/css/style.css b/public/css/style.css index 0475253a..cb1d6843 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -1,7 +1,11 @@ -h1{ - color: red; -} -.completed{ - color: gray; - text-decoration: line-through; -} \ No newline at end of file +/* This file is an external stylesheet containing CSS code */ + +h1{ /* Targets every h1 element */ + color: red; /* Set the color of the text to red */ +} /* end of style declaration for the h1 selector */ + + +.completed{ /* Targets the .completed class */ + color: gray; /* Set the color of the text to gray */ + text-decoration: line-through; /* Apply a strikethrough effect to the text */ +} /* end of style declaration for the .completed class */ \ No newline at end of file diff --git a/public/js/main.js b/public/js/main.js index ff0eac39..95a4a64d 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -1,72 +1,95 @@ +// target the class .fa-trash const deleteBtn = document.querySelectorAll('.fa-trash') +// target the span elements within the element with the class .item const item = document.querySelectorAll('.item span') +// target the span with the class .completed within the element with the class .item const itemCompleted = document.querySelectorAll('.item span.completed') +// for each item in the li that has the trash can icon Array.from(deleteBtn).forEach((element)=>{ - element.addEventListener('click', deleteItem) -}) + // attach an event listener for each li item when the trash icon is clicked + element.addEventListener('click', deleteItem) // invoke deleteItem(): delete item +}) +// for each item with a class .item Array.from(item).forEach((element)=>{ + // attach an event listener to mark the item as complete element.addEventListener('click', markComplete) }) +// for each li item with a span of a class .completed Array.from(itemCompleted).forEach((element)=>{ + // attach an event listener to mark the item and uncomplete element.addEventListener('click', markUnComplete) }) +// this function will be called when the trash icon is clicked async function deleteItem(){ + // grab the item the user clicked on to delete const itemText = this.parentNode.childNodes[1].innerText - try{ - const response = await fetch('deleteItem', { - method: 'delete', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ - 'itemFromJS': itemText - }) - }) - const data = await response.json() - console.log(data) - location.reload() + // error handling, in case the item does not exist + try{ + // initiate the request and wait until a response is received + const response = await fetch('deleteItem', { // target endpoint + method: 'delete', // http method delete, remove the item + // request header, the body of the data is formatted in json + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ // the request body, property set to stringified JSON object + // create key-value pair + 'itemFromJS': itemText // itemText = the text of the item to be deleted + }) // end of JSON object + }) // end of fetch call + const data = await response.json() // store the response + console.log(data) // display the response to the console + location.reload() // refresh the web page - }catch(err){ - console.log(err) - } -} + }catch(err){ // end of try, catch the error + console.log(err) // display the error in the console + } // end of catch block +} // end of deleteItem function -async function markComplete(){ +// this function will mark the item on the todo list as complete +async function markComplete(){ // declare a function name markComplete + // grab the item from the list to mark as complete const itemText = this.parentNode.childNodes[1].innerText - try{ + try{ // start of the error handling + // store the response from the request from the markComplete endpoint const response = await fetch('markComplete', { - method: 'put', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ - 'itemFromJS': itemText - }) - }) - const data = await response.json() - console.log(data) - location.reload() + method: 'put', // http method put, to update the item + // request header, the body of the data is formatted in json + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ // request body, data converted to json + 'itemFromJS': itemText // key-value pair, itemText = text of the li item + }) // end of json object + }) // end of fetch + const data = await response.json() // store the response to data + console.log(data) // display the data in console + location.reload() // refresh page - }catch(err){ - console.log(err) - } -} + }catch(err){ // catch error, if occured + console.log(err) // display error in console + } // end of catch +} // end of markComplete() -async function markUnComplete(){ +// this function changes the item status to incomplete +async function markUnComplete(){ + // grabs the text of the item the user clicked on const itemText = this.parentNode.childNodes[1].innerText - try{ - const response = await fetch('markUnComplete', { - method: 'put', + try{ // error handling + // start a fetch request for the endpoint markUnComplete + const response = await fetch('markUnComplete', { + method: 'put', // http method put, updates the status of the item + // request header, the body of the data is formatted in json headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ - 'itemFromJS': itemText - }) - }) - const data = await response.json() - console.log(data) - location.reload() + body: JSON.stringify({ // request body, data converted to json + 'itemFromJS': itemText // key-value pair, itemText = text of the li item + }) // end of json object + }) // end of fetch request + const data = await response.json() // store response to json in a data variable + console.log(data) // display the data in console + location.reload() // refresh page - }catch(err){ - console.log(err) - } -} \ No newline at end of file + }catch(err){ // handle error, if any + console.log(err) // display the error in console + } // end of catch block +} // end of markUnComplete function \ No newline at end of file From d95fa54398f2b142a1224dbd272b434f2ae950f1 Mon Sep 17 00:00:00 2001 From: SabrinaLynnDev Date: Thu, 23 Oct 2025 22:33:49 -0400 Subject: [PATCH 2/3] Upload index.ejs with comments Add comments to every line to this ejs file --- index.ejs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 index.ejs diff --git a/index.ejs b/index.ejs new file mode 100644 index 00000000..2dc30ae8 --- /dev/null +++ b/index.ejs @@ -0,0 +1,62 @@ +<%# This file render the data from server %> + <%#Declare this is an HTML5 document%> + <%# Opens HTML document, set language to english %> + <%# Opens head section%> + <%#Sets character encoding to UTF-8 which supports all characters/symbols)%> + + <%# Tells Internet Explorer to use the latest rendering engine%> + + <%# Makes the page responsive on mobile devices%> + + Document<%#Sets the browser tab title%> + <%#Links Font Awesome CSS library (for icons like the trash icon)%> + + <%# %> + +<%#Closes head section %> +<%# Closes body section %> + +<%#line 20 - line 29 are duplicate section %> + + + + + + + Document + + +

Todo List:

<%#Set to do list as main heading with h1 size%> + <%#Closes the unordered list%> + <%#Displays count of remaining todos with h2 %> +

Left to do: <%= left %>

+ <%#Heading for the add todo form%> +

Add A Todo:

+ + <%#form that submit to /addTodo route with POST method%> +
+ <%#Text input field for new todo%> + + <%#submit button for the form%> +
<%#closes the form%> + <%#Links external JavaScript file%> + +<%#Closes body and html tags%> + + From bda74cd6d0b04b16d48eba380412478a1ff25ac1 Mon Sep 17 00:00:00 2001 From: SabrinaLynnDev Date: Mon, 27 Oct 2025 14:55:19 -0400 Subject: [PATCH 3/3] Update package.json and server.js file comment on every line --- package.json | 34 ++++++------- server.js | 132 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 107 insertions(+), 59 deletions(-) diff --git a/package.json b/package.json index 276ae590..33cc5c3f 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,18 @@ -{ - "name": "rap-name-api", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { +{ //Open JSON object + "name": "rap-name-api", //declares project name + "version": "1.0.0", //declares project version + "description": "", //describe what the project is generally + "main": "index.js", //the main file that runs once the package get required + "scripts": { //defines custom commands you can run with npm run "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "dependencies": { - "cors": "^2.8.5", - "dotenv": "^8.2.0", - "ejs": "^3.1.6", - "express": "^4.17.1", - "mongodb": "^3.6.5" - } -} + },//close the scripts section + "author": "",// generally contain author name but empty here + "license": "ISC", //list license type is ISC which is permissive open-source license + "dependencies": { //lists packages the app needs to run + "cors": "^2.8.5", //allows your api to be accessed from different domain + "dotenv": "^8.2.0",//loads environment variable from .env file, to hide sensitive data + "ejs": "^3.1.6",//allow JS to be embed in HTML templates + "express": "^4.17.1", //web app framework to handle rounting, requests, responses + "mongodb": "^3.6.5" //connects app to MongoDB database, used to store and retrieve the to do items + }//closes dependencies section +}//closes the entire JSON object diff --git a/server.js b/server.js index 58b53e2f..f5b9eff1 100644 --- a/server.js +++ b/server.js @@ -1,29 +1,49 @@ -const express = require('express') -const app = express() +const express = require('express')//imports express framework +const app = express() //creates express application instance +//import MongoClient from MongoDB package const MongoClient = require('mongodb').MongoClient +//Sets the port number the server will run const PORT = 2121 +//loads environment variables from .env file require('dotenv').config() - -let db, - dbConnectionStr = process.env.DB_STRING, +//Declares these variables: +let db, //db will hold the database connection + //dbConnectionStr = MongoDB connection string from .env file + dbConnectionStr = process.env.DB_STRING, + //dbName = name of the database('todo') dbName = 'todo' - +//connect MongoDB using the connection string and uses new MongoDB connection +//engine, returns a promise MongoClient.connect(dbConnectionStr, { useUnifiedTopology: true }) +//when the connection succeeds, run this function below. .then(client => { + //print out success message to console console.log(`Connected to ${dbName} Database`) + //sets the db variable to 'todo'database db = client.db(dbName) - }) + })//closes the .then()block -app.set('view engine', 'ejs') -app.use(express.static('public')) -app.use(express.urlencoded({ extended: true })) -app.use(express.json()) - +app.set('view engine', 'ejs')//tells express to use EJS as templating engine +app.use(express.static('public'))//serves static files(CSS/JS) from the public folder +app.use(express.urlencoded({ extended: true }))//Middleware to parse form data from POST requests +app.use(express.json())//Middleware to parse JSON data from requests +/* +defines GET route for homepage(/) +async() is the function can use await for asynchronous operations +including two parameters: +request-> incoming request object; +response-> object to send response back to client*/ app.get('/',async (request, response)=>{ + //get all the documents from 'todos' collection, find them and list them in an array + //await-> waits for database operation to complete const todoItems = await db.collection('todos').find().toArray() + //count the amount of incompleted items, stored the amount in itemsLeft const itemsLeft = await db.collection('todos').countDocuments({completed: false}) + //Render index.ejs template, + //passes array of all todosItems and the amount of incompleted todos + //to the template response.render('index.ejs', { items: todoItems, left: itemsLeft }) // db.collection('todos').find().toArray() // .then(data => { @@ -33,61 +53,89 @@ app.get('/',async (request, response)=>{ // }) // }) // .catch(error => console.error(error)) -}) + //commented out line 48-line55: + /* The original code was using .then() instead of async/await + async/await is cleaner and easier to read so modern code prefer this method + */ +}) //closes the Get route + +//Define Post route at /addTodo +//Triggered when the form in the EJS file is submitted app.post('/addTodo', (request, response) => { + //insert a new document to todos collections + //create objects: + //declare thing = the todo text from form input name is todoItem + //todoIteam condition is incompleted if completed = false db.collection('todos').insertOne({thing: request.body.todoItem, completed: false}) + //when insert succeeds, runs this function .then(result => { + //print out success message to console console.log('Todo Added') + //redirects user back to homepage, this refreshes the page to show + //the new todo response.redirect('/') }) - .catch(error => console.error(error)) -}) + .catch(error => console.error(error))//if error occurs, print it out to console +}) //closes the route function +//Define PUT route at /markComplete +//Called from frontend JS(main.js) when user clicks a todo app.put('/markComplete', (request, response) => { + //Updates one document in 'todos' collection + //first parameter declares filter to find the todo from frontend + //second parameter declares update conditions db.collection('todos').updateOne({thing: request.body.itemFromJS},{ - $set: { - completed: true + $set: { //MongoDB operator to set field value + completed: true //set completed field to be true } - },{ - sort: {_id: -1}, - upsert: false + },{ //third parameter is options object + sort: {_id: -1}, //update according to descending order + upsert: false //dont create new item if no match found }) - .then(result => { - console.log('Marked Complete') - response.json('Marked Complete') + .then(result => {//when update succeeds + console.log('Marked Complete')//print out to console + response.json('Marked Complete')//send JSON response back to frontend }) - .catch(error => console.error(error)) + .catch(error => console.error(error))//catches and print out errors -}) +})//closes the put route +//declares PUT rounte at /markUnComplete app.put('/markUnComplete', (request, response) => { + //first parameter declares filter to find todos from frontend main.js db.collection('todos').updateOne({thing: request.body.itemFromJS},{ - $set: { - completed: false + //seconde parameter declares update conditions + $set: { //MongoDB operator to set field value + completed: false //set completed filed to be false } - },{ - sort: {_id: -1}, - upsert: false + },{ //third parameter is option object + sort: {_id: -1},//update the newest incompleted item by descending order + upsert: false //dont create new item if no match found }) - .then(result => { - console.log('Marked Complete') - response.json('Marked Complete') + .then(result => {//if update succeeds + console.log('Marked Complete')// BUG: here should print out Marked Incompleted to console + response.json('Marked Complete')//BUG: here should response Marked Incompleted to JSON }) - .catch(error => console.error(error)) + .catch(error => console.error(error))//catch and print out error if any -}) +})//closed the put route +//define delete route at /deleteItem, +//Called from frontend when user clicks trash icon app.delete('/deleteItem', (request, response) => { + //Deletes ONE document from 'todos' collection + //first parameter is to filter the item match thing defination db.collection('todos').deleteOne({thing: request.body.itemFromJS}) - .then(result => { - console.log('Todo Deleted') - response.json('Todo Deleted') + .then(result => {//if update succeeds + console.log('Todo Deleted')//print out 'Todo Deleted' to console + response.json('Todo Deleted')//response 'Todo Deleted' to frontend }) - .catch(error => console.error(error)) + .catch(error => console.error(error))//catch and print out error if any -}) +}) //closes the delete route +//listen from env file or port 2121 app.listen(process.env.PORT || PORT, ()=>{ - console.log(`Server running on port ${PORT}`) -}) \ No newline at end of file + console.log(`Server running on port ${PORT}`)//print out message if server starts +})//closes the listen function \ No newline at end of file