mirror of
				https://github.com/cse110-fa22-group29/cse110-fa22-group29.git
				synced 2025-10-31 03:46:50 +00:00 
			
		
		
		
	Merge pull request #66 from cse110-fa22-group29/storage-revamp
Storage revamp
This commit is contained in:
		
							
								
								
									
										2
									
								
								.github/workflows/js-unittest.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/js-unittest.yml
									
									
									
									
										vendored
									
									
								
							| @@ -24,6 +24,6 @@ jobs: | |||||||
|       - name: Install dependencies |       - name: Install dependencies | ||||||
|         run: sudo npm install |         run: sudo npm install | ||||||
|       - name: Start local http server |       - name: Start local http server | ||||||
|         run: sudo npm run http-server |         run: sudo npm run http-server &  | ||||||
|       - name: Run tests |       - name: Run tests | ||||||
|         run: sudo npm test |         run: sudo npm test | ||||||
| @@ -14,12 +14,13 @@ | |||||||
|   <!-- Main Stylesheets & Scripts --> |   <!-- Main Stylesheets & Scripts --> | ||||||
|   <!-- Temporarily commented out reset.css due to furthur discussion needed on the values of the default config--> |   <!-- Temporarily commented out reset.css due to furthur discussion needed on the values of the default config--> | ||||||
|   <!-- <link rel="stylesheet" href="/static/reset.css" /> --> |   <!-- <link rel="stylesheet" href="/static/reset.css" /> --> | ||||||
|   <link rel="stylesheet" href="./static/CreatePage.css" /> |   <link rel="stylesheet" href="./static/ReviewCard.css" /> | ||||||
|   <script src="assets/scripts/main.js" type="module"></script> |   <script src="./assets/scripts/CreatePage.js" type="module"></script> | ||||||
|  |  | ||||||
| </head> | </head> | ||||||
|  |  | ||||||
| <body> | <body> | ||||||
|  |   <input type="button" value="Home" id="home-btn" onclick="window.location.assign('./index.html')"> | ||||||
|   <form id="new-food-entry"> |   <form id="new-food-entry"> | ||||||
|     <fieldset> |     <fieldset> | ||||||
|       <legend>Pic:</legend> |       <legend>Pic:</legend> | ||||||
| @@ -69,8 +70,7 @@ | |||||||
|       </label> |       </label> | ||||||
|  |  | ||||||
|     </fieldset> |     </fieldset> | ||||||
|     <button type="submit" value="Submit">Add Review</button> |     <button type="submit" id="save-btn" value="Submit">Save Review</button> | ||||||
|     <button type="button" class="danger">Clear Review Journal</button> |  | ||||||
|   </form> |   </form> | ||||||
| </body> | </body> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ | |||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|   <main> |   <main> | ||||||
|  |     <input type="button" value="Home" id="home-btn" onclick="window.location.assign('./index.html')"> | ||||||
|     <button type="button" id="update-btn">Update</button> |     <button type="button" id="update-btn">Update</button> | ||||||
|     <button type="button" id="delete-btn" class="danger">Delete</button> |     <button type="button" id="delete-btn" class="danger">Delete</button> | ||||||
|   </main> |   </main> | ||||||
|   | |||||||
							
								
								
									
										66
									
								
								source/assets/scripts/CreatePage.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								source/assets/scripts/CreatePage.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | import { newReviewToStorage } from "./localStorage.js"; | ||||||
|  |  | ||||||
|  | window.addEventListener("DOMContentLoaded", init); | ||||||
|  |  | ||||||
|  | function init() { | ||||||
|  | 	// get next id | ||||||
|  |  | ||||||
|  | 	// creates the key | ||||||
|  | 	initFormHandler(); | ||||||
|  |      | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function initFormHandler() { | ||||||
|  |  | ||||||
|  | 	//accessing form components | ||||||
|  | 	let tagContainer = document.getElementById("tag-container-form"); | ||||||
|  | 	let form = document.querySelector("form"); | ||||||
|  |    | ||||||
|  | 	form.addEventListener("submit", function(e){ | ||||||
|  | 	/* | ||||||
|  |     *  User submits the form for their review. | ||||||
|  |     *  We create reviewCard and put in storage | ||||||
|  |     */ | ||||||
|  | 		e.preventDefault(); | ||||||
|  | 		let formData = new FormData(form); | ||||||
|  | 		let reviewObject = {}; | ||||||
|  | 		for (let [key, value] of formData) { | ||||||
|  | 			console.log(`${key}`); | ||||||
|  | 			console.log(`${value}`); | ||||||
|  | 			if (`${key}` !== "tag-form") { | ||||||
|  | 				reviewObject[`${key}`] = `${value}`; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		reviewObject["tags"] = []; | ||||||
|  |  | ||||||
|  | 		let tags = document.querySelectorAll(".tag"); | ||||||
|  | 		for(let i = 0; i < tags.length; i ++) { | ||||||
|  | 			reviewObject["tags"].push(tags[i].innerHTML); | ||||||
|  | 			tagContainer.removeChild(tags[i]); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		let nextReviewId = newReviewToStorage(reviewObject); | ||||||
|  | 		sessionStorage.setItem("currID", JSON.stringify(nextReviewId)); | ||||||
|  |  | ||||||
|  | 		window.location.assign("./ReviewDetails.html"); | ||||||
|  |          | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	let tagAddBtn = document.getElementById("tagAdd"); | ||||||
|  | 	tagAddBtn.addEventListener("click", ()=> { | ||||||
|  | 		let tagField = document.getElementById("tag-form"); | ||||||
|  | 		if (tagField.value.length > 0) { | ||||||
|  | 			let tagLabel = document.createElement("label"); | ||||||
|  | 			tagLabel.innerHTML = tagField.value; | ||||||
|  | 			tagLabel.setAttribute("class","tag"); | ||||||
|  | 			tagLabel.addEventListener("click",()=> { | ||||||
|  | 				tagContainer.removeChild(tagLabel); | ||||||
|  | 			}); | ||||||
|  |        | ||||||
|  | 			tagContainer.append(tagLabel); | ||||||
|  | 			tagField.value = ""; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -6,7 +6,6 @@ class ReviewCard extends HTMLElement { | |||||||
| 	constructor() { | 	constructor() { | ||||||
| 		super();  | 		super();  | ||||||
|  |  | ||||||
|  |  | ||||||
| 		let shadowEl = this.attachShadow({mode:"open"}); | 		let shadowEl = this.attachShadow({mode:"open"}); | ||||||
|  |  | ||||||
| 		let articleEl = document.createElement("article"); | 		let articleEl = document.createElement("article"); | ||||||
| @@ -88,9 +87,9 @@ class ReviewCard extends HTMLElement { | |||||||
| 		//attach event listener to each recipe-card | 		//attach event listener to each recipe-card | ||||||
| 		this.addEventListener("click", (event) => { | 		this.addEventListener("click", (event) => { | ||||||
| 			console.log(event.target); | 			console.log(event.target); | ||||||
| 			console.log(event.target.data); | 			console.log(event.target.reviewId); | ||||||
| 			//Option 1: sending current data to second html page using localStorage (could also just store index) | 			//Option 1: sending current data to second html page using localStorage (could also just store index) | ||||||
| 			sessionStorage.setItem("current", JSON.stringify(event.target.data)); | 			sessionStorage.setItem("currID", JSON.stringify(event.target.data.reviewID)); | ||||||
| 			window.location.assign("./ReviewDetails.html"); | 			window.location.assign("./ReviewDetails.html"); | ||||||
| 			/* | 			/* | ||||||
|       //Option 2: sending current data to second html page using string query w/ url (currently not storing value) |       //Option 2: sending current data to second html page using string query w/ url (currently not storing value) | ||||||
| @@ -133,12 +132,18 @@ class ReviewCard extends HTMLElement { | |||||||
| 		let articleEl = this.shadowEl.querySelector("article"); | 		let articleEl = this.shadowEl.querySelector("article"); | ||||||
|      |      | ||||||
| 		// setting the article elements for the review card | 		// setting the article elements for the review card | ||||||
|  | 		this.reviewID = data["reviewID"]; | ||||||
|  |  | ||||||
| 		//image setup | 		//image setup | ||||||
| 		let mealImg = document.createElement("img"); | 		let mealImg = document.createElement("img"); | ||||||
| 		mealImg.setAttribute("id", "a-mealImg"); | 		mealImg.setAttribute("id", "a-mealImg"); | ||||||
| 		mealImg.setAttribute("src",data["mealImg"]); |  | ||||||
| 		mealImg.setAttribute("alt",data["imgAlt"]); | 		mealImg.setAttribute("alt",data["imgAlt"]); | ||||||
|  | 		if(data["mealImg"] != ""){ | ||||||
|  | 			mealImg.setAttribute("src",data["mealImg"]); | ||||||
|  | 		} | ||||||
|  | 		else{ | ||||||
|  | 			mealImg.setAttribute("src", "./assets/images/icons/plate_with_cutlery.png"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		//meal name setup | 		//meal name setup | ||||||
| 		let mealLabel = document.createElement("label"); | 		let mealLabel = document.createElement("label"); | ||||||
| @@ -147,26 +152,6 @@ class ReviewCard extends HTMLElement { | |||||||
| 		mealLabel.innerHTML = data["mealName"]; | 		mealLabel.innerHTML = data["mealName"]; | ||||||
|  |  | ||||||
| 		//restaurant name setup | 		//restaurant name setup | ||||||
| 		/* |  | ||||||
|     //review page link |  | ||||||
|     //giving it functionality to save the review card's info to session storage for loading the review page |  | ||||||
|     let reviewLink = document.createElement('a'); |  | ||||||
|     reviewLink.setAttribute('href','./review.html') |  | ||||||
|     reviewLink.innerHTML = 'review page' |  | ||||||
|     reviewLink.addEventListener('click', () => { |  | ||||||
|       sessionStorage.clear(); |  | ||||||
|       let currReview = { |  | ||||||
|         "imgSrc": data['imgSrc'], |  | ||||||
|         "imgAlt": data['imgAlt'], |  | ||||||
|         "mealName": data['mealName'], |  | ||||||
|         "restaurant": data['restaurant'], |  | ||||||
|         "comments": data['comments'], |  | ||||||
|         "rating": data['rating'], |  | ||||||
|         "tags": data['tags']                 |  | ||||||
|       } |  | ||||||
|       sessionStorage.setItem('currReview', JSON.stringify(currReview)); |  | ||||||
|     }); |  | ||||||
| */ |  | ||||||
| 		let restaurantLabel = document.createElement("label"); | 		let restaurantLabel = document.createElement("label"); | ||||||
| 		restaurantLabel.setAttribute("id", "a-restaurant"); | 		restaurantLabel.setAttribute("id", "a-restaurant"); | ||||||
| 		restaurantLabel.setAttribute("class","restaurant-name"); | 		restaurantLabel.setAttribute("class","restaurant-name"); | ||||||
| @@ -197,14 +182,15 @@ class ReviewCard extends HTMLElement { | |||||||
| 			for (let i = 0; i < data["tags"].length; i++) { | 			for (let i = 0; i < data["tags"].length; i++) { | ||||||
| 				let newTag = document.createElement("label"); | 				let newTag = document.createElement("label"); | ||||||
| 				newTag.setAttribute("class","tag"); | 				newTag.setAttribute("class","tag"); | ||||||
| 				newTag.innerHTML = data["tags"][i] + "   "; | 				newTag.innerHTML = data["tags"][i]; | ||||||
| 				tagContainer.append(newTag); | 				tagContainer.append(newTag); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		//adding final ID to data! | ||||||
|  |  | ||||||
| 		articleEl.append(mealImg); | 		articleEl.append(mealImg); | ||||||
| 		articleEl.append(mealLabel); | 		articleEl.append(mealLabel); | ||||||
| 		//articleEl.append(reviewLink) |  | ||||||
| 		articleEl.append(restaurantLabel); | 		articleEl.append(restaurantLabel); | ||||||
| 		articleEl.append(ratingDiv); | 		articleEl.append(ratingDiv); | ||||||
| 		articleEl.append(tagContainer); | 		articleEl.append(tagContainer); | ||||||
| @@ -237,6 +223,7 @@ class ReviewCard extends HTMLElement { | |||||||
| 		let dataContainer = {}; | 		let dataContainer = {}; | ||||||
|      |      | ||||||
| 		// getting the article elements for the review card | 		// getting the article elements for the review card | ||||||
|  | 		dataContainer["reviewID"] = this.reviewID; | ||||||
|  |  | ||||||
| 		//get image | 		//get image | ||||||
| 		let mealImg = this.shadowEl.getElementById("a-mealImg"); | 		let mealImg = this.shadowEl.getElementById("a-mealImg"); | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| //reviewDetails.js | //reviewDetails.js | ||||||
| import {getReviewsFromStorage, saveReviewsToStorage} from "./localStorage.js"; | import {deleteReviewFromStorage, getReviewFromStorage, updateReviewToStorage} from "./localStorage.js"; | ||||||
|  |  | ||||||
| // Run the init() function when the page has loaded | // Run the init() function when the page has loaded | ||||||
| window.addEventListener("DOMContentLoaded", init); | window.addEventListener("DOMContentLoaded", init); | ||||||
| @@ -11,55 +11,44 @@ function init(){ | |||||||
|  |  | ||||||
| function setupDelete(){ | function setupDelete(){ | ||||||
| 	let deleteBtn = document.getElementById("delete-btn"); | 	let deleteBtn = document.getElementById("delete-btn"); | ||||||
| 	let reviews = getReviewsFromStorage(); | 	let currID = JSON.parse(sessionStorage.getItem("currID")); | ||||||
| 	let current = JSON.parse(sessionStorage.getItem("current")); |  | ||||||
| 	deleteBtn.addEventListener("click", function(){ | 	deleteBtn.addEventListener("click", function(){ | ||||||
| 		if(window.confirm("Are you sure you want to delete this entry?")){ | 		if(window.confirm("Are you sure you want to delete this entry?")){ | ||||||
| 			//delete function | 			deleteReviewFromStorage(currID); | ||||||
| 			if(current){ | 			sessionStorage.removeItem("currID"); | ||||||
| 				console.log(current); |  | ||||||
| 				for(let i = 0; i < reviews.length; i++){ |  | ||||||
| 					console.log(reviews[i]); |  | ||||||
| 					if(reviews[i]["mealName"] == current["mealName"] && reviews[i]["restaurant"] == current["restaurant"]){ |  | ||||||
| 						console.log("match found"); |  | ||||||
| 						reviews.splice(i,1); |  | ||||||
| 						saveReviewsToStorage(reviews); |  | ||||||
| 						sessionStorage.removeItem("current"); |  | ||||||
| 			window.location.assign("./index.html"); | 			window.location.assign("./index.html"); | ||||||
| 						break; |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
|  |  | ||||||
| function setupUpdate(){ | function setupUpdate(){ | ||||||
| 	let updateBtn = document.getElementById("update-btn"); | 	let updateBtn = document.getElementById("update-btn"); | ||||||
| 	let reviews = getReviewsFromStorage(); | 	let currID = JSON.parse(sessionStorage.getItem("currID")); | ||||||
| 	let current = JSON.parse(sessionStorage.getItem("current")); | 	let currReview = getReviewFromStorage(currID); | ||||||
| 	let form = document.getElementById("update-food-entry"); | 	let form = document.getElementById("update-food-entry"); | ||||||
| 	updateBtn.addEventListener("click", function(){ | 	updateBtn.addEventListener("click", function(){ | ||||||
| 		//update function | 		//update function | ||||||
| 		if(current){ |  | ||||||
| 			console.log(current); | 		//form.style.display = "block"; | ||||||
| 			form.style.display = "block"; | 		form.classList.remove("hidden"); | ||||||
| 		let tagContainer = document.getElementById("tag-container-form"); | 		let tagContainer = document.getElementById("tag-container-form"); | ||||||
| 			console.log(document.querySelectorAll("#update-food-entry input")); |  | ||||||
|  |  | ||||||
| 		//Set value of each input element to current's values | 		//Set value of each input element to current's values | ||||||
| 			document.getElementById("mealImg").defaultValue = current["mealImg"]; | 		document.getElementById("mealImg").defaultValue = currReview["mealImg"]; | ||||||
| 			document.getElementById("imgAlt").defaultValue = current["imgAlt"]; | 		document.getElementById("imgAlt").defaultValue = currReview["imgAlt"]; | ||||||
| 			document.getElementById("mealName").defaultValue = current["mealName"]; | 		document.getElementById("mealName").defaultValue = currReview["mealName"]; | ||||||
| 			document.getElementById("comments").textContent = current["comments"]; | 		document.getElementById("comments").textContent = currReview["comments"]; | ||||||
| 			document.getElementById("rating-" + `${current["rating"]}`).checked = true; | 		document.getElementById("s" + `${currReview["rating"]}`).checked = true; | ||||||
| 			document.getElementById("restaurant").defaultValue = current["restaurant"]; | 		document.getElementById("restaurant").defaultValue = currReview["restaurant"]; | ||||||
|  |  | ||||||
| 			if(current["tags"]){ | 		if(currReview["tags"]){ | ||||||
| 				for (let i = 0; i < current["tags"].length; i++) { | 			while (tagContainer.firstChild) { | ||||||
|  | 				tagContainer.removeChild(tagContainer.firstChild); | ||||||
|  | 			} | ||||||
|  | 			for (let i = 0; i < currReview["tags"].length; i++) { | ||||||
| 				let newTag = document.createElement("label"); | 				let newTag = document.createElement("label"); | ||||||
| 				newTag.setAttribute("class","tag"); | 				newTag.setAttribute("class","tag"); | ||||||
| 					newTag.innerHTML = current["tags"][i] + "   "; | 				newTag.innerHTML = currReview["tags"][i]; | ||||||
| 				newTag.addEventListener("click",()=> { | 				newTag.addEventListener("click",()=> { | ||||||
| 					tagContainer.removeChild(newTag); | 					tagContainer.removeChild(newTag); | ||||||
| 				}); | 				}); | ||||||
| @@ -89,16 +78,9 @@ function setupUpdate(){ | |||||||
| 				tagContainer.removeChild(tags[i]); | 				tagContainer.removeChild(tags[i]); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 				for(let i = 0; i < reviews.length; i++){ | 			newData["reviewID"] = currID; | ||||||
| 					console.log(reviews[i]); |  | ||||||
| 					if(reviews[i]["mealName"] == current["mealName"] && reviews[i]["restaurant"] == current["restaurant"]){ | 			updateReviewToStorage(currID, newData); | ||||||
| 						console.log("match found"); |  | ||||||
| 						reviews.splice(i,1,newData); |  | ||||||
| 						saveReviewsToStorage(reviews); |  | ||||||
| 						sessionStorage.setItem("current", JSON.stringify(newData)); |  | ||||||
| 						break; |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 			form.style.display = "none"; | 			form.style.display = "none"; | ||||||
|  |  | ||||||
| @@ -119,6 +101,5 @@ function setupUpdate(){ | |||||||
| 				tagField.value = ""; | 				tagField.value = ""; | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
| 		} |  | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,13 +0,0 @@ | |||||||
| // Run the init() function when the page has loaded |  | ||||||
| window.addEventListener("DOMContentLoaded", init); |  | ||||||
|  |  | ||||||
| function init() { |  | ||||||
| 	let result = sessionStorage.getItem("currReview"); |  | ||||||
|  |  | ||||||
| 	let main = document.querySelector("main"); |  | ||||||
|      |  | ||||||
| 	main.innerHTML = result; |  | ||||||
| 	let p = document.createElement("p"); |  | ||||||
| 	p.innerHTML = JSON.parse(result)["comments"]; |  | ||||||
| 	main.append(p); |  | ||||||
| } |  | ||||||
| @@ -1,19 +1,79 @@ | |||||||
| /** | /** | ||||||
|  * @returns {Array<Object>} An array of reviews found in localStorage |  * Creates a new review to storage and performs related meta tasks | ||||||
|  |  * @param {Object} review to store | ||||||
|  |  * @return {number} ID of the newly added review | ||||||
|  */ |  */ | ||||||
| export function getReviewsFromStorage() { | export function newReviewToStorage(review){ | ||||||
| 	let result = JSON.parse(localStorage.getItem("reviews")); | 	//grabbing the nextID, and putting our review object in storage associated with the ID | ||||||
| 	if (result) { | 	let nextReviewId = JSON.parse(localStorage.getItem("nextID")); | ||||||
| 		return result; | 	review["reviewID"] = nextReviewId; | ||||||
| 	} |  | ||||||
| 	return new Array(0); | 	// set the review entry to the review object | ||||||
|  | 	localStorage.setItem(`review${nextReviewId}`, JSON.stringify(review)); | ||||||
|  | 	 | ||||||
|  | 	//updating our activeIDS list | ||||||
|  | 	let tempIdArr = JSON.parse(localStorage.getItem("activeIDS")); | ||||||
|  | 	tempIdArr.push(nextReviewId); | ||||||
|  | 	localStorage.setItem("activeIDS", JSON.stringify(tempIdArr)); | ||||||
|  | 	 | ||||||
|  | 	//increment nextID for next review creation | ||||||
|  | 	nextReviewId++; | ||||||
|  | 	localStorage.setItem("nextID", JSON.stringify(nextReviewId)); | ||||||
|  |  | ||||||
|  | 	return nextReviewId; | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Takes in an array of reviews, converts it to a string, and then |  * Gets a single review by ID from storage | ||||||
|  * saves that string to 'reviews' in localStorage |  * @param {string} ID of the review to get | ||||||
|  * @param {Array<Object>} reviews An array of reviews |  * @returns {Object} review object corresponding to param ID | ||||||
|  */ |  */ | ||||||
| export function saveReviewsToStorage(reviews) { | export function getReviewFromStorage(ID){ | ||||||
| 	localStorage.setItem("reviews", JSON.stringify(reviews)); | 	return JSON.parse(localStorage.getItem(`review${ID}`)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Updates a single review by ID to storage | ||||||
|  |  * @param {string} ID of review to update | ||||||
|  |  * @param {Object} review to store | ||||||
|  |  */ | ||||||
|  | export function updateReviewToStorage(ID, review){ | ||||||
|  | 	// set the review entry with ID to the review object | ||||||
|  | 	localStorage.setItem(`review${ID}`, JSON.stringify(review)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Deletes a review by ID from storage | ||||||
|  |  * @param {string} ID of the review to delete | ||||||
|  |  */ | ||||||
|  | export function deleteReviewFromStorage(ID){ | ||||||
|  | 	let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); | ||||||
|  |  | ||||||
|  | 	for (let i in activeIDS) { | ||||||
|  | 		if (activeIDS[i] == ID) { | ||||||
|  | 			activeIDS.splice(i,1); | ||||||
|  | 			localStorage.setItem("activeIDS", JSON.stringify(activeIDS)); | ||||||
|  | 			localStorage.removeItem(`review${ID}`); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	console.error(`could not find review${ID} in localStorage`); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // legacy function | ||||||
|  | export function getAllReviewsFromStorage() { | ||||||
|  | 	if (!(localStorage.getItem("activeIDS"))) { | ||||||
|  | 		// we wanna init the active ID array and start the nextID count | ||||||
|  | 		localStorage.setItem("activeIDS", JSON.stringify([])); | ||||||
|  | 		localStorage.setItem("nextID",  JSON.stringify(0)); | ||||||
|  | 	} | ||||||
|  | 	//iterate thru activeIDS | ||||||
|  | 	let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); | ||||||
|  | 	let reviews = []; | ||||||
|  | 	for (let i = 0; i < activeIDS.length; i++) { | ||||||
|  | 		let currReview = JSON.parse(localStorage.getItem(`review${activeIDS[i]}`)); | ||||||
|  | 		reviews.push(currReview); | ||||||
|  | 	} | ||||||
|  | 	return reviews; | ||||||
| } | } | ||||||
| @@ -1,49 +1,106 @@ | |||||||
| import {strict as assert} from "node:assert"; | import {strict as assert} from "node:assert"; | ||||||
| import {describe, it, beforeEach} from "mocha"; | import {describe, it, before, after} from "mocha"; | ||||||
| import {saveReviewsToStorage, getReviewsFromStorage} from "./localStorage.js"; | import {newReviewToStorage, getReviewFromStorage, updateReviewToStorage, deleteReviewFromStorage, getAllReviewsFromStorage} from "./localStorage.js"; | ||||||
|  |  | ||||||
| describe("test app localStorage interaction", () => { | describe("test app localStorage interaction", () => { | ||||||
| 	 | 	 | ||||||
| 	beforeEach(() => { | 	before(() => { | ||||||
| 		localStorage.clear(); | 		localStorage.clear(); | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	it("get after init", () => { | 	it("test localStorage state after init", () => { | ||||||
| 		assert.deepEqual(getReviewsFromStorage(), []); | 		assert.deepEqual(getAllReviewsFromStorage(), []); | ||||||
|  | 		assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), []); | ||||||
|  | 		assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 0); | ||||||
| 	}); | 	}); | ||||||
| 	it("store one then get", () => { |  | ||||||
| 		let reviews = [{ | 	it("test localStorage state after adding one review", () => { | ||||||
|  | 		let review = { | ||||||
| 			"imgSrc": "sample src", | 			"imgSrc": "sample src", | ||||||
| 			"imgAlt": "sample alt", | 			"imgAlt": "sample alt", | ||||||
| 			"mealName": "sample name", | 			"mealName": "sample name", | ||||||
| 			"restaurant": "sample restaurant", | 			"restaurant": "sample restaurant", | ||||||
| 			"rating": 5, | 			"rating": 5, | ||||||
| 			"tags": ["tag 1", "tag  2", "tag 3"] | 			"tags": ["tag 1", "tag  2", "tag 3"] | ||||||
| 		}]; | 		}; | ||||||
|  |  | ||||||
| 		saveReviewsToStorage(reviews); | 		newReviewToStorage(review); | ||||||
| 		assert.deepEqual(getReviewsFromStorage(), reviews); |  | ||||||
|  | 		review.reviewID = 0; | ||||||
|  |  | ||||||
|  | 		assert.deepEqual(getAllReviewsFromStorage(), [review]); | ||||||
|  | 		assert.deepEqual(getReviewFromStorage(0), review); | ||||||
|  | 		assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), [0]); | ||||||
|  | 		assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1); | ||||||
| 	}); | 	}); | ||||||
| 	it("repeated store one more and get", () => { |  | ||||||
| 		let reviews = []; |  | ||||||
|  |  | ||||||
| 		assert.deepEqual(getReviewsFromStorage(), reviews); | 	it("test localStorage state during adding 999 reviews", () => { | ||||||
|  | 		let reviews = getAllReviewsFromStorage(); | ||||||
|  | 		let ids = [0]; | ||||||
|  |  | ||||||
| 		for(let i = 0; i < 1000; i++){ | 		for(let i = 1; i < 1000; i++){ | ||||||
| 			reviews = getReviewsFromStorage(); | 			ids.push(i); | ||||||
| 			 | 			let new_review = { | ||||||
| 			reviews.push( |  | ||||||
| 				{ |  | ||||||
| 				"imgSrc": `sample src ${i}`, | 				"imgSrc": `sample src ${i}`, | ||||||
| 				"imgAlt": `sample alt ${i}`, | 				"imgAlt": `sample alt ${i}`, | ||||||
| 				"mealName": `sample name ${i}`, | 				"mealName": `sample name ${i}`, | ||||||
| 				"restaurant": `sample restaurant ${i}`, | 				"restaurant": `sample restaurant ${i}`, | ||||||
| 				"rating": i, | 				"rating": i, | ||||||
| 				"tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] | 				"tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			newReviewToStorage(new_review); | ||||||
|  |  | ||||||
|  | 			new_review.reviewID = i; | ||||||
|  | 			reviews.push(new_review); | ||||||
|  |  | ||||||
|  | 			assert.deepEqual(getAllReviewsFromStorage(), reviews); | ||||||
|  | 			assert.deepEqual(getReviewFromStorage(i), new_review); | ||||||
|  | 			assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids); | ||||||
|  | 			assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), (i+1)); | ||||||
| 		} | 		} | ||||||
| 			); | 	}).timeout(5000); | ||||||
| 			saveReviewsToStorage(reviews); |  | ||||||
| 			assert.deepEqual(getReviewsFromStorage(), reviews); | 	it("test localStorage state during updating 1000 reviews", () => { | ||||||
|  | 		let reviews = getAllReviewsFromStorage(); | ||||||
|  | 		let ids = JSON.parse(localStorage.getItem("activeIDS")); | ||||||
|  |  | ||||||
|  | 		for(let i = 0; i < 1000; i++){ | ||||||
|  | 			let new_review = { | ||||||
|  | 				"imgSrc": `updated sample src ${i}`, | ||||||
|  | 				"imgAlt": `updated sample alt ${i}`, | ||||||
|  | 				"mealName": `updated sample name ${i}`, | ||||||
|  | 				"restaurant": `updated sample restaurant ${i}`, | ||||||
|  | 				"rating": i*2+i, | ||||||
|  | 				"tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] | ||||||
|  | 			}; | ||||||
|  | 			new_review.reviewID = i; | ||||||
|  |  | ||||||
|  | 			reviews[i] = new_review; | ||||||
|  |  | ||||||
|  | 			updateReviewToStorage(i, new_review); | ||||||
|  |  | ||||||
|  | 			assert.deepEqual(getAllReviewsFromStorage(), reviews); | ||||||
|  | 			assert.deepEqual(getReviewFromStorage(i), new_review); | ||||||
|  | 			assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids); | ||||||
|  | 			assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000); | ||||||
| 		} | 		} | ||||||
| 	}).timeout(10000); | 	}).timeout(5000); | ||||||
|  |  | ||||||
|  | 	it("test localStorage state during deleting 1000 reviews", () => { | ||||||
|  | 		let reviews = getAllReviewsFromStorage(); | ||||||
|  | 		let ids = JSON.parse(localStorage.getItem("activeIDS")); | ||||||
|  |  | ||||||
|  | 		for(let i = 999; i >= 0; i--){ | ||||||
|  | 			deleteReviewFromStorage(i); | ||||||
|  | 			ids.pop(); | ||||||
|  | 			reviews.pop(); | ||||||
|  |  | ||||||
|  | 			assert.deepEqual(getAllReviewsFromStorage(), reviews); | ||||||
|  | 			assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids); | ||||||
|  | 			assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000); | ||||||
|  | 		} | ||||||
|  | 	}).timeout(5000); | ||||||
|  |  | ||||||
|  | 	after(() => {}); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,18 +1,19 @@ | |||||||
| // main.js | // main.js | ||||||
| import {getReviewsFromStorage, saveReviewsToStorage} from "./localStorage.js"; | import {getAllReviewsFromStorage} from "./localStorage.js"; | ||||||
|  |  | ||||||
| // Run the init() function when the page has loaded | // Run the init() function when the page has loaded | ||||||
| window.addEventListener("DOMContentLoaded", init); | window.addEventListener("DOMContentLoaded", init); | ||||||
|  |  | ||||||
| function init() { | function init() { | ||||||
| 	// Get the reviews from localStorage | 	// Get the reviews from localStorage | ||||||
| 	let reviews = getReviewsFromStorage(); | 	let reviews = getAllReviewsFromStorage(); | ||||||
| 	// Add each reviews to the <main> element | 	// Add each reviews to the <main> element | ||||||
| 	addReviewsToDocument(reviews); | 	addReviewsToDocument(reviews); | ||||||
| 	// Add the event listeners to the form elements | 	// Add the event listeners to the form elements | ||||||
| 	initFormHandler(); | 	initFormHandler(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @param {Array<Object>} reviews An array of reviews |  * @param {Array<Object>} reviews An array of reviews | ||||||
|  */ |  */ | ||||||
| @@ -33,87 +34,9 @@ function addReviewsToDocument(reviews) { | |||||||
|  */ |  */ | ||||||
| function initFormHandler() { | function initFormHandler() { | ||||||
|  |  | ||||||
| 	/* |  | ||||||
| 	//btn to create form (could be its own function?) | 	//btn to create form (could be its own function?) | ||||||
| 	let createBtn = document.getElementById("create"); | 	let createBtn = document.getElementById("create-btn"); | ||||||
| 	createBtn.addEventListener("click", function(){ | 	createBtn.addEventListener("click", function(){ | ||||||
| 		window.location.assign("./CreatePage.html"); | 		window.location.assign("./CreatePage.html"); | ||||||
| 	});*/ |  | ||||||
|  |  | ||||||
| 	//accessing form components |  | ||||||
| 	let tagContainer = document.getElementById("tag-container-form"); |  | ||||||
| 	let form = document.querySelector("form"); |  | ||||||
|    |  | ||||||
| 	form.addEventListener("submit", function(){ |  | ||||||
| 	/* |  | ||||||
|     *  User submits the form for their review. |  | ||||||
|     *  We create reviewCard and put in storage |  | ||||||
|     */ |  | ||||||
| 		let formData = new FormData(form); |  | ||||||
| 		let reviewObject = {}; |  | ||||||
| 		for (let [key, value] of formData) { |  | ||||||
| 			console.log(`${key}`); |  | ||||||
| 			console.log(`${value}`); |  | ||||||
| 			if (`${key}` !== "tag-form") { |  | ||||||
| 				reviewObject[`${key}`] = `${value}`; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		reviewObject["tags"] = []; |  | ||||||
|  |  | ||||||
| 		let tags = document.querySelectorAll(".tag"); |  | ||||||
| 		for(let i = 0; i < tags.length; i ++) { |  | ||||||
| 			reviewObject["tags"].push(tags[i].innerHTML); |  | ||||||
| 			tagContainer.removeChild(tags[i]); |  | ||||||
| 		} |  | ||||||
|      |  | ||||||
|  |  | ||||||
| 		let newReview = document.createElement("review-card"); |  | ||||||
| 		newReview.data = reviewObject; |  | ||||||
|  |  | ||||||
| 		//TODO: want to append it to whatever the box is in layout  |  | ||||||
| 		let mainEl = document.querySelector("main"); |  | ||||||
| 		mainEl.append(newReview); |  | ||||||
|  |  | ||||||
| 		let storedReviews = getReviewsFromStorage(); |  | ||||||
| 		storedReviews.push(reviewObject); |  | ||||||
| 		saveReviewsToStorage(storedReviews); |  | ||||||
| 		document.getElementById("new-food-entry").reset(); |  | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	// DEV-MODE: for testing purposes  |  | ||||||
| 	let clearBtn = document.querySelector(".danger"); |  | ||||||
| 	clearBtn.addEventListener("click", function() { |  | ||||||
| 		localStorage.clear(); |  | ||||||
| 		let mainEl = document.querySelector("main"); |  | ||||||
| 		while (mainEl.firstChild) { |  | ||||||
| 			mainEl.removeChild(mainEl.firstChild); |  | ||||||
| 		} |  | ||||||
| 		let deleteTags = document.querySelectorAll(".tag"); |  | ||||||
| 		for(let i = 0; i < deleteTags.length; i ++) { |  | ||||||
| 			tagContainer.removeChild(deleteTags[i]); |  | ||||||
| 		} |  | ||||||
|      |  | ||||||
| 		//clears reviews AS WELL as resets form |  | ||||||
| 		document.getElementById("new-food-entry").reset(); |  | ||||||
|       |  | ||||||
|       |  | ||||||
| 	}); |  | ||||||
|  |  | ||||||
| 	let tagAddBtn = document.getElementById("tagAdd"); |  | ||||||
| 	tagAddBtn.addEventListener("click", ()=> { |  | ||||||
| 		let tagField = document.getElementById("tag-form"); |  | ||||||
| 		if (tagField.value.length > 0) { |  | ||||||
| 			let tagLabel = document.createElement("label"); |  | ||||||
| 			tagLabel.innerHTML = tagField.value; |  | ||||||
| 			tagLabel.setAttribute("class","tag"); |  | ||||||
| 			tagLabel.addEventListener("click",()=> { |  | ||||||
| 				tagContainer.removeChild(tagLabel); |  | ||||||
| 			}); |  | ||||||
|        |  | ||||||
| 			tagContainer.append(tagLabel); |  | ||||||
| 			tagField.value = ""; |  | ||||||
|  |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -22,58 +22,6 @@ | |||||||
|   <main> |   <main> | ||||||
|     <!-- Add Food Entries Here --> |     <!-- Add Food Entries Here --> | ||||||
|   </main> |   </main> | ||||||
|   <!--<button type="button" id="create">CREATE</button>--> |   <button type="button" id="create-btn"><a href='./CreatePage.html'></a>CREATE</button> | ||||||
|   <!----> <form id="new-food-entry"> |  | ||||||
|     <fieldset> |  | ||||||
|       <legend>Pic:</legend> |  | ||||||
|       <label for="mealImage"> |  | ||||||
|         Source: |  | ||||||
|         <input type="text" id="mealImg" name="mealImg"> |  | ||||||
|       </label> |  | ||||||
|       <label for="image-alt"> |  | ||||||
|         Alt Text: |  | ||||||
|         <input type="text" id="imgAlt" name="imgAlt"> |  | ||||||
|       </label> |  | ||||||
|     </fieldset> |  | ||||||
|     <fieldset> |  | ||||||
|  |  | ||||||
|       <legend> Meal: </legend> |  | ||||||
|       <label for="Meal: ">Meal: |  | ||||||
|         <input type="text" id="mealName" name="mealName" required> |  | ||||||
|       </label> |  | ||||||
|       <label for="comments">Comments:  |  | ||||||
|         <br> |  | ||||||
|         <textarea name="comments" id="comments"></textarea> |  | ||||||
|       </label> |  | ||||||
|     </fieldset> |  | ||||||
|      |  | ||||||
|     <fieldset class="rating"> |  | ||||||
|       <legend> Rating: </legend> |  | ||||||
|       <input type="radio" id="s5" name="rating" value="5"/> <label for="s5"> 5 stars </label> |  | ||||||
|       <input type="radio" id="s4" name="rating" value="4"/> <label for="s4"> 4 stars </label> |  | ||||||
|       <input type="radio" id="s3" name="rating" value="3"/> <label for="s3"> 3 stars </label> |  | ||||||
|       <input type="radio" id="s2" name="rating" value="2"/> <label for="s2"> 2 stars </label> |  | ||||||
|       <input type="radio" id="s1" name="rating" value="1"/> <label for="s1"> 1 star </label> |  | ||||||
|     </fieldset> |  | ||||||
|  |  | ||||||
|     <fieldset> |  | ||||||
|       <legend>Other Info:</legend> |  | ||||||
|       <label for="restaurant"> |  | ||||||
|         Restaurant: |  | ||||||
|         <input type="text" id="restaurant" name="restaurant" required> |  | ||||||
|       </label> |  | ||||||
|       <label for="tag-form"> |  | ||||||
|         Tags: |  | ||||||
|         <input type="text" id="tag-form" name="tag-form"> |  | ||||||
|         <div class='tag-container' id="tag-container-form"> |  | ||||||
|  |  | ||||||
|         </div> |  | ||||||
|         <button type="button" id="tagAdd">Add Tag</button> |  | ||||||
|       </label> |  | ||||||
|  |  | ||||||
|     </fieldset> |  | ||||||
|     <button type="submit" value="Submit">Add Review</button> |  | ||||||
|     <button type="button" class="danger">Clear Review Journal</button> |  | ||||||
|   </form> <!----> |  | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -1,16 +0,0 @@ | |||||||
| <!DOCTYPE html> |  | ||||||
| <html lang="en"> |  | ||||||
| <head> |  | ||||||
|     <meta charset="UTF-8" /> |  | ||||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge" /> |  | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |  | ||||||
|     <title>Food Journal</title> |  | ||||||
|      |  | ||||||
|     <script src="assets/scripts/reviewpage.js" type="module"></script> |  | ||||||
| </head> |  | ||||||
| <body> |  | ||||||
|     <h1>Current Review:</h1> |  | ||||||
|     <main> |  | ||||||
|     </main> |  | ||||||
| </body> |  | ||||||
| </html> |  | ||||||
		Reference in New Issue
	
	Block a user