diff --git a/.env b/.env new file mode 100644 index 0000000..5ffd66a --- /dev/null +++ b/.env @@ -0,0 +1,6 @@ +DB_NAME=delivereat_db +DB_USERNAME= +DB_PASSWORD= + +accountSid=ACabafbc79c1c76c070ea7300972ef7e05 +authToken=d3e4758f3da08a0e569c8355712fd333 diff --git a/README.md b/README.md index 9530e57..f46597c 100644 --- a/README.md +++ b/README.md @@ -1,83 +1,15 @@ -# Delivereat - -In this project we will create a database backed version of Delivereat. We will build it as a new project, but feel free to use your original Delivereat project as reference. Be aware that because the data structures we will be working with here are likely to be different, it may not be possible to directly re-use your UI components. - -A few notes before we get started - -* Fork and clone this repo -* Start by building the simplest thing that works. Add to it as you go along. Test your application as frequently as possible to make sure it does what you expect -* Commit frequently and push to Github -* Implement features one at a time -* Make sure your app is responsive -* You may want to design the API first, before implementing the UI that uses and API - -## Features - -**Database and API** - -* Design a database that will allow you to store a menu and orders. Start out with pen and paper first sketching out the tables and columns you will need, as well as the relationships between the tables. -* The database will need to store a menu which will contain item name and price. We will also need to store orders. Each order can have multiple menu items and each menu item can appear in multiple orders. Each menu item ordered will also need to have a quantity. -* Store the SQL commands used to create database and populate with initial data in a `database.sql` file in your repo. It will allow us to review your database code and also make it easy for you to rebuild database. -* Create a RESTful API that will allow you to get the menu and save new orders -* Test the API using Postman - -**Menu** -* Design and build a front end UI that will load the menu from the API and display it to the user - -**Order** - -* Update the menu page to make it an order page -* It should allow the user to specify quantities of items to order -* It should add a delivery charge and display the total order cost -* Create functionality to submit orders to the API and display a notification to the user with order id - -## Stretch goals - -**Own feature** - -* Design and implement a feature of your choosing - -**SMS notification** - -* Add a phone number input to your UI and a column in orders table to store it. -* Update the API to receive the phone number as part of the order -* Sign up for an account with Twilio. It's an API that allows you to send SMS messages and do lots of other cool things with phones. Use the signup code WELOVECODE to receive $20 credit. -* Implement SMS notification using Twilio to send an SMS notification to a user letting them know that the order has been received. - -**Unit tests** - -* Add unit tests to your application where appropriate +## README -## Technical notes -* Run `npm install` after cloning to download all dependencies -* Use `npm run dev -- --watch` to build React -* You will need to create a `.env` file to store your database credentials. Make sure you add it to `.gitignore` file so that the credentials do not get commit to git and end up in public. -* Use `node server.js` to run the Node server in another tab -* Place all static files such as images and CSS in the `static` folder. When requesting those files from the server use `/static` at the beginning of the URL. For example `` -* `bundle.js` produced by webpack will be output in the `static` folder -* To send data server using a POST, PUT or PATCH request you can do something the example below, where `order` is an object we want to send to the server and `http://localhost:8080/api/order` is URL we want to send it to. + * what the project does +This is a food order for delivery app. You Select cakes from a menu and submit the order to the restaurant -```js -fetch('http://localhost:8080/api/order', { - method: 'post', - body: JSON.stringify(order), - headers: { - 'Content-Type': 'application/json' - } - }).then(function(response) { - return response.json(); - }).then(data => { - // handle response - }); -``` + * what technologies it uses +React, postgres, APIs, SCSS, node -* Check out [Nodemon](https://nodemon.io/) to automatically rebuild and restart your server when changes are saved. + * how to build it and run it +npm run dev, pgweb, node - all through terminal -## README -* Produce a README.md which explains - * what the project does - * what technologies it uses - * how to build it and run it * any unresolved issues the user should be aware of +lots of unfinished features. Styling is very poor. diff --git a/database.sql b/database.sql new file mode 100644 index 0000000..9bd951f --- /dev/null +++ b/database.sql @@ -0,0 +1,59 @@ +CREATE DATABASE delivereat_db; + +CREATE TABLE menu ( + id serial PRIMARY KEY, + name varchar (100) NOT NULL, + price NUMERIC(5,2) NOT NULL, + description varchar (500) NOT NULL, + vegan BOOLEAN NOT NULL +) + +INSERT INTO menu VALUES (1, 'Rainbow Cake', 4.99, 'Great for a party', FALSE); +INSERT INTO menu VALUES (2, 'New York Cheesecake', 3.99, 'Classic', FALSE); +INSERT INTO menu VALUES (3, 'Strawberry Cheesecake', 3.99, 'Classic with rich strawberry', FALSE); +INSERT INTO menu VALUES (4, 'Sticky Toffee Pudding', 5.99, 'Sweet and rich and served warm', FALSE); +INSERT INTO menu VALUES (5, 'Red Velvet', 4.50, 'Posher version of sponge', FALSE); +INSERT INTO menu VALUES (6, 'Victoria Sponge', 4.99, 'British Classic with cream and jam', FALSE); +INSERT INTO menu VALUES (7, 'Apple Pie', 4.00, 'American classic', FALSE); +INSERT INTO menu VALUES (8, 'Chocolate Tort', 5.00, 'Ultra rich for chocolate enthusiasts', FALSE); +INSERT INTO menu VALUES (9, 'Battenberg', 3.50, 'Great for kids', FALSE); +INSERT INTO menu VALUES (10, 'Lemon Cake', 3.25, 'Sweet and tart and indulgent', FALSE); +ALTER SEQUENCE menu_id_seq RESTART WITH 11 INCREMENT BY 1 + +CREATE TABLE order ( + id serial PRIMARY KEY, + name varchar (100) NOT NULL, + address varchar (500) NOT NULL, + telephone varchar (15) NOT NULL +) + +CREATE TABLE order_content ( + id serial PRIMARY KEY, + quantity INT NOT NULL, + FOREIGN KEY (menu_id) REFERENCES menu (id), + FOREIGN KEY (order_id) REFERENCES order (id) +) + + +UPDATE menu SET photoUrl='rainbow.jpeg' WHERE id=1; +UPDATE menu SET photoUrl='blueberry.jpeg' WHERE id=2; +UPDATE menu SET photoUrl='strawberry.jpeg' WHERE id=3; +UPDATE menu SET photoUrl='toffee.jpeg' WHERE id=4; +UPDATE menu SET photoUrl='redvelvet.jpeg' WHERE id=5; +UPDATE menu SET photoUrl='banana.jpeg' WHERE id=6; +UPDATE menu SET photoUrl='apple.jpeg' WHERE id=7; +UPDATE menu SET photoUrl='tart.jpeg' WHERE id=8; +UPDATE menu SET photoUrl='battenberg.jpeg' WHERE id=9; +UPDATE menu SET photoUrl='fudge.jpeg' WHERE id=10; + + +ALTER TABLE menu +ADD photoUrl varchar(200); + +-- CREATE TABLE delivery ( +-- id serial PRIMARY KEY, +-- price_range +-- delivery_charge +-- FOREIGN KEY (menu_id) REFERENCES menu (id), +-- FOREIGN KEY (order_id) REFERENCES order (id), +-- ) diff --git a/package-lock.json b/package-lock.json index 167f7e9..15c01a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "react-testing", + "name": "deliveat-with-db", "version": "1.0.0", "lockfileVersion": 1, "requires": true, @@ -53,11 +53,71 @@ "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", "dev": true }, + "@types/body-parser": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", + "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", + "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", + "requires": { + "@types/node": "*" + } + }, + "@types/events": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" + }, + "@types/express": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz", + "integrity": "sha512-TtPEYumsmSTtTetAPXlJVf3kEqb6wZK0bZojpJQrnD/djV4q1oB6QQ8aKvKqwNPACoe02GNiy5zDzcYivR5Z2w==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz", + "integrity": "sha512-lTeoCu5NxJU4OD9moCgm0ESZzweAx0YqsAcab6OB0EB3+As1OaHtKnaGJvcngQxYsi9UNv0abn4/DRavrRxt4w==", + "requires": { + "@types/events": "*", + "@types/node": "*", + "@types/range-parser": "*" + } + }, + "@types/mime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", + "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" + }, "@types/node": { "version": "10.11.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.11.7.tgz", - "integrity": "sha512-yOxFfkN9xUFLyvWaeYj90mlqTJ41CsQzWKS3gXdOMOyPVacUsymejKxJ4/pMW7exouubuEeZLJawGgcNGYlTeg==", - "dev": true + "integrity": "sha512-yOxFfkN9xUFLyvWaeYj90mlqTJ41CsQzWKS3gXdOMOyPVacUsymejKxJ4/pMW7exouubuEeZLJawGgcNGYlTeg==" + }, + "@types/range-parser": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.2.tgz", + "integrity": "sha512-HtKGu+qG1NPvYe1z7ezLsyIaXYyi8SoAVqWDZgDQ8dLrsZvSzUNCwZyfX33uhWxL/SU0ZDQZ3nwZ0nimt507Kw==" + }, + "@types/serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==", + "requires": { + "@types/express-serve-static-core": "*", + "@types/mime": "*" + } }, "@webassemblyjs/ast": { "version": "1.5.12", @@ -2215,6 +2275,11 @@ "isarray": "^1.0.0" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-from": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", @@ -3469,6 +3534,11 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, + "deprecate": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/deprecate/-/deprecate-1.0.0.tgz", + "integrity": "sha1-ZhSQ7SQokWpsiIPYg05WRvTkpKg=" + }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -3656,6 +3726,14 @@ "jsbn": "~0.1.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", + "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "editions": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", @@ -4039,13 +4117,13 @@ } }, "express": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", - "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", "requires": { "accepts": "~1.3.5", "array-flatten": "1.1.1", - "body-parser": "1.18.2", + "body-parser": "1.18.3", "content-disposition": "0.5.2", "content-type": "~1.0.4", "cookie": "0.3.1", @@ -4062,10 +4140,10 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.3", - "qs": "6.5.1", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", "range-parser": "~1.2.0", - "safe-buffer": "5.1.1", + "safe-buffer": "5.1.2", "send": "0.16.2", "serve-static": "1.13.2", "setprototypeof": "1.1.0", @@ -4075,66 +4153,10 @@ "vary": "~1.1.2" }, "dependencies": { - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.1", - "http-errors": "~1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "~2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "~1.6.15" - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": ">= 1.3.1 < 2" - } - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" - } - } + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "statuses": { "version": "1.4.0", @@ -6100,9 +6122,9 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ipaddr.js": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", - "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" }, "is-absolute-url": { "version": "2.1.0", @@ -7081,6 +7103,29 @@ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, + "jsonwebtoken": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz", + "integrity": "sha512-oge/hvlmeJCH+iIz1DwcO7vKPkNGJHhgkspk8OH3VKlw+mbi42WtD4ig1+VXRln765vxptAv+xT26Fd3cteqag==", + "requires": { + "jws": "^3.1.5", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -7092,6 +7137,25 @@ "verror": "1.10.0" } }, + "jwa": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", + "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.10", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz", + "integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==", + "requires": { + "jwa": "^1.1.5", + "safe-buffer": "^5.0.1" + } + }, "keyv": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", @@ -7500,12 +7564,42 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, "lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", "dev": true }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -7518,6 +7612,11 @@ "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -8002,6 +8101,11 @@ "minimist": "0.0.8" } }, + "moment": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.3.tgz", + "integrity": "sha1-vbmdJw1tf9p4zA+6zoVeJ/59pp8=" + }, "moo": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz", @@ -9143,6 +9247,11 @@ "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" }, + "pop-iterate": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pop-iterate/-/pop-iterate-1.0.1.tgz", + "integrity": "sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M=" + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -9775,12 +9884,12 @@ } }, "proxy-addr": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", - "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", "requires": { "forwarded": "~0.1.2", - "ipaddr.js": "1.6.0" + "ipaddr.js": "1.8.0" } }, "prr": { @@ -10478,6 +10587,11 @@ "inherits": "^2.0.1" } }, + "rootpath": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/rootpath/-/rootpath-0.1.2.tgz", + "integrity": "sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms=" + }, "rst-selector-parser": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", @@ -10986,6 +11100,11 @@ } } }, + "scmp": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/scmp/-/scmp-0.0.3.tgz", + "integrity": "sha1-NkjfLXKUZB5/eGc//CloHZutkHM=" + }, "scoped-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", @@ -12198,6 +12317,35 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "optional": true }, + "twilio": { + "version": "3.23.1", + "resolved": "https://registry.npmjs.org/twilio/-/twilio-3.23.1.tgz", + "integrity": "sha512-1Gi2LctRWPokZC2SxrpUuAYjWbgu3LTEAnJI8Q3AYRcDpV4pua9YZmhHcYNRDYNuj1cU4I78kSy9k9PdiHxGwQ==", + "requires": { + "@types/express": "^4.11.1", + "deprecate": "1.0.0", + "jsonwebtoken": "^8.1.0", + "lodash": "^4.17.10", + "moment": "2.19.3", + "q": "2.0.x", + "request": "^2.87.0", + "rootpath": "0.1.2", + "scmp": "0.0.3", + "xmlbuilder": "9.0.1" + }, + "dependencies": { + "q": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/q/-/q-2.0.3.tgz", + "integrity": "sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ=", + "requires": { + "asap": "^2.0.0", + "pop-iterate": "^1.0.1", + "weak-map": "^1.0.5" + } + } + } + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -12686,6 +12834,11 @@ "neo-async": "^2.5.0" } }, + "weak-map": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", + "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=" + }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -13277,9 +13430,9 @@ } }, "widest-line": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz", - "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", "dev": true, "requires": { "string-width": "^2.1.1" @@ -13377,6 +13530,11 @@ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" }, + "xmlbuilder": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.1.tgz", + "integrity": "sha1-kc1wiXdVNj66V8Et3uq0o0GmH2U=" + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/package.json b/package.json index a03a776..4863b06 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "scripts": { "test": "jest", "dev": "webpack --mode development", - "build": "webpack --mode production" + "build": "webpack --mode production", + "start": "nodemon index.js" }, "author": "", "license": "ISC", @@ -19,12 +20,13 @@ "dependencies": { "body-parser": "^1.18.3", "dotenv": "^6.1.0", - "express": "^4.16.3", + "express": "^4.16.4", "hbs": "^4.0.1", "jest": "^22.3.0", "pg-promise": "^8.5.0", "react": "^16.2.0", - "react-dom": "^16.2.0" + "react-dom": "^16.2.0", + "twilio": "^3.23.1" }, "devDependencies": { "babel-jest": "^22.4.1", @@ -38,11 +40,22 @@ "jest": "^22.4.2", "jest-fetch-mock": "^1.6.6", "node-sass": "^4.9.1", - "nodemon": "1.17.5", + "nodemon": "^1.17.5", + "react-test-renderer": "^16.2.0", "sass-loader": "^7.0.3", "style-loader": "^0.21.0", - "react-test-renderer": "^16.2.0", "webpack": "^4.0.1", "webpack-cli": "^2.0.9" - } + }, + "directories": { + "test": "tests" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/zuberman/delivereat-with-db.git" + }, + "bugs": { + "url": "https://github.com/zuberman/delivereat-with-db/issues" + }, + "homepage": "https://github.com/zuberman/delivereat-with-db#readme" } diff --git a/send_sms.js b/send_sms.js new file mode 100644 index 0000000..c63891b --- /dev/null +++ b/send_sms.js @@ -0,0 +1,15 @@ + +// Download the helper library from https://www.twilio.com/docs/node/install +// Your Account Sid and Auth Token from twilio.com/console +const accountSid = 'ACabafbc79c1c76c070ea7300972ef7e05'; +const authToken = 'd3e4758f3da08a0e569c8355712fd333'; +const client = require('twilio')(accountSid, authToken); + +client.messages + .create({ + body: 'This is the ship that made the Kessel Run in fourteen parsecs?', + from: '+447447980922', + to: '+447490095780' + }) + .then(message => console.log(message.sid)) + .done(); diff --git a/server.js b/server.js index 89ca1de..12e551a 100644 --- a/server.js +++ b/server.js @@ -1,23 +1,76 @@ -const express = require('express'); +require('dotenv').config(); +const client = require('twilio')(process.env.accountSid, process.env.authToken); + const bodyParser = require('body-parser'); +const pgp = require('pg-promise')(); +const express = require('express'); const app = express(); +const db = pgp({ + host: 'localhost', + port: 5432, + database: process.env.DB_NAME, + user: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD +}); app.use(bodyParser.json()); app.use('/static', express.static('static')); app.set('view engine', 'hbs'); -const menu = { - 1: { - id: 1, - name: "Strawberry cheesecake", - price: 6 - } -}; - app.get('/', function(req, res){ res.render('index'); }); -app.listen(8080, function(){ - console.log('Listening on port 8080'); +app.get('/api/menu', function(req, res){ + db.any('SELECT * FROM menu') + .then(function(data) { + res.json(data); + }) + .catch(function(error){ + res.json({error: error.message}) + }) +}) + +app.get('/api/menu/:itemId', function(req, res){ + const menuId = req.params.itemId; + db.one('SELECT menu.id ,menu.name, menu.price, menu.description, menu.vegan, menu.photourl FROM menu WHERE id=$1', [menuId]) + .then(function(data) { + res.json(data); + }) + .catch(function(error) { + res.json({error: error.message}) + }) +}) + +app.post('/api/order', function(req, res){ + const { items, name, address, telephone } = req.body; + db.one("INSERT INTO orders (id, name, address, telephone) VALUES (DEFAULT, $1, $2, $3) RETURNING id", [name, address, telephone]) + .then(result => { + const orderId = result.id; + + return Promise.all(Object.entries(items).map(([menuItemId, quantity]) => { + return db.none( + "INSERT INTO order_content (menu_id, orders_id, quantity) VALUES ($1, $2, $3)", + [menuItemId, orderId, quantity] + ); + })) + .then(() => client.messages + .create({ + body: `Your order number is ${orderId}. Listen out for the doorbell!`, + from: '+447447980922', + to: telephone + }) + .then(message => console.log(message.sid)) + .done() + ) + .then(() => orderId); + }) + .then(orderId => res.json({ orderId: orderId })) + .catch(error => res.json({ error: error.message })); +}); + + + +app.listen(8080, function() { + console.log('Listening on port 8080!'); }); diff --git a/sms_server.js b/sms_server.js new file mode 100644 index 0000000..8c8bcc8 --- /dev/null +++ b/sms_server.js @@ -0,0 +1,17 @@ +const express = require('express'); +const MessagingResponse = require('twilio').twiml.MessagingResponse; + +const app = express(); + +app.post('/sms', (req, res) => { + const twiml = new MessagingResponse(); + + twiml.message('The Robots are coming! Head for the hills!'); + + res.writeHead(200, {'Content-Type': 'text/xml'}); + res.end(twiml.toString()); +}); + +http.createServer(app).listen(1337, () => { + console.log('Express server listening on port 1337'); +}); diff --git a/src/components/AddOrderModal b/src/components/AddOrderModal new file mode 100644 index 0000000..4b605af --- /dev/null +++ b/src/components/AddOrderModal @@ -0,0 +1 @@ +import Reac diff --git a/src/components/AddOrderModal.js b/src/components/AddOrderModal.js new file mode 100644 index 0000000..529156b --- /dev/null +++ b/src/components/AddOrderModal.js @@ -0,0 +1,67 @@ +import React from 'react'; + + +import '../styles/AddOrderModal.scss'; + +class AddOrderModal extends React.Component { + constructor(){ + super(); + + this.state= { + quantity: "1" + } + + this.handleClick = this.handleClick.bind(this); + this.handleSubmit = this.handleSubmit.bind(this); + this.handleChange = this.handleChange.bind(this); + } + +handleClick(event) { + this.props.receiveModalCloseBtn(); + this.setState({ + quantity: 1, + }) +} + +handleSubmit(event){ + event.preventDefault() + this.props.updateOrder(this.props.modalDetails.id, this.state.quantity) + this.props.receiveModalCloseBtn(); + this.setState({ + quantity: 1 + }) +} + +handleChange(event) { + this.setState({ + quantity: parseInt(event.target.value, 10), + }) + } + + +render(){ + return( +
+
+
+ × +

Add to Order

+
+
+ +

{this.props.modalDetails.name}

£{this.props.modalDetails.price}

+

{this.props.modalDetails.description}

+
+ + +
+
+
+
+ ) +} + + +} + +export default AddOrderModal diff --git a/src/components/App.js b/src/components/App.js index 2ba4c77..beba9df 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,16 +1,159 @@ import React from 'react'; +import MenuItem from './MenuItem.js' +import AddOrderModal from './AddOrderModal.js' +import Order from './Order.js' import '../styles/App.scss'; class App extends React.Component { constructor(){ super(); + + this.state = { + menu: [], + modalOpen: false, + modalDetails: "", + order: {}, + total: "", + orderNo: 0 + } + + this.menuCall = this.menuCall.bind(this); + this.itemCall = this.itemCall.bind(this); + this.receiveModal = this.receiveModal.bind(this); + this.updateOrder = this.updateOrder.bind(this); + this.submitOrderPost = this.submitOrderPost.bind(this); + this.clearOrder = this.clearOrder.bind(this); + this.receiveRemoveItem = this.receiveRemoveItem.bind(this); + this.receiveModalCloseBtn = this.receiveModalCloseBtn.bind(this); + // this.updateQuantity = this.updateQuantity.bind(this); } +componentDidMount(){ + this.menuCall(); +} + +menuCall(){ + fetch('/api/menu') + .then(function(response) { + return response.json(); + }) + .then(body => { + this.setState({ + menu: body + }) + }) +} + +itemCall(menuId){ + fetch(`/api/menu/${menuId}`) + .then(function(response) { + return response.json(); + }) + .then(body => { + this.setState({ + modalDetails: body + }) + }) +} + +submitOrderPost(name, address, telephone){ + const order = {name, address, telephone, items: this.state.order}; + fetch(`/api/order`, {method:"POST", headers: { + "Content-Type": "application/json; charset=utf-8", + }, body: JSON.stringify(order)}) + //two then statements + .then(response => response.json()) + .then(response => this.setState({ + orderNo: response.orderId + }, + () => window.alert(`Your order number ${this.state.orderNo} is on its way - Listen for the doorbell!`) + )) + this.setState({ + order: {} + }) + +} + +clearOrder(){ + this.setState({ + order: {} + }) +} + +// remember to pass this down through props +// updateQuantity(id, value){ +// update the quantity of the relevant item in the Object +// const updateOrder = Object.assign({}, this.state.order); +// updateOrder[id] = {id: value} +// this.state.order[] +// this.setState({ +// +// }) +// } + +receiveRemoveItem(itemId){ + // const orderArray = Object.entries(this.state.order) + // const filteredOrder = ordersArray.filter(([itemId, quantity]) => { + // return itemId !== itemId.toString() + // }) + const newOrder = Object.assign({}, this.state.order); + + delete newOrder[itemId]; + + this.setState({ + order: newOrder + }) +} + +receiveModal(menuItemId){ + this.itemCall(menuItemId); + this.setState({ + modalOpen: true + }) +} + +updateOrder(itemId, itemQuantity){ + const newOrder = Object.assign({}, this.state.order); + + if (newOrder[itemId]) { + newOrder[itemId] = newOrder[itemId] + itemQuantity + } else { + newOrder[itemId] = itemQuantity + } + this.setState({ + order: newOrder, + }) +} + +receiveModalCloseBtn(){ + this.setState({ + modalOpen: false, + }) +} + +modalOutsideClick(event){ + if(event.target.className == "modal2"){ + this.setState({ + modalOpen: false, + }) + } + } + + render(){ return ( -
- Delivereat app +
+

DIABETES

+ {this.state.menu.map( menuItem => { + return( + + ); + })} + + {Object.values(this.state.order).length > 0 ? : null }
) } diff --git a/src/components/Menu.js b/src/components/Menu.js new file mode 100644 index 0000000..0ad224e --- /dev/null +++ b/src/components/Menu.js @@ -0,0 +1,29 @@ +import React from 'react'; + +class MenuItem extends React.Component { + constructor(){ + super(); + + this.setState = { + + } + + + } + +handleClick(menuItem.id){ + this.props.receiveModal() +} + +render(){ + return( +
this.handleClick(menuItem.id)}> +

{this.props.menuItem.name}

+
+ + ) +} + +} + +export default Menu; diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js new file mode 100644 index 0000000..391b4ae --- /dev/null +++ b/src/components/MenuItem.js @@ -0,0 +1,30 @@ +import React from 'react'; + +class MenuItem extends React.Component { + constructor(){ + super(); + + this.setState = { + + } + + this.handleClick = this.handleClick.bind(this); + + } + +handleClick(){ + this.props.receiveModal(this.props.menuItem.id) +} + +render(){ + return( +
+

{this.props.menuItem.name}

+
+ + ) +} + +} + +export default MenuItem; diff --git a/src/components/Order.js b/src/components/Order.js new file mode 100644 index 0000000..0fac133 --- /dev/null +++ b/src/components/Order.js @@ -0,0 +1,126 @@ +import React from 'react'; + +class Order extends React.Component { + constructor(){ + super(); + + this.state = { + name: "", + address: "", + telephone: "", + + } + + this.handleSubmit = this.handleSubmit.bind(this); + this.handleChangeName = this.handleChangeName.bind(this); + this.handleChangeAddress = this.handleChangeAddress.bind(this); + this.handleChangeTelephone = this.handleChangeTelephone.bind(this); + this.receiveRemoveItem = this.receiveRemoveItem.bind(this); + this.handleClear = this.handleClear.bind(this); + // this.updateQuantity = this.updateQuantity.bind(this); + } + +handleClear(event){ + event.preventDefault() + this.props.clearOrder() + this.setState({ + name: "", + address: "", + telephone: "", + }) +} + +handleSubmit(event){ + event.preventDefault() + this.props.submitOrder(this.state.name, this.state.address, this.state.telephone) + this.setState({ + name: "", + address: "", + telephone: "", + }) +} + +handleChangeName(event){ + this.setState({ + name: event.target.value + }) +} + +handleChangeAddress(event){ + this.setState({ + address: event.target.value + }) +} + +handleChangeTelephone(event){ + this.setState({ + telephone: event.target.value + }) +} + +receiveRemoveItem(id){ + this.props.receiveRemoveItem(id) +} + +// updateQuantity(id, event.target.value){ +// this.props.updateQuantity(id, event.target.value) +// } + +render(){ + const orderDetails = Object.entries(this.props.order) + const total = orderDetails.reduce((acc, [id, quantity]) => { + const {price} = this.props.menu.find(item => item.id.toString() === id) // price is destructing from the object for the property called price, declaring ocnst equal to price + return acc +(quantity * price) + }, 0) + const deliveryCharge = total > 20 ? "you've qualified for free delivery" : 3.95 + const totalIncDelivery = total > 20 ? total : total + 3.95 + return( +
+

Your Order Basket

+
+ + + + + + + + +
NameQuantityTotal
+ {orderDetails.map (([id, quantity]) => { + const menuItem = this.props.menu.find(item => item.id.toString() === id) + return( + + {menuItem.name} + X{quantity} + {/* this.updateQuantity(id, event)} /> */} + £{quantity * menuItem.price} + + + ) + })} +
+ + {total.toFixed(2)}xxxx + {deliveryCharge}xxxx + {totalIncDelivery.toFixed(2)} + + +
+
+ + + + +
+

+

+

+
+
+ ) +} + +} + +export default Order diff --git a/src/styles/AddOrderModal.scss b/src/styles/AddOrderModal.scss new file mode 100644 index 0000000..a7dcfa3 --- /dev/null +++ b/src/styles/AddOrderModal.scss @@ -0,0 +1,130 @@ +.modal{ + display:none; + position: fixed; + z-index:1; + left: 0; + top:0; + height: 100%; + width:100%; + overflow: auto; + background-color: rgba(0,0,0,0.5); +} + +.modal2{ + display: block; + position: fixed; + z-index:1; + left: 0; + top:0; + height: 100%; + width:100%; + overflow: auto; + background-color: rgba(0,0,0,0.5); +} + + +.modal-content{ + background-color:#f4f4f4; + margin: 20% auto; + width:70%; + box-shadow: 0 5px 8px 0 rgba(0,0,0,0.2),0 7px 20px 0 rgba(0,0,0,0.17); + animation-name:modalopen; + animation-duration:1s; +} + +.modal-header h2, .modal-footer h3{ + margin:0; +} + +.modal-header{ + background:coral; + padding:15px; + color:#fff; +} + +.modal-body{ + padding:10px 20px; +} + +img { + max-width: 400px; + min-width: 50px; + height: auto; + float: center; + padding-bottom: 15px; +} + + +button{ + background-color: coral; + padding: 1em 2em; + color: #fff; + border:0; +} + +button:hover{ + background:#333; +} + + +.closeBtn{ + color:#ccc; + float: right; + font-size: 30px; +} + +.closeBtn:hover,.closeBtn:focus{ + color: #000; + text-decoration: none; + cursor:pointer; +} + +.menuItem { + box-shadow: 10px 10px grey; + margin:30px; + background-color: #f4f4f4; + border: 1px solid; + text-align: center; + overflow-wrap: normal; + +} + +h2 { + display: flex; + justify-content: center; + flex-wrap: wrap; +} + +.menuItem:hover { + background-color: #C0C0C0; +} + + +// #posterImage { +// min-width: 300px; +// min-height: 460px; +// max-width: 325px; +// } + +.main { + display: flex; + flex-wrap: wrap; + justify-content: space-around; +} + + +@keyframes modalopen{ + from{opacity: 0} + to{opacity: 1} +} + +@media (max-width:510px) { + img { + max-width: 200px; + height: auto; + float: center; + padding-bottom: 15px; + } + + +} diff --git a/src/styles/App.scss b/src/styles/App.scss index 0bdf5c0..1cc1278 100644 --- a/src/styles/App.scss +++ b/src/styles/App.scss @@ -1,3 +1,12 @@ body { background-color: Cornsilk; } + +header { + background-color: coral; + text-align: center; + color: white; + margin:auto; + overflow:hidden; + font-family: 'Charmonman', cursive; +} diff --git a/src/styles/Order.scss b/src/styles/Order.scss new file mode 100644 index 0000000..976704a --- /dev/null +++ b/src/styles/Order.scss @@ -0,0 +1,22 @@ +.modal-content{ + background-color:#f4f4f4; + margin: 20% auto; + width:70%; + box-shadow: 0 5px 8px 0 rgba(0,0,0,0.2),0 7px 20px 0 rgba(0,0,0,0.17); + animation-name:modalopen; + animation-duration:1s; +} + +.modal-header h2, .modal-footer h3{ + margin:0; +} + +.modal-header{ + background:coral; + padding:15px; + color:#fff; +} + +.modal-body{ + padding:10px 20px; +} diff --git a/static/apple.jpeg b/static/apple.jpeg new file mode 100644 index 0000000..a611cf9 Binary files /dev/null and b/static/apple.jpeg differ diff --git a/static/banana.jpeg b/static/banana.jpeg new file mode 100644 index 0000000..67230ec Binary files /dev/null and b/static/banana.jpeg differ diff --git a/static/battenberg.jpeg b/static/battenberg.jpeg new file mode 100644 index 0000000..68a9dff Binary files /dev/null and b/static/battenberg.jpeg differ diff --git a/static/blueberry.jpeg b/static/blueberry.jpeg new file mode 100644 index 0000000..9019b8d Binary files /dev/null and b/static/blueberry.jpeg differ diff --git a/static/fudge.jpeg b/static/fudge.jpeg new file mode 100644 index 0000000..a622419 Binary files /dev/null and b/static/fudge.jpeg differ diff --git a/static/rainbow.jpeg b/static/rainbow.jpeg new file mode 100644 index 0000000..b38a11b Binary files /dev/null and b/static/rainbow.jpeg differ diff --git a/static/redvelvet.jpeg b/static/redvelvet.jpeg new file mode 100644 index 0000000..fadd84d Binary files /dev/null and b/static/redvelvet.jpeg differ diff --git a/static/strawberry.jpeg b/static/strawberry.jpeg new file mode 100644 index 0000000..c9f6c85 Binary files /dev/null and b/static/strawberry.jpeg differ diff --git a/static/tart.jpeg b/static/tart.jpeg new file mode 100644 index 0000000..a779878 Binary files /dev/null and b/static/tart.jpeg differ diff --git a/static/toffee.jpeg b/static/toffee.jpeg new file mode 100644 index 0000000..86b23c9 Binary files /dev/null and b/static/toffee.jpeg differ diff --git a/static/vegan.png b/static/vegan.png new file mode 100644 index 0000000..1bd375c Binary files /dev/null and b/static/vegan.png differ diff --git a/views/index.hbs b/views/index.hbs index 8fdb420..0267a92 100644 --- a/views/index.hbs +++ b/views/index.hbs @@ -1,8 +1,9 @@ - Let's get some food + DIABETES +