Skip to content

Code-Platoon-Assignments/video-store-0-functional-js-and-state

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Practicing Modern JS - Video Store

We will use what we have learned to build the logic to handle the data for a video store. We will do this in JS and make a node project for it.

Instructions & Advice

Depending on your experience level this may be a big assignment, but it builds up in logical steps. Do not worry if you don't complete every step.

If you do finish this assignment and have time on your hands, continue adding features to the video store following the patterns you have been shown here. Feel free to reach out to an Instructor or TA if you would like additional guidance on how to do this.

Project setup

  1. Create a new node project named "my-video-store", or, whatever you want.

Import JSON

  1. In app.js import video-store-inventory.json into a variable named inventoryJson.

Format & Manipulate JSON to get a good application state

We need to do some work to use our inventory. First, each video needs a unique ID that we create (imagine this is a database primary key). The existing id attribute for each video is actually it's ID on imdb.com - which is great, but not what we need. So:

  1. Use .map() to rename id to imdbId.

  2. Install the npm package uuid. An UUID (universally unique id) is an alphanumeric string generated by some sort of fancy math that is guaranteed to be unique throught the entire universe. The perfect way to make sure two videos don't have the same ID in our system!

  3. Take 5 - 10 minutes to test out uuid and read the docs before doing work with it.

  4. Use .map() and for each video create a property named id -- which should be a UUID. So each video has an id which is an unique UUID.

Add metadata

We want to know when the video was added to our system. To do this we'll want to add a createdAt property with a datetime value. To help keep our data organized, we are going to add it inside a _meta property. Here is an example of what a video record will look like now:

{
    id: "8c0cf063-d505-4ff6-be5f-b90f19b97008",
    imdbId: "tt6615224",
    title: "A Snowy Day in Oakland",
    imgUrl: "https://images.fandango.com/ImageRenderer/200/0/redesign/static/img/default_poster.png/0/images/MasterRepository/fandango/231006/asnowydayinoakland-posterart.jpg",
    copiesAvailable: 0,
    totalAvailable: 4,
    rating: "PG-13",
    description: "It snows one dat in Oakland and everybody is talking about it! Wow, it snowed! In Oakland? Wow! Someone should make a movie about this. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    _meta: {
        createdAt: "2023-10-01T01:17:26.103Z"
    }
}

You could do this in the same .map() operation as before, or if you prefer, chain two map operations together like so:

const inventory = inventoryJson
    .map(video => /* do stuff to rename `id` to `imdbId` */ )
    .map(video => /* do stuff add the new `id` prop and give it a UUID */ )
    .map(video => /* do stuff to add the `_meta` property with a `createdDate` to each video */ )

The above approach is worth trying. Even if it is overkill in this specific case, method-chaining like this is a technique you will see used more and more, and, it offers the advantage of being able think about each step in smaller chunks - which is easier to do and easier to implement. You're less likely to make errors.

Stretch goal: use date-fns

Instead of using JS's built-in Date() function by itself, use the date-fns npm module. dayjs is a popular alternative as well. Note that you'll have to install them with npm.

Users!

We need some users. We want something like the following:

const customers = [
    {
        id: "abxasj23498h245h", // THIS IS A UUID!!!!
        name: "Alice",
        email: "alice@gmail.com",
    },
    {
        id: "s29dafor2h8h245h", // THIS IS A UUID!!!!
        name: "Bob",
        email: "alice@gmail.com",
    },
]
  1. Create a makeCustomer function which returns a new customer object like above.
  2. Use it to build an array like the one above.
  3. Go wild - add whatever other fields you want, etc.

Application state

Our program now has two kinds of data - videos and customers.

As new customers are added, old customers leave, and videos are checked out and returned, the state of our program changes. "State" is simply a term for "a snapshot of your program in a current moment."

Which means:

  • The values of all the variables
    • Including iterators for loops, etc

You will see why a bit more when we start using React, but it is often best with JS programs to manage state by putting it all together in a single object. We want something like:

const state = {
    users: [
        { // alice },
        { // bob },
        { // bob },
        // ... and so on
    ],
    videos: [
        { // one video here },
        { // another video here },
        // ... and so on
    ]
}

Task: Create a state object for you program like the one above.

Finding stuff

Find a customer

Write a function to get a customer by id. It must accept our state object as input, along with the desired customerId. It must use .filter(). It should look like this:

function getCustomerById(state, customerId) {
    // does stuff with state.filter()
    // returns a customer object 
}
  • Now write a findCustomerByEmail() function that works the same way.
  • Now write a findCustomerByName() function that works the same way.

Find a video

Follow the above pattern and:

  • Write a findVideoById() function
  • Write a findVideoByImdbID() function
  • Write a findVideoByTitle() function

Find all videos which have copies checked out

  1. How do we know if a video has at least one copy checked out?
  2. Write a findAllVideosWithCheckouts() function that follows the above patterns.

New Feature: Customers Checking out Videos!

Update our customers object

Lets add an array, checkedOut, to our customer object. It will hold the ID (our id, NOT imdbId) of each video a customer checks out.

Edge case -- w/the above system, a customer cannot check out multiple copies of the same video. This is OK, but, if you want, think of an alternate approach

Our customer object should now look like this:

    {
        id: "abxasj23498h245h", // THIS IS A UUID!!!!
        name: "Alice",
        email: "alice@gmail.com",
        checkedOut: [
            "8c0cf063-d505-4ff6-be5f-b90f19b97008",
            "bcasdf0h2388w0yef", // <-- I made this up, this should be a UUID
        ]
    },
    {
        id: "s29dafor2h8h245h", // THIS IS A UUID!!!!
        name: "Bob",
        email: "alice@gmail.com",
        checkedOut: [], // If no videos are checked out the array is empty
    },

Create a checkoutVideo() function

Create a checkoutVideo function. It must look like this:

function checkoutVideo(state, customerId, videoId) {

}

Question: What should it return?

Answer:

  1. If no copies of the video are available, it returns false. Checkout attempt failed.
  2. If a copy is available, it returns true. Checkout attempt was a success.

It also must update the video and customer info, so we are tracking how many copies of the video are left "in stock", and which customer checked out what video!

New Feature: Return Video

Now, write a returnVideo() function that returns the same way.

Stretch goal: Add a customer history

Refactor your program, so that it logs, in our customer object:

  1. A history of all videos ever checked out by the customer
  2. The datetime when a video was checked out.
  3. The datetime when a video was return.

Stretch Goal: All customers who have checked-out videos

Write a function using .filter() to get an array of all customers who have 1 or more videos checked out. Then, modify your function so that it gets all customers with at least 2 videos checked out, or at least 5 videos checked out, etc.

Then, modify your function so it it also sorts the array of customers by number of checked-out videos. The person with the most videos checked out should be first!

New Feature: Genres

Add a genre to each movie. Feel free to make them up. It is up to you if a movie can have one or more genres.

New Feature: Find by genre

Write a findVideosByGenre() function. It should follow the same pattern as our previous functions. Important: You should assume this function will sometimes return more than one video, as there normally many videos of the same genre!

Stretch Goal: Get a list of all genres

Use .map() to get an array listing all genres. Make sure it is a flat array, meaning this:

['western', 'romance', 'drama', 'adventure']

... and not this:

[['western', 'drama'], ['romance', 'adventure']]

Stretch Goal: Construct a genre dictionary

Use reduce() to create an object which has each genre as a property, and then an array of movie ids belonging to that genre. It should look something like this:

{
    western: [ "abc123" ],
    drama: [ "abc123", "xyz456", ],
    romance: [ "xyz456", "dd344" ],
    adventure: ["dd344"],
}

Note that a film ID may be listed under multiple genres here.

About

Use modern functional JS approach to writing the logic handling the state and data of a video store rental program

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors