diff --git a/.glitch-assets b/.glitch-assets
new file mode 100644
index 00000000..e69de29b
diff --git a/README.md b/README.md
index 493995c1..63192ab5 100644
--- a/README.md
+++ b/README.md
@@ -1,100 +1,32 @@
-Assignment 2 - Short Stack: Basic Two-tier Web Application using HTML/CSS/JS and Node.js
-===
+## Shopping List
-Due: September 11th, by 11:59 AM.
+Website link: https://a2-javieira.glitch.me/
-This assignment aims to introduce you to creating a prototype two-tiered web application.
-Your application will include the use of HTML, CSS, JavaScript, and Node.js functionality, with active communication between the client and the server over the life of a user session.
+This Shopping List Application was designed to help users keep track of the items they would like to purchase and how much the total cost is compared to their budget. The user begins by filling out a budget if they would like. This budget is updated to the right of where they enter this figure as “Total Budget.” Alongside this label are the “Total Cost” and “Remaining Budget” labels which display how much all the items cost and the difference between the budget and total cost. If the user does not enter a budget, the budget and remaining budget labels will remain at $0.00, which is also the case if a NaN is entered. Below this section is where they can add in items. The sections that are required are the item, quantity, price, and product type. Each of these fields are marked with an aria label, the * symbol, so that the user knows they are required fields. In addition, there is CSS to outline the required fields in a red glow when they are not properly filled in. The user may also choose to write down some notes if they want to keep track of their purchase for each item, however this field is not required. If the user does not fill out a required field, a banner will appear at the top stating which field still needs to be filled out. Once the item is successfully entered into the server, the table is automatically updated with the new item. The derived field in this project is the cost for a quantity of items. This value is stored for each item and summed to find the total cost. This is found and added to the server data by multiplying the quantity and the price per item that the user enters. If the user accidentally reloads the page, the table will also repopulate so they are always aware of which items they have stored. The table displays all the information the user provided and in each row, there is a remove button which will take out the unwanted item. Further, when the item is submitted, the total cost and remaining budget are adjusted accordingly at the top of the screen. To format this project using CSS, multiple flex boxes were used. A flex box was used for the table so that the width could be set to 100% without running off the page as there is also padding. Another flexbox contains the budget information at the top of the screen. Inside this flexbox, a secondary flexbox sits so that the labels and input area could be formatted side by side while the labels, button, and input area themselves remained in columns. A similar technique was used in the add item section since the quantity and price fields were situated in columns for their respective labels and input boxes and then side by side. Then the entire add item section was encapsulated into another flexbox for further styling.The margins, padding, fonts, and colors were also manipulated using the classes defined by the flexboxes. In addition, individual elements, such as the buttons, and sections, such as the table rows and columns, were called separate from the flexboxes for CSS styling. I would also like to make a note about the validation baseline requirement. I went through and fixed all the errors that were given, but I was still given a couple warnings about unnecessary / in the HTML. This was a recurring problem as using the “prettier” function in Glitch adds in these extra slashes. In addition, there was another warning about the aria label which marked the label as a required field with the asterisk *. This is something I pulled directly from the forms link that was included in this assignment. I also collected all my fonts from Google fonts. These fonts made up the button, label, table, and title fonts.
-Baseline Requirements
----
-
-There is a large range of application areas and possibilities that meet these baseline requirements.
-Try to make your application do something useful! A todo list, storing / retrieving high scores for a very simple game... have a little fun with it.
-
-Your application is required to implement the following functionalities:
-
-- a `Server` which not only serves files, but also maintains a tabular dataset with 3 or more fields related to your application
-- a `Results` functionality which shows the entire dataset residing in the server's memory
-- a `Form/Entry` functionality which allows a user to add or delete data items residing in the server's memory
-- a `Server Logic` which, upon receiving new or modified "incoming" data, includes and uses a function that adds at least one additional derived field to this incoming data before integrating it with the existing dataset
-- the `Derived field` for a new row of data must be computed based on fields already existing in the row.
-For example, a `todo` dataset with `task`, `priority`, and `creation_date` may generate a new field `deadline` by looking at `creation_date` and `priority`
-
-Your application is required to demonstrate the use of the following concepts:
-
-HTML:
-- One or more [HTML Forms](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms), with any combination of form tags appropriate for the user input portion of the application
-- A results page displaying all data currently available on the server. You will most likely use a `
` tag for this, but `
` or `` could also work and might be simpler to work with. Alternatively, you can create a single-page app (see Technical Acheivements) but this is not a requirement.
-- All pages should [validate](https://validator.w3.org)
-- If your app contains multple pages, they should all be accessible from the homepage (index.html)
-
-CSS:
-- CSS styling of the primary visual elements in the application
-- Various CSS Selector functionality must be demonstrated:
- - Element selectors
- - ID selectors
- - Class selectors
-- CSS positioning and styling of the primary visual elements in the application:
- - Use of either a CSS grid or flexbox for layout
- - Rules defining fonts for all text used; no default fonts! Be sure to use a web safe font or a font from a web service like [Google Fonts](http://fonts.google.com/)
-
-- CSS defined in a maintainable, readable form, in external stylesheets
-
-JavaScript:
-- At minimum, a small amount of front-end JavaScript to get / fetch data from the server; a sample is provided in this repository.
-
-Node.js:
-- An HTTP Server that delivers all necessary files and data for the application, and also creates the required `Derived Fields` in your data.
-A starting point is provided in this repository.
-
-Deliverables
----
-
-Do the following to complete this assignment and acheive a base grade of 85%:
-
-1. Fork the starting project code (make sure to fork the 2023 repo!). This repo contains some starter code that may be used or discarded as needed.
-2. Implement your project with the above requirements.
-3. Test your project to make sure that when someone goes to your main page, it displays correctly.
-4. Deploy your project to Glitch, and fill in the appropriate fields in your package.json file.
-5. Ensure that your project has the proper naming scheme `a2-yourGithubUsername` so we can find it.
-6. Modify the README to the specifications below, and delete all of the instructions originally found in this README.
-7. Create and submit a Pull Request to the original repo. Label the pull request as follows: a2-gitusername-firstname-lastname
-
-Acheivements
----
-
-Below are suggested technical and design achievements. You can use these to help boost your grade up to an A and customize the assignment to your personal interests. These are recommended acheivements, but feel free to create/implement your own... just make sure you thoroughly describe what you did in your README and why it was challenging. ALL ACHIEVEMENTS MUST BE DESCRIBED IN YOUR README IN ORDER TO GET CREDIT FOR THEM. Remember, the highest grade you can get on any individual assignment is a 100%.
-
-*Technical*
-- (5 points) Create a single-page app that both provides a form for users to submit data and always shows the current state of the server-side data. To put it another way, when the user submits data, the server should respond sending back the updated data (including the derived field calculated on the server) and the client should then update its data display.
-
-- (5 points) In addition to a form enabling adding and deleting data on the server, also add the ability to modify existing data.
-
-*Design/UX*
-- (5 points per person, with a max of 10 points) Test your user interface with other students in the class. Define a specific task for them to complete (ideally something short that takes <10 minutes), and then use the [think-aloud protocol](https://en.wikipedia.org/wiki/Think_aloud_protocol) to obtain feedback on your design (talk-aloud is also fine). Important considerations when designing your study:
-
-1. Make sure you start the study by clearly stating the task that you expect your user to accomplish.
-2. You shouldn't provide any verbal instructions on how to use your interface / accomplish the task you give them. Make sure that your interface is clear enough that users can figure it out without any instruction, or provide text instructions from within the interface itself.
-3. If users get stuck to the point where they give up, you can then provde instruction so that the study can continue, but make sure to discuss this in your README. You won't lose any points for this... all feedback is good feedback!
-
-You'll need to use sometype of collaborative software that will enable you both to see the test subject's screen and listen to their voice as they describe their thoughts, or conduct the studies in person. After completing each study, briefly (one to two sentences for each question) address the following in your README:
-
-1. Provide the last name of each student you conduct the evaluation with.
-2. What problems did the user have with your design?
-3. What comments did they make that surprised you?
-4. What would you change about the interface based on their feedback?
-
-*You do not need to actually make changes based on their feedback*. This acheivement is designed to help gain experience testing user interfaces. If you run two user studies, you should answer two sets of questions.
-
-Sample Readme (delete the above when you're ready to submit, and modify the below so with your links and descriptions)
----
+## Technical Achievements
-## Your Web Application Title
-Include a very brief summary of your project here. Be sure to include the CSS positioning technique you used, and any required instructions to use your application.
+- **Tech Achievement 1**:
-## Technical Achievements
-- **Tech Achievement 1**: Using a combination of...
+I completed the first technical achievement which provided a form for the user to submit data and always shows the current state of the server side data. In order to accomplish this, when the user submits new data, a showResults function is called in the main.js file which is responsible for updating the table immediately. In addition, in the window.onload function, the same showResults function is called such that the data is repopulated each time the page is reloaded. This solves the issue where a user initially goes onto the page, enters a new item, and then is shown a list of items they may have forgotten were added to the server. The derived field is also updated each time a user enters a new item. This derived field is the cost, which is calculated by multiplying the quantity by the unit price for each item.
### Design/Evaluation Achievements
-- **Design Achievement 1**:
+- **Design Achievement 1**:
+
+Provide the last name of each student you conduct the evaluation with.
+Juliana Porto
+What problems did the user have with your design?
+There was a problem with the total cost and remaining budget calculations when items were removed that I did not come across at first. When an item was removed, the total cost and remaining budget would not update immediately and therefore show an inaccurate amount.
+What comments did they make that surprised you?
+It was also suggested that the budget be placed further up on the screen so that the user could alter that prior to entering their items. This is not something I had thought of before but makes sense since the user will want to see their remaining budget as items are added. She did mention that the red outline of the required fields was handy to identify which fields were required.
+What would you change about the interface based on their feedback?
+I did change both of these issues. The total cost and remaining budget label changes were put into a separate function so I now call it every time a table is updated regardless of whether items were added or removed. In addition, I did move the budget to the top of the page so the user can enter this information first if they choose.
+
+Provide the last name of each student you conduct the evaluation with.
+Nicole Burgess
+What problems did the user have with your design?
+Nicole’s problems with my design were similar to Julianna’s problems which I thought was interesting that they had such a similar experience. She also discovered the issue with the budget and total cost being slightly off when certain items were removed. In addition, Nicole also mentioned that the budget should be moved to the top as she was unclear whether it was a budget for the whole trip or each individual item.
+What comments did they make that surprised you?
+She also brought up the point that my label was unclear when asking for the price. I asked the user for the price of the item, but did not specify that I wanted the unit price. This was misinterpreted to be the price for the item at a certain quantity, which defeats the purpose of the derived field cost column.
+What would you change about the interface based on their feedback?
+As mentioned above, I fixed the issues in regard to the budget labels being moved to the top and the labels updating properly. I also edited the price label so that it asks for the unit price rather than any price.
diff --git a/package.json b/package.json
index 988f135f..85719f1c 100644
--- a/package.json
+++ b/package.json
@@ -1,12 +1,12 @@
{
"name": "",
- "version": "",
- "description": "",
+ "version": "0.1.0",
+ "description": "A2 Short Stack: Basic Two-tier Web Application using HTML/CSS/JS and Node.js",
"author": "",
"scripts": {
"start": "node server.improved.js"
},
"dependencies": {
- "mime": "^2.4.4"
+ "mime": "^3.0.0"
}
-}
+}
\ No newline at end of file
diff --git a/public/css/main.css b/public/css/main.css
index 7cf6207b..f9f99088 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -1,4 +1,193 @@
-body {
- background:black;
- color:white;
+:root{
+ --paleGray: #DBE4F5;
+ --navy: #00388A;
+ --royal: #004D9E;
+ --lightBlue: #AEC5F5;
+ --cream: #FEFBF0;
+ --fontSizeTitle: 45px;
+ --fontSizeLabels: 20px;
+ --fontSizeInput: 15px;
+}
+
+body{
+ background-color: var(--lightBlue);
+}
+
+#title{
+ font-family: 'Cinzel Decorative', cursive;
+ font-Size: var(--fontSizeTitle);
+ text-align: center;
+ color: var(--lightBlue);
+ background-color: var(--navy);
+ padding: 20px;
+ border:10px solid var(--cream);
+ text-shadow: 2px 2px 2px black;
+ margin: 20px;
+}
+
+/*
+Encapsulates budgetBox and labelsBox
+*/
+.budgetCost{
+ display: flex;
+ justify-content: center;
+ margin-left: 40px;
+ margin-right: 40px;
+ color: var(--navy);
+ background-color: var(--paleGray);
+ padding: 20px;
+ border:10px solid var(--cream);
+ margin-top: 40px;
+ margin-bottom: 40px;
+ justify-content: space-evenly;
+ font-size: var(--fontSizeLabels);
+ font-family: 'Comfortaa', cursive;
+}
+
+.budgetBox{
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ background-color: var(--forest);
+}
+
+.labelsBox{
+ display: flex;
+ flex-direction: column;
+ justify-content: space-evenly;
+ background-color: var(--bright);
+ font-weight: bold;
+}
+
+/*
+Encapsulates numbersInput
+*/
+.itemBox{
+ display: flex;
+ justify-content: center;
+ margin-left: 40px;
+ margin-right: 40px;
+ color: var(--navy);
+ background-color: var(--paleGray);
+ padding: 20px;
+ border:10px solid var(--cream);
+ margin-top: 40px;
+ margin-bottom: 40px;
+ font-size: var(--fontSizeLabels);
+ font-family: 'Comfortaa', cursive;
+}
+
+/*
+Encapsulates priceInput and quantity Input
+*/
+.numbersInput{
+ display: flex;
+ background-color: var(--deep);
+ justify-content: space-evenly;
+ margin-top: 5px;
+ margin-bottom: 5px;
+}
+
+.quantityInput{
+ display: flex;
+ background-color: var(--light);
+ flex-direction: column;
+ width: 100%;
+ margin-left: 20px;
+}
+
+.priceInput{
+ display: flex;
+ background-color: var(--light);
+ flex-direction: column;
+ width: 100%;
+ margin-right: 20px;
+}
+
+/*
+Table box
+*/
+.itemTable{
+ display: flex;
+ font-size: var(--fontSizeLabels);
+}
+
+input[type="text"],
+input[type="number"],
+textarea,
+fieldset {
+ width: 100%;
+ border: 1px solid #333333;
+ box-sizing: border-box;
+ font-size: var(--fontSizeInput);
+}
+
+/*
+red outline on required field boxes
+*/
+input:invalid {
+ box-shadow: 0 0 5px 1px red;
+}
+
+input:focus:invalid {
+ box-shadow: none;
+}
+
+/*
+table rules
+*/
+table, th, td {
+ border: 1px solid black;
+ color: black;
+ font-size: var(--fontSizeLabels);
+}
+/*
+table header
+*/
+th{
+ background-color: var(--navy);
+ color: white;
+ font-family: 'Changa', sans-serif;
+}
+/*
+table rows
+*/
+td{
+ font-family: 'Changa', sans-serif;
+}
+table{
+ width: 100%;
+ table-layout: fixed;
+ background-color: var(--cream);
+ margin-left: 40px;
+ margin-right: 40px;
+}
+
+/*
+button rules
+*/
+#removeButton{
+ width: 100%;
+ height: 100%;
+ font-size: var(--fontSizeInput);
+ background-color: var(--navy);
+ color: white;
+ font-family: 'Changa', sans-serif;
+}
+
+#addItem{
+ width: 100%;
+ font-size: var(--fontSizeInput);
+ background-color: var(--navy);
+ color: white;
+ font-family: 'Comfortaa', cursive;
+}
+
+#addBudget{
+ width: 100%;
+ font-size: var(--fontSizeInput);
+ margin-top: 5px;
+ background-color: var(--navy);
+ color: white;
+ font-family: 'Comfortaa', cursive;
}
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index 59d90d3b..bb618b46 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,18 +1,133 @@
-
+
- CS4241 Assignment 2
-
+
-
-
-
-
+
+
+
+
+ Grocery List
-
+
Shopping List
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Item
+
Quantity
+
Price
+
Cost
+
Product Type
+
Product Details
+
Remove Item
+
+
+
diff --git a/public/js/main.js b/public/js/main.js
index a569258f..1dfbd3c2 100644
--- a/public/js/main.js
+++ b/public/js/main.js
@@ -1,27 +1,213 @@
-// FRONT-END (CLIENT) JAVASCRIPT HERE
-
-const submit = async function( event ) {
- // stop form submission from trying to load
- // a new .html page for displaying results...
- // this was the original browser behavior and still
- // remains to this day
- event.preventDefault()
-
- const input = document.querySelector( '#yourname' ),
- json = { yourname: input.value },
- body = JSON.stringify( json )
+/*
+Constants used to keep track of user's total grocery budget and
+what they are spending
+defaultValue: fixed so prices formatted with two decimal places
+totalCost: total cost of groceries
+budget: user input budget
+remaining: difference between budget and totalCost
+*/
+let defaultValue = 0;
+defaultValue = defaultValue.toFixed(2);
+let totalCost = defaultValue;
+let budget = defaultValue;
+let remaining = defaultValue;
+
+/*
+This is a function to handle the submit action in the addItem button
+Variables item, quantity, price, productType, and productDetails are
+collected from user input
+If any of the input values is missing, a validation error will pop
+up at the top of the screen stating which field is missing
+Json object created using this data and showResults function is called
+*/
+const submit = async function (event) {
+ event.preventDefault();
+ const item = document.querySelector("#item");
+ const quantity = document.querySelector("#quantity");
+ const price = document.querySelector("#price");
+ const productType = document.querySelector("#productType");
+ const productDetails = document.querySelector("#productDetails");
+
+ //Validation error messages
+ if (item.value === "") {
+ window.alert("Please fill out item");
+ return;
+ } else if (quantity.value === "") {
+ window.alert("Please fill out quantity");
+ return;
+ } else if (price.value === "") {
+ window.alert("Please fill out price");
+ return;
+ } else if (productType.value === "") {
+ window.alert("Please fill out product type");
+ return;
+ }
- const response = await fetch( '/submit', {
- method:'POST',
- body
+ //Create json object with user input
+ const json = {
+ item: item.value,
+ quantity: quantity.value,
+ price: price.value,
+ productType: productType.value,
+ productDetails: productDetails.value,
+ };
+ const body = JSON.stringify(json);
+ const response = await fetch("/submit", {
+ method: "POST",
+ body,
+ });
+ let data = await response.json();
+
+ //Display table of data
+ showResults(data, false);
+};
+
+/*
+This is a function to handle the remove action in the removeItem button
+When an item is removed, the table is automatically updated along
+with the total cost label and remaining budget label
+When all items are removed, the table should just show the header
+*/
+const remove = async function (item) {
+ let json = { removeItem: item };
+ let body = JSON.stringify(json);
+ fetch("/remove", {
+ method: "DELETE",
+ body,
})
+ .then((response) => response.json())
+ .then((json) => {
+ showResults(json, true);
+ });
+ return false;
+};
+
+/*
+Constantly updates the table each time an item is added or removed
+If the page is reloaded, all items in the server will still display
+Each time an item is added, a new row in the table will appear
+When an item is added, the remaining budget and total cost are
+adjusted accordingly
+*/
+const showResults = function (data, pageReloaded) {
+ let cost = 0.0; // initial cost for new item
+ let resultsTable = document.querySelector("#resultsTable"); // table
+ // when page reloaded or item is removed, all items in server
+ // must be added back to table
+ if (pageReloaded) {
+ // add header in table
+ resultsTable.innerHTML =
+ "
Item
Quantity
Price
Cost
Product Type
Product Details
Remove Item
";
+ // for each item in server, add back data
+ data.forEach((grocery) => {
+ formatTable(grocery, resultsTable);
+ });
+ }
+
+ // if a new item is added
+ else {
+ // get the last added element in json Object
+ const update = data.at(-1);
+ // update table
+ formatTable(update, resultsTable);
+ }
+
+ totalCost = defaultValue; // reset cost
+ // for each item in server, add its cost to totalCost
+ data.forEach((item) => {
+ cost = parseFloat(item.cost);
+ totalCost = (parseFloat(totalCost) + parseFloat(cost)).toFixed(2);
+ });
+
+ // update budgets and cost labels
+ updateBudgetCostLabels();
+};
- const text = await response.text()
+/*
+Updates table
+Adds row each time an item is added
+Gets the correct attribute value from the json Object element
+*/
+const formatTable = function (grocery, resultsTable) {
+ console.log(resultsTable);
+ // get item price and format it to have 2 decimals
+ let price = parseFloat(grocery.price).toFixed(2);
+ // format strings to have dollar sign
+ let priceText = toPriceString(price);
+ let costText = toPriceString(grocery.cost);
+ // create new row in table
+ const row = resultsTable.insertRow();
+ const cellItem = row.insertCell(); // create new cell
+ cellItem.innerHTML = grocery.item; // add data to cell
+ const cellQuantity = row.insertCell(); // create new cell
+ cellQuantity.innerHTML = grocery.quantity; // add data to cell
+ const cellPrice = row.insertCell(); // create new cell
+ cellPrice.innerHTML = priceText; // add data to cell
+ const cellCost = row.insertCell(); // create new cell
+ cellCost.innerHTML = costText; // add data to cell
+ const cellProductType = row.insertCell(); // create new cell
+ cellProductType.innerHTML = grocery.productType; // add data to cell
+ const cellProductDetails = row.insertCell(); // create new cell
+ cellProductDetails.innerHTML = grocery.productDetails; // add data to cell
+ // in last column, create a button to remove items
+ row.innerHTML += ``;
+};
- console.log( 'text:', text )
-}
+/*
+Formats strings so they have a dollar sign, negative sign if
+applicable, and two decimal places
+*/
+const toPriceString = function (price) {
+ if (price >= 0) {
+ return "$" + `${price.toString()}`;
+ } else {
+ return "-$" + `${(price * -1).toString()}`;
+ }
+};
-window.onload = function() {
- const button = document.querySelector("button");
- button.onclick = submit;
-}
\ No newline at end of file
+/*
+Allows user to create or modify budget for entire shopping trip
+*/
+const addBudget = function () {
+ // get budget input by user
+ let budgetInput = document.querySelector("#budgetInput").value;
+ // format budget so it is a float with 2 decimal places
+ budget = parseFloat(budgetInput).toFixed(2);
+ // if budget is not a number, set to 0; otherwise set to budget
+ budget = isNaN(budget) ? defaultValue : budget;
+ // update labels
+ updateBudgetCostLabels();
+};
+
+/*
+Update the labels for the total budget, total cost, and remaining
+budget for the grocery trip
+*/
+const updateBudgetCostLabels = function () {
+ // get labels
+ let totalBudgetLabel = document.querySelector("#totalBudget");
+ let totalCostLabel = document.querySelector("#totalCost");
+ let remainingBudgetLabel = document.querySelector("#remainingBudget");
+ // if budget is not 0, update the remaining budget
+ if (budget != 0) {
+ remaining = isNaN(budget) || isNaN(totalCost) ? defaultValue : budget - totalCost;
+ remaining = remaining.toFixed(2);
+ }
+ // update labels
+ totalBudgetLabel.innerHTML = "Total Budget: " + toPriceString(budget);
+ totalCostLabel.innerHTML = "Total Cost: " + toPriceString(totalCost);
+ remainingBudgetLabel.innerHTML = "Remaining Budget: " + toPriceString(remaining);
+};
+
+window.onload = function () {
+ const addItem = document.querySelector("#addItem");
+ const removeItem = document.querySelector("#removeItem");
+ addItem.onclick = submit;
+ fetch("/data", {
+ method: "GET",
+ })
+ .then((response) => response.json())
+ .then((json) => {
+ showResults(json, true);
+ });
+};
diff --git a/server.improved.js b/server.improved.js
index 9ac27fb8..3d4533c3 100644
--- a/server.improved.js
+++ b/server.improved.js
@@ -1,74 +1,95 @@
-const http = require( 'http' ),
- fs = require( 'fs' ),
- // IMPORTANT: you must run `npm install` in the directory for this assignment
- // to install the mime library if you're testing this on your local machine.
- // However, Glitch will install it automatically by looking in your package.json
- // file.
- mime = require( 'mime' ),
- dir = 'public/',
- port = 3000
-
-const appdata = [
- { 'model': 'toyota', 'year': 1999, 'mpg': 23 },
- { 'model': 'honda', 'year': 2004, 'mpg': 30 },
- { 'model': 'ford', 'year': 1987, 'mpg': 14}
-]
-
-const server = http.createServer( function( request,response ) {
- if( request.method === 'GET' ) {
- handleGet( request, response )
- }else if( request.method === 'POST' ){
- handlePost( request, response )
+const http = require("http"),
+ fs = require("fs"),
+ mime = require("mime"),
+ dir = "public/",
+ port = 3000;
+
+let groceryList = [];
+
+const server = http.createServer(function (request, response) {
+ if (request.method === "GET") {
+ handleGet(request, response);
+ } else if (request.method === "POST") {
+ handlePost(request, response);
}
-})
-
-const handleGet = function( request, response ) {
- const filename = dir + request.url.slice( 1 )
-
- if( request.url === '/' ) {
- sendFile( response, 'public/index.html' )
- }else{
- sendFile( response, filename )
+ else if (request.method === 'DELETE') {
+ handleDelete(request, response)
}
-}
-
-const handlePost = function( request, response ) {
+});
+const handleGet = function (request, response) {
+ const filename = dir + request.url.slice(1);
+ if (request.url === "/") {
+ sendFile(response, "public/index.html");
+ } else if (request.url === "/data") {
+ console.log(JSON.stringify(groceryList));
+ response.writeHeader(200, { "Content-type": "text/json" });
+ response.end(JSON.stringify(groceryList));
+ } else {
+ sendFile(response, filename);
+ }
+};
+const handlePost = function (request, response) {
+ console.log("request URL" + request.url);
+ let dataString = "";
+ request.on("data", function (data) {
+ dataString += data;
+ });
+ request.on("end", function () {
+ let item = JSON.parse(dataString);
+ let cost = getCost(item.price, item.quantity);
+ groceryList.push({
+ item: item.item,
+ quantity: item.quantity,
+ price: item.price,
+ cost: cost,
+ productType: item.productType,
+ productDetails: item.productDetails,
+ });
+ response.writeHead(200, "OK", { "Content-Type": "text/json" });
+ response.end(JSON.stringify(groceryList));
+ });
+};
+const handleDelete = function (request, response) {
let dataString = ''
-
- request.on( 'data', function( data ) {
- dataString += data
+ request.on('data', function (data) {
+ dataString += data
})
-
- request.on( 'end', function() {
- console.log( JSON.parse( dataString ) )
-
- // ... do something with the data here!!!
-
- response.writeHead( 200, "OK", {'Content-Type': 'text/plain' })
- response.end('test')
+ request.on('end', function () {
+ let removeItem = JSON.parse(dataString).removeItem
+
+ let index = -1;
+ for(let i = 0; i < groceryList.length; i++){
+ if(groceryList[i].item === removeItem){
+ index = i;
+ }
+ }
+ if(index != -1){
+ groceryList.splice(index, 1);
+ }
+
+ response.writeHead(200, "OK", { 'Content-Type': 'text/plain' })
+ response.end(JSON.stringify(groceryList))
})
}
-
-const sendFile = function( response, filename ) {
- const type = mime.getType( filename )
-
- fs.readFile( filename, function( err, content ) {
-
- // if the error = null, then we've loaded the file successfully
- if( err === null ) {
-
- // status code: https://httpstatuses.com
- response.writeHeader( 200, { 'Content-Type': type })
- response.end( content )
-
- }else{
-
- // file not found, error code 404
- response.writeHeader( 404 )
- response.end( '404 Error: File Not Found' )
-
- }
- })
+const sendFile = function (response, filename) {
+ const type = mime.getType(filename);
+ fs.readFile(filename, function (err, content) {
+ // if the error = null, then we've loaded the file successfully
+ if (err === null) {
+ // status code: https://httpstatuses.com
+ response.writeHeader(200, { "Content-Type": type });
+ response.end(content);
+ } else {
+ // file not found, error code 404
+ response.writeHeader(404);
+ response.end("404 Error: File Not Found");
+ }
+ });
+};
+
+const getCost = function (price, quantity){
+ let priceItem = parseFloat(price).toFixed(2);
+ return parseFloat(quantity * priceItem).toFixed(2).toString();
}
-server.listen( process.env.PORT || port )
+server.listen(process.env.PORT || port);
diff --git a/shrinkwrap.yaml b/shrinkwrap.yaml
new file mode 100644
index 00000000..7cc43d7c
--- /dev/null
+++ b/shrinkwrap.yaml
@@ -0,0 +1,15 @@
+dependencies:
+ mime: 3.0.0
+packages:
+ /mime/3.0.0:
+ dev: false
+ engines:
+ node: '>=10.0.0'
+ hasBin: true
+ resolution:
+ integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==
+registry: 'https://registry.npmjs.org/'
+shrinkwrapMinorVersion: 9
+shrinkwrapVersion: 3
+specifiers:
+ mime: ^3.0.0