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 Startup: Your first web page
Overview and Setup
See the client project introduction page for the Client-0 overview and setup instructions.
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-610 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.
- Use the
- 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
onchangeevent anddocument.getElementByNameor get clever with onclick and pass in the object instance
- HINT: Use the
- 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
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…
Sample Page 1
Sample Page 2
Sample Page 3
Client 1
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. clubs.css or nutrikit.css) and a .js file for your javascript code.
NOTE: To avoid conflict with
client-0files, we are having you implement your HTML page forclient-1in 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 textNutriKit 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…
Sample Page 1

Sample Page 2: Add Item

Sample Page 3: 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.
- Do our React Setup instructions. Be sure to review the walkthrough explanation of all the files.
- Review the resources available to you at Getting Started with React. We have found these resources to be very well-written and helpful.
- They have a Tic Tac Toe tutorial that shows everything together. Please do this tutorial, as it will prepare you for your assignment.
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:
-
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.
-
Create component classes to represent elements of your UI. Put each component in a separate file.
-
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.
-
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.
-
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.
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
Grading Client-2
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
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_NAME3 variable
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,abc123is 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 About the Project for an explanation of how 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, Colfor layout andCard, Dropdown, FormGroupfor 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’
- Use the Grid System to lay out your UI and place the Reactstrap components. I like to use
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.
- 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
- (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 for goal
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_NAME4 variable
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_610_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.pyfile loads the DB directly (exec_sql_file(...)). - There is a sample React file (
mycomponent.js) provided that shows how to use the Javascriptfetchmethod. Review this and adapt for your code.- The sample file also shows how you can use the React built-in event
componentDidMountto trigger your code to kick off thefetchand get the initial DB data using a RESTful API.
- The sample file also shows how you can use the React built-in event
- There is a
testfolder 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_corson the command line (pip3for 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.
- 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.
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
GETAPI 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, update the DB accordingly (
PUTAPI) - Add the ability to create new food items in an existing category (
POSTAPI) - Add the ability to delete a particular food item (
DELETEAPI) - Add the ability to have goals for each nutritional value.
- Provide a progress bar to show status vs. the goal for each nutritional value
- 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)