‫Let's now make our watched movies list work,
‫and let's do it all in one go.
‫So this is gonna be a long one,
‫and so let's quickly get started.
‫And let's actually get started by quickly recapping
‫what this watched list actually is.
‫So remember how we already have this watched state here,
‫which right now is this empty array,
‫but it used to be this tempWatchedData.
‫So let's close this here.
‫And so you see that then we had these two movies
‫with a few details, with the user rating
‫and then also this summary right here.
‫Now, of course we will start from zero here,
‫and then we can add each of the movies here to our list.
‫So they will then appear over there.
‫So we already have the list component.
‫So it should be somewhere down here.
‫So we have the watched summary,
‫we have the watched movie list,
‫and we have the watched movie itself.
‫So each of these movies needs the poster, the title,
‫the rating, the user rating, and the runtime.
‫So basically we need to create a brand-new object
‫for each of these movies
‫and then pass each of these objects here
‫into this watched array.
‫So actually let's start by creating that function
‫with which we can add a new item to that array.
‫So let's call it handleAddWatch.
‫Then we get a movie.
‫Let's call this watched.
‫And then let's do it as always.
‫So we call setWatched,
‫and then we get the current watched movies array,
‫and then we create a brand-new one based on that one,
‫so based on all the elements of that array,
‫and then the brand-new movie object.
‫Okay, and now we just need to pass that in,
‫so again as a prop.
‫And you see that this component is getting really big,
‫and the same for this entire file.
‫So if you want, feel free to split up this file
‫into multiple files, so one component per file.
‫But anyway, I will just keep working here.
‫And so let's pass that function
‫that we just created here as onAddWatched,
‫handleAddWatched.
‫So we're passing that into MovieDetails
‫because, again, that is where we will actually have
‫the button to add the movie to the watched list.
‫So it will be right here.
‫And so then here in this component, we set the state.
‫It will get updated in the parent,
‫and from there it goes back here into the statistics
‫and then into this list, of course.
‫Okay, but now let's then move to the MovieDetails component
‫and let's add a button right here,
‫so under this rating.
‫So here let's say button
‫with the className of btn-add
‫and then Add to list.
‫Now, here of course, we need our event handler,
‫and let's actually create another event handler right here
‫which will then call the one
‫that we passed into the component,
‫because here we actually need to do a lot of stuff.
‫So function handleAdd.
‫And so, again, this one will then eventually call
‫that function that we passed here as a prop.
‫So that was onAddWatched.
‫So again, in the end, we will call that function here,
‫which, remember, needs a new movie object as the input.
‫So newMovie, basically.
‫So like a new watched movie.
‫So let's create that object here.
‫Let's actually call it newWatchedMovie,
‫just so we understand what we are doing here.
‫So this movie object will also need an IMDB rating,
‫and here we can simply use the one
‫that is currently selected.
‫So the currently selected ID is
‫of course the IMDB rating of that movie
‫that we are going to add.
‫Then remember we also need the title, of course,
‫of the movie, the year, the poster,
‫the IMDB rating.
‫And here we actually need to convert that to a number.
‫And the reason for that is that the rating needs
‫to be a number so that we can then do the statistics here,
‫so calculating the averages.
‫So let's just use the number function on the IMDB rating.
‫And finally, we also need the runtime.
‫Now, if we take a look at one of the movies,
‫you you see that the runtime includes the minutes here.
‫And so again, with this,
‫we can then later not do any calculations.
‫So we need to basically split that,
‫so runtime.split
‫by an empty string, which will just get us that first part.
‫And then from there, we can just take that first part,
‫and then we just convert everything
‫to a number again.
‫Now, here we get some problem.
‫It's because we have a duplicate key.
‫That's because here, of course, it is the imdbID.
‫So thanks ESLint here for letting me know.
‫That was a pretty big problem, actually.
‫So let's see if this already works at this point.
‫So maybe it does, maybe it doesn't, but let's see.
‫Let's see our console.
‫So there are a lot of moving pieces here, so let's check.
‫So let's add this to our list.
‫And we didn't get any error,
‫so let's go back to see our list, and there it is.
‫I mean, there are still some problems here,
‫but something did work, so that's great.
‫Now, I think it is because down here,
‫we are using some of these properties
‫with their uppercase letters here.
‫So this should be title, and title like this.
‫And, yeah, beautiful.
‫The only thing that we are missing here is the stars.
‫And so that's actually what we're gonna take care of next.
‫So let's go back here.
‫And I just remembered that actually there is something else.
‫So let's say we also want to add this one.
‫So we add it to the list, but then nothing happens.
‫So I think that as we click here,
‫we should probably close this movie
‫and then basically go back.
‫And so then we can immediately see the new movie
‫that has been added.
‫So that's not too difficult
‫because we already have a function for that.
‫So it's this handleCloseMovie.
‫And so this is the function
‫that we now want to call here as well
‫as soon as a new movie is added there to that list.
‫So into MovieDetails.
‫Ah, we already have the function there.
‫Well, that's very convenient.
‫And, yeah, of course we do have it
‫because of this button here.
‫Okay, but anyway,
‫yeah, here it is.
‫So after adding a movie,
‫we then want to immediately also close the movie.
‫Okay, let's add this.
‫And so there it is again.
‫Now, you immediately see that there is a problem
‫because we already have the movie on the list,
‫but we will take care of that a little bit later.
‫For now, let's take care of the user rating here.
‫So let's maybe just reload, which will clear our list.
‫And, yeah.
‫So basically we want to be able
‫to get this rating here from the user,
‫and then as we add to the list,
‫that should be the rating that should be added here
‫to this new watched movie, right?
‫Or in other words, we now need the state that we have here,
‫like this nine rating.
‫We need it outside the StarRating component
‫and inside our MovieDetails component.
‫So how do we do that?
‫Well, remember that we actually created a way
‫of getting that state outside the component
‫by adding in a function.
‫So we defined the onSetRating prop.
‫And so into this, we can pass a state, set, or function.
‫So then we need that state, set, or function.
‫So let's create yet another piece of state here
‫for that rating.
‫So userRating
‫and setUserRating.
‫So useState, and here let's just start at an empty string.
‫Okay.
‫Now, for some reason we are already using this somewhere.
‫Well, not really.
‫So I was saying that because it wasn't
‫with the yellow underline.
‫But anyway, let's get the setUserRating
‫and then pass it here into our StarRating component.
‫Then let's reload.
‫Then let's open up this.
‫Give a rating.
‫And if we now check in here in our component.
‫So this we haven't done in a long time,
‫but, again, this is really helpful.
‫So here we have...
‫Ah, that reset everything.
‫Sometimes that happens when you click.
‫But anyway, here in our MovieDetails,
‫we see all the props, like the selected ID and the state.
‫So here we have, of course, the MovieObject
‫that has been loading.
‫Then we have the is loading state
‫and finally the current rating.
‫So as we click here now, you see that this changes,
‫and so therefore that means that now we have the state
‫inside our MovieDetails component.
‫Of course, it's also still inside the StarRating.
‫So here we have the same.
‫So of course now that changes to 10,
‫but now it also changed to 10 in MovieDetails.
‫All right, so that's really helpful.
‫And so now we can just add that new state
‫right here to that object, so userRating.
‫And now as we have this userRating,
‫we only want to allow a movie to be added to the list
‫if the user actually gave it a rating.
‫So let's translate that requirement into code.
‫And so what I just said is basically this.
‫So if userRating is greater than zero,
‫then display the button.
‫So let's reload that here manually.
‫Okay, and so now the button is gone.
‫But then as soon as I click here, the button will appear.
‫And now I add it, and there it is.
‫So there is our eight.
‫Now, I haven't watched any of these other ones.
‫Let's just give it something.
‫And then indeed, we get this movie with the IMDB rating
‫and with my own rating.
‫And so then the average between these two
‫is actually correctly calculated with 5 1/2.
‫Great.
‫Now, next up we need to ensure
‫that I cannot just add this movie here
‫as many times as I want.
‫So of course, I can keep going,
‫and I can keep going over and over again.
‫So now I have the exact same movie here three times
‫in my list, and that should not be allowed.
‫So basically when we come here to this component,
‫we want to check if this movie is already in the list.
‫And if it is,
‫then we don't want to display any of this here.
‫So then we can no longer rate it,
‫and it should then simply display the rating
‫that we already gave.
‫All right.
‫Now, does that maybe sound like something
‫that you might want to try on your own?
‫I know it sounds probably a bit scary,
‫but I think you could actually do it.
‫So if you are up to speed
‫with how the data flows through this application,
‫I think you will be able to do this.
‫So maybe take a minute or two now,
‫and then I see you back here once you are done with that.
‫All right, so maybe you tried it.
‫And if not, that's also absolutely no problem.
‫So what we need to do is to now pass the watched array
‫into that component, right?
‫So that is right here.
‫So the watched array, we simply pass it as a prop.
‫And so then with that, we can check for each of these movies
‫if it is already part of the watched list.
‫Okay, so let's calculate that here.
‫So a new piece of derived state,
‫which is isWatched.
‫So what we need to do now is to basically check
‫if the watched array that we need
‫to accept here still as a prop.
‫So we need to check if this array of objects
‫includes the array that is currently selected.
‫So let's do that, so watched.
‫And let's first transform this simply into array of IDs.
‫So we grab all the movies,
‫and then we simply take out the movie.imdbDB.
‫So let's just lock that to the console here,
‫just to make sure.
‫All right.
‫Let's check that.
‫Somehow it's taking a lot of time here.
‫So right now we have nothing on the watched list.
‫So let's add a couple of movies there.
‫All right, and for some reason,
‫we are getting undefined here.
‫Ah, but I see that's because here it should be imdbID.
‫And indeed, now it works.
‫So we have this array now, and so now all we need to do is
‫to check whether this array
‫includes the currently selected ID.
‫All right, and now based on that,
‫we will basically display this entire thing here,
‫so all of this.
‫So let's say if isWatched...
‫Well, let's start with if it's not watched,
‫then display what we have here.
‫And if not, then let's just create another paragraph here.
‫You rated this movie.
‫And then we can also later calculate
‫or derive the rating that we actually gave.
‫Now, here we need to return yet again
‫a piece of JSX with a fragment.
‫So just like this.
‫And, yeah, so here is where we then place that paragraph.
‫So working with JSX, as you see,
‫can always be a bit confusing.
‫And even after you have done it for years,
‫it can still take a little bit of time.
‫All right, and now you see you rated this movie.
‫And the same with this one,
‫but this one we haven't rated, so it not on our list.
‫So only these two.
‫And so for all the other ones, we can still rate them.
‫So we tried the third one,
‫and so now as we click on that again,
‫then you see that we can longer add it to the list.
‫So that option is now gone.
‫And so we fixed that problem.
‫Now all we have left to do is
‫to then place the current rating there.
‫So let's again derive that from the watched array.
‫So let's say const watchedUserrating.
‫And then let's take watched.find.
‫So we will just find the movie
‫where the movie.imdbID
‫is equal to the selected ID.
‫And then if that exists.
‫And so here we are now using optional chaining
‫because there might be
‫actually no movie already in the list.
‫So if we haven't watched a movie,
‫then here this find method will return nothing.
‫So here then we need optional chaining
‫so that userRating is only taken from that object
‫in case it actually exists.
‫All right, so again pretty standard JavaScript right here,
‫but if that's confusing, then, yeah.
‫As I said many times, I have a review section
‫for all the stuff right at the beginning of the course.
‫So watchedUserRating.
‫And, yeah, here we go.
‫You rated this movie seven.
‫Maybe let's add some nice emoji here once again.
‫So the star, where is it?
‫Okay, and so with this, we are now almost, almost done.
‫So our list works almost the same way as before.
‫So you see now it is here.
‫And our "Inception," for example, has the eight,
‫which is also had here.
‫And all the other ones have the seven.
‫Okay, and now the only thing that is left to do
‫is the ability to also remove movies from the list.
‫So that's the only thing that is here in the demo app,
‫but which we do not have yet.
‫So this button right here where we click,
‫and it will then remove it from the list.
‫All right, so let's go again back up here
‫where the state actually lives.
‫And then let's add the function
‫for handleDeleteWatched.
‫So then here let's pass in the ID,
‫and then here we do it just like we always do.
‫So we use the current watched movies array,
‫and then we filter out the one that we no longer want.
‫So we get the current movie,
‫and then if movie.imdb.ID
‫is different from the passed in ID,
‫then that movie will stay basically in the array.
‫But if it's the same, then that movie will be filtered out,
‫so it will be deleted basically.
‫And so now let's pass in this function into the list here.
‫So that is the WatchedMoviesList.
‫So the movies, so these movies right here,
‫they are inside the WatchedMoviesList,
‫and so therefore we need to pass this function into there
‫so that we can then pass it
‫into each of these movie components right there.
‫So onDeleteWatched
‫is handleDeleteWatched.
‫And let's move there,
‫so onDeleteWatched.
‫And then let's immediately pass that down
‫into the child component,
‫so onDeleteWatched is onDeleteWatched.
‫Okay, and then let's go there.
‫Ah, that's right here, onDeleteWatched.
‫And don't worry if it's taking you a lot longer
‫to process all of this, so to write all the code.
‫That's just completely normal, of course.
‫When I built this app here for the first time,
‫it also took me a few hours to build this,
‫so it was not nearly as fast as right now.
‫But of course, here we cannot take like 30 hours
‫(chuckles) just to build one small application, right?
‫But anyway, here let's now create this button.
‫We need to give it the class of btn-delete
‫and then onClick.
‫And don't forget it needs to be a function,
‫not a function call, so onDeleteWatched.
‫And then all we have to do is to pass in the ID.
‫So once again, that's movie.imdbID.
‫And that should be it.
‫So you see that the buttons are here, and let's see.
‫Yes, that works, and our statistics get updated.
‫Now here we have still this weird thing
‫where JavaScript is like really bad at math.
‫Or actually this time it looks
‫like it's not even JavaScript's fault.
‫But let's just fix that
‫because that looks just like really bad.
‫So we should be able to just append
‫a toFixed here, hopefully.
‫Yeah, that's a lot better.
‫Let's do the same here for the rating, toFixed.
‫So the two here is the number of decimal points basically
‫that we are allowing.
‫Yeah, but anyway, that's actually it.
‫So you see our stats updates in real time, of course,
‫and now everything is back to zero.
‫All right, so as I said in the beginning,
‫it was a long lecture, but we also got a lot of stuff done.
‫Now, I'm aware that we moved a lot of, like, data
‫up and down the tree
‫and the same for some handler functions,
‫and so please again just make sure
‫that you really understand what we just did here.
‫And with that, I think our component tree
‫can really help you out a lot.
‫So just analyze all the props
‫that all these components receive,
‫how the state changes over time.
‫And so all of that will really help you out
‫in becoming a better React developer
‫because, as I mentioned many times before,
‫you will also have to learn
‫to work with other developers' code.
‫And so then these skills of really analyzing the code
‫and the data flow will become very handy.