Nutri-Kit


Overview

For this assignment, you will build a web applications using HTML, CSS and Javascript for managing food items and viewing/ tracking nutriional information. Food items will be in groups according to the nutritional pyramid, and you will build up a menu using one or more items from the various food groups.

Client-0

Web development - Startup: Your first web page

Overview

This initial assignment will introduce you to the basics of HTML. In this initial assignment, we will not use CSS. Use style attributes on the appropriate HTML tags to adjust the appearance. When finished, tag the commit as client-0

Setup

Locate your project in your group (Named client-group-x) in gitlab, and clone the project
Once you clone this project, create a folder named public.
All your code for this assignment will go in this folder.
Inside public/, do the following:
Create a file, and name it index.html
- Your web markup (html) will go in this file (You can use the template below to get started)

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Web Assignment 0</title>
  <meta name="description" content="First web assignment">
  <meta name="author" content="student name">
</head>
<body>
</body>
</html>

In the root directory, create a .gitlab-ci.yml file with this content:

image:
  name: node:18 #No special docker image.  Standard nodejs image from dockerhub
cache:
  paths:
  - node_modules/
before_script:
  - yarn install
  - node --version
pages:
  stage: deploy
  script:
    - ls -lFa public
  artifacts:
    paths:
    - public

This CI file will publish your webpage (index.html) to the gitlab web server.
You can find the URL (to check your webpage) on the settings/pages link in gitlab

Requirements

You will implement the following controls and behaviour for your webpage (index.html)
Set the default font to ‘Segoe UI’
Add a title using the <h1> tag to the top of the page with the following text ‘SWEN-344 Web Assignment 0’

  • Set the font to Bold, Verdana, with a size of 36px (Use the style property) and centre the title.

Add a sub-heading with the <h2> tag.

  • The text content should be ‘Section xx’, where ‘xx’ is your section number. Set the font to “Impact”
  • Center the text.

Add a pull down menu (drop-down list) control with the following values
Protein
Carbs
Fruits
Vegetables
Sweets
Use the <select> tag with those options. There should also be a default selection with an empty value (blank). Make sure it is a dropdown list as shown in the sample below.

Add a set of radio buttons with the following values
Black
Red
Green
Blue
Purple
Use the <input type="radio"> tag. Make sure the radio buttons operate as a group. i.e. only one item can be selected at a time!

Add a text box (textarea) control with the following initial content Food Type...
Use the <textarea> tag. Set the control to be non-expandable. Set the rows and columns properties to your liking. Position the control in the center.

Add a small javascript function (place in <HEAD> ) that will reflect the value of the selection of the SELECT tag (e.g. Protein, Fruit, Vegetables, …) as soon as the value changes. Use the value of the current selection in the radio button group to set the colour of the font in the text area.

  • HINT: Use the onchange event and document.getElementByName or get clever with onclick and pass in the object instance

Use style attributes to adjust the position of controls (so everything is not at the edges or clustered together). Look at the sample page and try to get as close as possible to the centering and left/ right/ top/ bottom positioning shown in the screen-shot. NOTE: In part-0, we want you to put the styles in-line, and not use CSS. That will come later.

Grading

Grading: 10 points total
Correct implemention for each of the controls and styles
Web Page and Actions:

  • Title & Headings: 1 point
  • Listbox creation: 1 points
  • Radio button: 1 points
  • Textarea creation (with resizing disabled): 1
  • Layout & Alignment: 2
  • Javascript dynamic updates: 4

Sample Output

UI Specifications are often page mockups. Your page should be similar to this…

../nutrikit-0.0.JPG

Sample Page-0

../nutrikit-0.1.JPG

Sample Page-1

../nutrikit-0.2.JPG

Sample Page-2

Client-1

Overview

For this assignment, you will build a web applications using HTML, CSS and Javascript to assist people in grocery list planning while summarizing nutritional information (calories).

Setup

You will create a new branch (dev-client-1) in your gitlab group repo (client-abc123) which you created for Client-0. When you finish this project merge to master and apply a tag client-1. You will continue to use the gitlab pages as before. You will place your HTML code in public/index-1.html and add a .css file for styles (e.g. nutrikit.css) and a .js file for your javascript code.

NOTE: To avoid conflict with client-0 files, we are having you implement your HTML page for client-1 in a different file i.e. public/index-1.html.

Use the same support file (.gitlab-ci.yml) from the prior project.

This CI file will publish your webpage (index.html) to the gitlab web server. You can find the URL (to check your webpage) on the settings/pages link in gitlab

Client-1: Initial UI

Your app maintains a list of grocery items for basic food groups [proteins, fruits, vegetables, grains, dairy]. For each category, there is a list of 5 items in that category. A user can select an item an add to there selection list/ menu. As each item is added (or removed), the total calories fo the selection list (menu) is summarized.

The following are the behaviour expectations
Set the default font to ‘Segoe UI’
Add a title using the <h1> tag, centred, to the top of the page with the following text ‘NutriKit Food Planner’
Add a sub-heading, <h3>, centred, with the following text NutriKit allows you to select your groceries, and track your nutritional progress (good or bad)

Use a pull-down menu with a <select> with options for the following food categories
- “proteins”, “fruits”, “vegetables”, “dairy”, “grain”
Provide a listbox that can hold 5 items, and as a food category is selected, populate the listbox with the matching food items.
Each food item also has a calorie count associated with it.
The data is shown below.
You will need to decide how to represent that data in your code. Remember, there is no database (yet), so you need to keep this all client side!

Proteins Calories
steak 300
ground beef 200
chicken 100
fish 80
soy 50
Fruits Calories
orange 300
banana 200
pineapple 100
grapes 80
blueberries 50
Vegetables Calories
romaine 30
green beans 40
squash 100
spinach 50
kale 10
Dairy Calories
milk 300
yoghurt 200
cheddar cheese 200
skim milk 100
cottage cheese 80
Grains Calories
bread 200
bagel 300
pita 250
naan 210
tortilla 120

There will be a second list box, for the user selections.
Between the two list boxes, there will be a button to add/ remove items from the selection list.
Once the items for the category are populated, the user can click the button to add an item to the selection list.
- When you click an item in the first listbox (with the items you can add), the button will be configured to add the selected item to your selection list.
- When you click an item in your selection list, the button will be configured to remove an item from the selection list.
The item that is added will appear in the selection list. As the item is added, the total amount of calories (total of all items in the selected items list) will be shown below the selection list.
An item can be removed from the selected items list, and the calorie count will also update when an item is removed.
The selected items list can hold any number of items, and can be a mix of items from all categories.

Place all the styles for the different display elements in your .css file. Place all your javascript code in your .js file.

Use the screenshots below as an additional reference for your web page design requirements.

Grading

Points: 40 points total

Web Page and Actions:

  • Pulldown menu selection: 5 points
  • Populating listboxes: 5
  • Headings, Layout & Alignment: 5
  • Good coding style of css: 5
  • Good coding style of javascript: 5
  • Following all requirements: 15

Sample Output

UI Specifications are often page mockups. Your page should be similar to this…

../client-1_nutrikit.1.jpg

Sample Page-0


../client-1_nutrikit.2.jpg

Sample Page-1-Add item


../client-1_nutrikit.3.png

Sample Page-2-Remove item

Client-2: Port to React

Your branch name should be client2-dev. When you have merged, the tag should be client2.

Now you have seen what it looks like to have a tiny bit of dynamic functionality on a webpage, let’s start thinking bigger. Modern websites that have a lot of client-side functionality use component-based frameworks. We’ll be using React.js, which is one of the most popular ones out there today.

Our goal with this iteration is to achieve feature parity, perhaps with some improvements along the way. Your app will hopefully look and act nearly exactly as before, but will be easier to build upon for future features.

Getting Started with React

Everyone must do this part, even if you think you are familiar with React.js.

  1. Do our React Setup instructions. Be sure to review the walkthrough explanation of all the files.
  2. Review the resources available to you on the Getting Started with React. We have found these resources to be very well-written and helpful.
  3. Do one of these:
  • Either the Step-by-Step Guide, all the way through Thinking in React.
    OR
  • They have tutorials that build a Tic-Tac-Toe example.
    • The example that uses Classes/ Components (same as we will mainly use in this course) is at Tic Tac Toe Tutorial
    • There is also the new version that uses function/ hooks. You may also follow this one. Tic Tac Toe tutorial that shows everything together. Feel free to do this tutorial instead.
    • In either case, commit your code (again, into a separate folder)

Commit your tutorial code to your repository, to the branch client2-dev into a separate folder.

  • i.e. create a sub-folder in your repo called ‘react-guide’, and place your files for the tutorial you used in there.

Porting to React

Once you’ve gotten set up and done the tutorials, let’s do the following, in this order:

  1. Decide what your app’s state will look like. This is the minimum amount of data that needs to be maintained to represent what the app tracks at any given time. Define your intitial state in your top-level component (e.g. App, or whatever you want to rename yours to). Consider which other components need their own state. Minimize the complexity of state management, but make sure you make components as independent as possible so you don’t always rely on a single ‘master’ object. This is the basics of good O-O design.
  2. Create component classes to represent elements of your UI. Put each component in a separate file.
  3. Next, make the render method for each component. Hard-code all your numbers first. Just get the JSX working so the site looks the same.
  4. Next, pass the state from your top-level component to the properties of the child components. Make the hard-coded aspects of your UI dynamic based on the state/properties of the component. Again, aim for the UI to look the same way as you do this.
  5. Finally, figure out your event listeners. The tic-tac-toe tutorial mentioned earlier is a useful reference on the proper way to pass around event listeners.
  6. And remember … no more getElementById (or similar things)! And no widespread usage of refs or useEffect or other escape hatches .

Grading Client2

Points: 50 points

  • (10 points) Completed the setup instructions and the React tutorials.
  • (10 points) Works on the CI and deployed to GitLab Pages
  • (20 points) Refactored to React components
  • (5 points) Proper use of props for passing data to components
  • (5 points) Proper use of state for updating dynamic elements

Nutrikit Specifics

  • Your state will likely be a collection of what the menu items are and which ones are selected.
  • Your state would also likely need to store which category is currently selected. Perhaps that needs to be in the top-level state, or perhaps that’s a state variable for the component representing the menu?

Client-3: Responsive Design, New Features

Your branch name should be client3-dev. When you have merged, the tag should be client3.

Be sure to update your .gitlab-ci.yml to update the PROJECT_NAME3variable

In this iteration, you will be focusing on both expanding the functionality and incorporating responsive design into your project.

Client 3 setup

  • Create a NEW React app.

    • In your root directory, create a new app npx create-react-app abc123-react-client3 (again, abc123 is YOUR id)
    • You will now have a directory structure similar to this:
            .  
            ├── .git/  
            ├── .gitlab-ci.yml  
            ├── README.md  
            ├── abc123-react-client2/  
            │   ├── .gitignore  
            │   ├── README.md  
            │   ├── node_modules/  
            │   ├── package-lock.json  
            │   ├── package.json  
            │   ├── public/  
            │   └── src/  
            ├── abc123-react-client3/  
            │   ├── .gitignore  
            │   ├── README.md  
            │   ├── node_modules/  
            │   ├── package-lock.json  
            │   ├── package.json  
            │   ├── public/  
            │   └── src/  
            ├── public/    
            │   ├── index.html  
            │   └── index_1.html  
        ```   
    
    
  • NOTE:

    • This is a new project, so you should copy over any files you need from client2 into client3

Responsive Design

We would like you to research and incorporate Reactstrap into your project. Reactstrap is a library that creates React components for incorporating Bootstrap features easily. Install using the npm install command they show (not the CDN install). Be sure to review the About the Project for an explanation of how it it integrates the two.

We would like you to:

  • Use the Reactstrap components (also see Bootstrap ). We will give an overview of this in class, so be sure to review the lecture. If a Reactstrap equivalent component doesn’t exist, you can use basic Bootstrap or HTML, but try use use Reactstrap for the majority of the work.
  • Your application must be usable on a desktop, and usable on an iPhone X, i.e. 375 x 812 px. We want the following:
    • Use the Grid System to lay out your UI and place the Reactstrap components. I like to use Container, Row, Col for layout and Card, Dropdown, FormGroup for data etc. … but feel free to expand your horizons.
    • The UI must adjust on the desktop vs. on mobile, i.e. take advantage of the Bootstrap breakpoints, enable the layout to ‘flow’
    • When on a mobile device, the components need to be arranged to maximize the screen real estate
    • No horizontal scrolling on either desktop or mobile
    • All UI components should be big enough to be usable by touchscreen, i.e. “fat finger compatible”
    • Minimize the number of “clicks” or “taps” needed to use your UI
    • This is still a simple application, but keep basic usability in your implementation.
    • Ensure error cases are cleanly handled. Now that you have a ‘real’ UI, this is an important task for development. Make sure you test for error cases, not just ‘happy path’

Test out your application in the browser’s Development Tools used to simulate devices. In Chrome it’s called Device Mode and Firefox it’s Responsive Design Mode. Note that just resizing the window is not a perfect simulation of what it would look like on a device.

Nutrikit Specifics

  • Make the add and remove two separate buttons for “Selected Items”
  • Add additional nutrition information to menu items, including total fat, saturated fat, trans fat, protein, and total carbohydrate. Assume this data is pre-loaded, as before. Look up reasonable examples for your built-in data. You can also use this for starter data if you wish. Adapt for your code as needed.
  • Add a simple visual representation of both a single food and the total, similar to a standard nutrition label. Add visual indicators (e.g. colors, icons, visual cues) for when the value is considered “high” (according to the FDA guidelines we just linked to).
  • Provide a way to edit a food item’s values. Populate the existing values in the edit dialog so it is easy to modify.
  • Provide a way to add a new food item in an existing food category
  • Use pop-up Reactstrap Modal dialogs to make data-entry easy
  • Add a total calorie goal and show the progress toward that. We recommend the Progress Bar as a simple way to represent this. Default to 2,000 calories but allow people to change this number for them.
  • Improve the UI according keeping in mind UI design guidlines, simplifying as best you can.

Grading Client-3

Points: 60 points total

  • (5 points) Builds on the CI by Lab Day
  • (5 points) Quality feedback given
  • (5 points) 2 buttons for add/ remove
  • (5 points) Additional nutrition information loaded with edit
  • (15 points) Responsive features and guidelines
  • (15 points) Aggregated nutrition label; single food item and total with visual indicators
  • (10 points) Total calorie goal progress bar, with edit capability

Client-4: Full Stack

In this assignment, you will retain functional parity with client-3, but move all your persitent data from the client side to the DB server. You will again be using PostgreSQL and Flask based RESTful APIs as your mechanism for accessing the DB.
Your branch name should be client4-dev. When you have merged, the tag should be client4.

Be sure to update your .gitlab-ci.yml to update the PROJECT_NAME4variable

Setup

  • Once again, create a new React app (from the root of your directory).
  • e.g. npx create-react-app abc123-react-client4 (abc123 is YOUR id)
  • You should copy over any files you need from client3 into client4

You will need to add a Flask server to your project to host the RESTful API and the DB. This will be similar to your prior REST work. Create a folder named server in your project. This should be at the same level as your abc123-react-client4 folder. Inside the server folder, create an api folder along with any __init__.py files. Add a db.yml file for your setup (in the api directory).
You can download example files for setting up full-stack server code here. Adapt for your code as necessary. There are no files in src in the example, but you can add any helper items there. There is a .gitlab-ci.yml file provided (to allow running this standalone), but for your project, you should use the version from client-3 and update as needed.

You can copy the files in the server folder into your project, and modify to fit your assignment. A starter .sql file is provided for testing purposes. You can delete this file and use your own schema for the project. You will need to add your own db.yml to the server/api folder.
Your directory stucture should look similar to this:

├── abc123-react-client4   
│   ├── public  
│   └── src  
├── public  
├── server  
│   ├── api  
│   ├──── __init__.py  
│   ├──── db.yml  
│   ├──── example_api.py  
│   ├──── people.sql  
│   ├──── swen_344_db_utils.py  
|   |── server.py  
│── __init__.py  

Items to Note:

  • Since the DB is on the server, it must be initialized when the Flask server starts. Notice that the server.py file loads the DB directly (exec_sql_file(...)).
  • There is a sample React file (mycomponent.js) provided that shows how to use the Javascript fetch method. Review this and adapt for your code.
    • The sample file also shows how you can use the React built-in event componentDidMount to trigger your code to kick off the fetch and get the initial DB data using a RESTful API.
  • There is a test folder in the sample code. This is just to show you that you can still run python client side code to confirm your API functionality. You are not required to create any client-side python code for this project.

Running the Flask server

To make sure your Client can talk to your Server, we need to make some changes to avoid CORS errors.
You will need to add a new module for the Flask server.

  • Type pip install flask_cors on the command line (pip3 for Mac).
    This will enable the Nodejs server to make API calls to another server (the Flask server) without CORS errors.
    You will see some additional code in server.py in the provided skeleton code. (Review this for your understanding)
app = Flask(__name__) #create Flask instance  

CORS(app) #Enable CORS for Flask  

api = Api(app) #api router  

As before, run your API (Flask) server by typing py server/server.py. You need to start up the Flask server before running your React client.

Running your React Client code

  • Calling the endpoints
    • Make sure you call the endpoints in your javascript code with the full URL http://localhost:5000 (do not use a relative path to the endpoint)
  • Mac Users
    • If you needed to change Flask previously (in REST) to run on a different port (e.g. 4999), then you will need to do that again when making the API calls.
    • Similarly, if you needed to use 127.0.0.1 instead of localhost, do that.
  • Running the web page server
    • We have a backend server with Flask, but now we will also be running the front end web server for the React pages. Use a separate console window and type npm start to run the Nodejs server and bring up your web pages.
      • This will run your web pages on port 3000.

CI/ gitlab pages

Since the data is now loaded from a backend database (which will not exist in the gitlab deployment), the gitlab webpages will no longer be provide full functionality. Just make sure your webpage display handles that situation (i.e. handles the fact that the API call will fail), and provides a reasonable default behaviour.

Nutrikit Specifics

  • Keep the initial nutritional data in a DB on the ‘server side’. Include all information in a table/ tables of your own design. When your page loads, it should get the data from the server. Provide a GET API to retrive that data. Provide any filters necessary for your design for retrieving data.
  • Allow the ability to modify nutrition data for existing food items as before; update the DB accordingly (PUT API)
  • Allow the ability to create new food items in an existing category as before and add to the DB (POST API)
  • Add the ability to delete a particular food item (DELETE API)
  • Provide a progress bar to show status vs. the goal for the caloric value as before
  • Keep the functionality for moving items between the category items list and selected items list, but you do not need to update the DB with that information, since it is transitory information.
  • In all cases, the web page should be displaying the data it retrieves from the DB using the REST API
    • Don’t leave modified data that should be committed to the DB cached in browser/ client data
    • When the user is filling in a form for new or modified data, don’t commit the data to the DB until the user confirms the changes. Make sure the user can cancel the action if they choose to do so.

Grading Client-4

Points: 60 points total

  • (5 points) Builds on the CI by Lab Day
  • (5 points) Quality feedback given
  • (10 points) All prior functionality still works!
  • (5 points) Flask server and DB properly setup and initialized
  • (15 points) API to load initial data on client (GET)
  • (20 points) Dialog and API to update/ create data (PUT/ POST)

Full points awarded only if all prior functionality works AND is propertly implemented using RESTful specs and requirements