W03 Individual Activity: Expand Inventory
Overview
Many of the changes we have already made were to prepare the site to be able to scale up to as many products as we would like. In this activity we will add products organized from four categories: Tents, Sleeping Bags, Backpacks, and Hammocks. We will need to change the index page to show our four categories, and then build a dynamic product-listing page that will pull the products from an API, and display them.
Instructions
Complete the following assignment individually. Each student will write code for their own copy.
Core Requirements
Start the Task
- Visit the team's copy of the Trello board for the project.
- Add yourself to the
Individual Activity W03: Expand inventory
task. - If no one else has done it yet, move it to
'Doing'
list. - Read the details of the card.
- Make sure to pull any changes from GitHub before proceeding.
- Create a new branch called
yourinitials--individual3
.
Refactor
- Create a new directory is
src
calledproduct-listing
. - Add a new
index.html
file to that directory.Remember that the words directory and folder have essentially the same meaning. Directory is the more accurate term for file systems while folder 📂 refers to the graphical metaphor that is generally accepted because it is highly related to the term file. - Create a
product-listing.js
file in thejs
directory. - Add basic HTML to the new
index.html
page such as the header, footer, styles, etc. You may just want to usesrc/index.html
as a starting point. Then remove the unnecessary content including the banner and text.🔨 Adding a new page to the site requires thatvite.config.js
file be updated to let Vite know about it or the build will break. - Move the JS from the
main.js
that is responsible to render our list of products to the newproduct-listing.js
file. - Open up
product-listing/index.html
in the browser to make sure the tents are still rendered.🔨 You will need to fix some paths to get everything working correctly. For example, the new page will not be able to find the CSS file nor the new JS file we made until the file paths are fixed. Do not worry about fixing the image URLs yet. Those will change again anyway and we will fix those later. - Add a grid of four (4) boxes to the
src/index.html
page, one for each category. They should look something like this:
Here are links to the icons. The icons are being used with a Creative Commons license so we need to give credit to the creator. We will do that in this case by adding it to the alt attribute:- Tent (alt="Tent Icon from Noun Project: Mustofa Bayu")
- Sleeping Bag (alt="Sleeping Bag Icon from Noun Project: Mustofa Bayu")
- Backpack (alt="Backpack Icon from Noun Project: Mustofa Bayu")
- Hammock (alt="Hammock Icon from Noun Project: Paul Richard")
-
Each of the category elements should link to
product-listing/index.html
. Make sure to pass the correct category as part of the URL (tents, backpacks, sleeping-bags, or hammocks).If you need a reminder of how to add a URL parameter to a link check out the template function inProductList.mjs
. It has an example of passing a parameter in the URL.
Environment Variables
We are about to change our application so that it communicates with an API server. This server will provide endpoints that we can hit (access) to do things like pull product information, login users, submit orders, etc. During development, changes are made that do not need to show up in the production environment. A development server is a testing environment used during application development. The application can be changed without worrying about the live application on the production server which has the real real data that must be protected.
This separation is very common in development. This means however that we are going to have to change the URL we use depending on whether our code is running in a development environment or a production environment. We could do this manually, but chances are that at some point the development server URL is sent to the production server❗That would be bad.
Environment variables are a way to store values that are
specific to the environment the code is running in. For example,
we could have a variable that stores the URL of the development
server and another variable that stores the URL of the
production server. Environment variables provide values that change
automatically depending on where the code is running. Most of the time we
create these in a file called .env
(dotenv). We are
using Vite as our build tool and it has the built
in ability to work with these files. It will automatically look for a
.env
file and if it finds one it will make the
variables defined therein available through a special global:
import.meta.env
.
Because Vite is for building frontend projects where all the
code ends up in the browser, it gives us a way to control which of our environment variables
become available in our client facing code. Any variable we want to use in the code we send
out will need to be prefaced by VITE_
syntax.
- Open the .env.sample file in the src directory.
- Look for the variable named
VITE_SERVER_URL
. - Note that the server URL is provided as
VITE_SERVER_URL=https://wdd330-backend.onrender.com/
.This server URL variable is not something we need to keep secret. It needs to be available in the code. It has theVITE_
prefix. - 🗝️ Rename the .env.sample to .env using
File->Save As. Vite will now see the file and use the variables in it.
It is common practice to provide a sample with a different name to make it clear that it is not the real file.
You may be wondering why that file is called .env.sample. Environment variables often contain sensitive information in them and so it is common to not include those files in the Git repo for the project. If you take a look in the .gitignore file that is part of the project you will see in fact that we have already been ignoring .env files. Files named that way will never be tracked by Git.
The next question you may have is: "well if the environment variables do not get included in the repo...how do I get them out to my production environment?" That is addressed below.
When our code gets deployed to Netlify (the production environment) it will need to know the server URL it should use. Since our .env file will not be part of the repo we have to set it a different way.
Only one member of your teams needs to do the following maintenance.
- Log into Netlify and pull up the project.
- Navigate to the Site Settings->Environment Variables.
- Add a new variable.
- Enter
VITE_SERVER_URL
as the Key. - Enter the server URL
https://wdd330-backend.onrender.com/
as the Value. - Be sure to Save the new variable.
Pulling from an API
Next we need to modify our code to pull the product data from an API instead of from the local JSON file. Because of the way we have structured our code this should be fairly easy.
- Open up
ProductData.mjs
. -
In the constructor we set a path for the products. That path was based off of the tents category and would later be used to pull the data. With the API we actually don't need to set the category in our DataSource anymore. We can pass it in when we need it. This will make our DataSource more flexible.
Add the following line to the top of the file:
const baseURL = import.meta.env.VITE_SERVER_URL
Notice that we are using the environment variable we set in the.env
file. - Remove the category and path from the constructor.
- In the
getData
method, add a parameter ofcategory
and take this opportunity to change the fetch to use async/await. Change thegetData
function to look like this:async getData(category) { const response = await fetch(baseURL + `products/search/${category}`); const data = await convertToJson(response); return data.Result; }
Why returndata.Result
? It used to be simplydata
. The data sent back from the API is structured differently. We will have some other corrections to make because of this as well. - Open
productList.js
. - Change the line in the
init()
method where we get our data. It should look like this after our changes:const list = await this.dataSource.getData(this.category);
You should now be seeing products listed if you click on one of the links, but there are two issues. The first is that no images are showing. The second is that all the links are showing the same list of products.
Pulling the Correct Products
You should be passing category in the URL to the
product-listing
page. We need to retrieve it from the
parameter in product-listing.js
. Then send it into
the ProductList
class. Remember that we created a
method in utils.mjs
earlier to grab parameters from a
URL.
We have been moving a lot of things around. At this point your
product-list.js
file should look something like this:
import ProductData from './ProductData.js';
import ProductList from './ProductList.js';
import { loadHeaderFooter, getParam } from './utils.mjs';
loadHeaderFooter();
const category = getParam('category');
// first create an instance of our ProductData class.
const dataSource = new ProductData();
// then get the element we want the product list to render in
const listElement = document.querySelector('.product-list');
// then create an instance of our ProductList class and send it the correct information.
const myList = new ProductList(category, dataSource, listElement);
// finally call the init method to show our products
myList.init();
Fix the Product Detail page
If you try and click on on of the products to see the details you will notice it is broken.
We will need to make some of the same changes to product.js
and
productDetail.js
that we made for the product listing.
There are a few places we need to check to do this. We should make a list:
-
Because we moved the product listing page into a directory
the URL listed in the template for a product card in
product-listing/index.html
will be wrong. That needs to be fixed first. -
We removed the requirement for the DataSource to be set to a
specific category, and we updated the
getData
method. Now we need to fix thefindProductById
method. We can query the API directly for this. The URL for the API endpoint you need to hit is:`${baseURL}product/${id}`
- Once you get it working you will find that the image is broken. We need to figure out why. See below for more on this.
Stretch Actviity
Fix the images
The data structure of our products changed slightly. This is why the images are broken. Analyze the data coming back from the API and figure out how to fix this issue.
PrimaryMedium
image for the productList, and
PrimaryLarge
for the productDetail for now.
Fix the title
Title of the page currently says: Top Products. Add the category
to that so that it looks like this:
Top Products: Tents
(if the
tent category link was selected)
Instructor's Solution
As a part of this individual activity, you are expected to look over a solution from the instructor, to compare your approach to that one.
Do NOT open the solution until you have worked through this activity individually for at least one hour. At the end of the hour, if you are still struggling with some of the core requirements, you are welcome to view the instructor's solution and use it to help you complete your own code. Even if you use the instructor's code to help you, you are welcome to report that you finished the core requirements, if you code them up yourself.
Finally
Wrap up this individual project work by finishing up your individual work and then coordinating with your team.
- Commit and push your changes.
- Meet with your team and discuss which team member's changes (branch) you would like to
keep.
Your team will only keep one. - Submit a request for the branch that you decided to keep.
- Review the Pull Request, close it, and merge the branch back into the Main branch.
- Move the Trello card to the
"Done"
column.
Submission
Return to I-Learn to report on your work.