Okay, so our next task is to deal with the product details component.
And of course we've got a text input here where we can define the quantity in the basket with a counter
because this is a number.
And then a button to add it to the basket.
And what we would ideally like to do is to be able to use this component.
So if they do go down to zero then we update the basket and it removes the item from the basket.
And of course we want them to be able to change the quantity and reflect that in the nav bar and the
order summary and our basket component.
And do all of that.
So slightly trickier, because we need to create the logic inside this component to handle these different
scenarios where we remove the item, reduce or increase its quantity by a certain amount.
And we've also got a text input this time to think about as well, and how we deal with that in a react
component.
Just to point out, first of all, I can click up and down inside this component right now because react
is unaware of it.
This is referred to as an uncontrolled component in react.
And if I go back to the code and this tidy things up at the top, and I'll just head over to the product
details component inside the code where we've got that text inputs or the text field, I should say
in material UI.
Then we've given this a default value.
Now when we use default value, you can pretty much say, well this is an uncontrolled component.
React doesn't know about this.
And in fact it does.
Tell us on the description here.
Use when the component is not controlled and not controlled means react does not know what this value
is.
Now we're going to change this to a controlled component.
And the way that we would do that is we would give it the value property instead of default value.
But what this does if I go back to the component is I've now broken my input.
I can't go up, I can't go down, I can't change it using the keyboard.
And I think we get a warning about this in the console as well, do we?
We do not.
Okay.
React 19.
I'm sure we used to get a warning about this sort of thing.
Maybe if I click no, we do not.
But this is just not working.
Text field now.
So effectively we need to track the value of this component in react state.
The text field component I mean and then we can use that value to get the value and update our basket.
So we're going to use a controlled component or controlled text field component for this.
And we've started that process by specifying the value here.
Now we would like to get that value of course from our basket to see if we've already got an item of
this type in our basket and update that accordingly.
So we're going to need to add a bit of functionality inside what is already quite a busy component,
but we'll persevere.
So first of all, we need to use the two mutation functions to either remove or add an item from our
basket.
So we'll set those up and we'll have the remove basket item function.
And I'm going to set that equal to use remove basket item mutation.
And we'll also have the add basket item function, and we'll set that to use add basket item mutation.
And we're also going to need the basket as well.
So inside here I'll specify const and say data.
And we'll give it the name of basket because we've got data down here.
But we have specified products for that one.
And we'll use the use fetch basket query.
And then we'll need to get the item from the basket so that we can find out if that item is indeed in
the basket.
So we'll create a const for this and say const item equals.
And we'll use baskets dot items dot find.
And we're going to look for the item that has x dot product ID that's equal to the ID inside our parameters.
And we've got a warning here that says this comparison appears to be unintentional because the types
number and string or undefined have no overlap.
So our ID is a string in our URL.
So let's see if we can get away with using the plus symbol.
We can.
And on this occasion we could be a bit more.
In fact, we cannot be a bit more defensive up here because what's going on with these hooks.
We cannot call any of these conditionally.
And we've got a hook down here as well.
And none of these can be conditional.
So if we add an if statement to check to see if we have the ID inside our code here we're going to run
into some TypeScript difficulties with the way that react hooks work.
They cannot be hidden behind the conditional, and we will always get a warning if we try to do so in
react.
So on this occasion, I'm going to use the overrides to tell TypeScript that I do not want this warning
to display here, and I know that the ID could possibly be undefined, so I'm going to use the exclamation
mark there just to take away the warning, because if we don't find an item that matches or we don't
have a basket, then the item is effectively just going to be undefined and I'm okay with that.
And then also inside here we're going to have some state to set the quantity.
So we'll have const quantity and set quantity.
And let's try and spell it correctly.
And I'll set this to use states.
And we're going to give this an initial value of just zero.
Now when our component loads we would like to be able to set the quantity if we do have the item.
So in order to add a side effect into our component, we'll add a use effect here.
And we will in its callback function add the dependencies afterwards.
Just an empty array for this one just now, and we'll check to see if we have the item.
And if we do, we're going to set the quantity to the item dot quantity.
And it's telling us that we need to supply the dependency, which of course is the item in this case.
Now we're also going to need a function to handle the updating of the basket.
Because we've got two scenarios here.
We could be reducing the quantity or adding to the quantity.
So we need to compare the quantity that we use in our input and compare it to the item quantity.
And if it's greater than or less than, then we either need to add or remove a basket item.
So we'll create a helper function in here as well.
And in fact we're going to need two helper functions.
So I'll say const handle updates baskets equals.
And we'll take no parameters.
And we'll open curly brackets inside here.
And we want to know what the updated quantity is.
And we're going to set this equal to item.
And we need to compare the item quantity with the quantity.
And to help us with this we'll use a math function.
And we'll say math Dot abs for absolutes and we'll use quantity minus item dot quantity.
Or it's going to be the quantity which means it hasn't changed.
So list.map absolute Len.
If we hover over this then this returns the absolute value of a number, the value without regard to
whether it is positive or negative.
And for example, the absolute value of minus five is the same as the absolute value of five.
So supposing that the quantity in this case this is what we're going to set it to is five.
And let's supposing the item quantity, what we currently have inside our basket is three.
So we want to go from 3 to 5.
Then in this example it would be.
And if we take a look at how we're using this function we're specifying quantity minus item quantity.
So that would be in this case it would be five minus three and that would give us.
Obviously that would give us two.
But supposing it was the other way round.
And supposing our quantity that we currently have is three, or the quantity in the inputs is three,
and we currently have five in our basket, then the calculation in this case would be three minus five
which would give us minus two.
But when we use the absolute function we effectively return two, which means that we change that into
a positive number, which means we would be removing two items from our cart.
So let's just a brief explanation of the math absolute that we're using inside here.
So now we have that we can check to see if we're adding or removing from our basket.
So we'll check and we'll check to see if we do not have an item.
Then obviously we're going to be adding to our basket at this point.
Or the quantity is greater than the item quantity.
Then we're adding something to our basket so we can use the add basket item method.
And in curly brackets we can specify the product and the quantity which will set to the updated quantity.
And we don't have access to the product at this point, which means I need to move my function below
where we're getting the product.
So I've got the const handle update basket here.
I just need to move it below the if statement in fact, because at this point we'll definitely have
the product.
So I'll just paste in the function there.
And then our warning goes away.
We've still got a warning because we haven't used it yet in our code.
Now we also need to handle the change of an input so that we can use the set quantity function based
on an input changing.
So inside here as well, we'll add another function and say const handle inputs change equals and I'll
just use event.
And for the time being I'll just use any and come back and correct this very soon.
And we'll add the arrow and open curly brackets.
And we need to get the value of the input.
So we'll say const value equals.
And if we take a look at what we get for the event then because I've given it the any type, I don't
have access to its properties.
So if we go down to the text fields and take a look at a text field, we'll just give it an Onchange
event.
As this is the event, we're going to be passing to our function and say handle input change.
If we hover over the onchange, then we can see what type of event this outputs.
And it's going to be an HTML input element event.
And we're using a react change event here.
So we can give this a type for our function.
And we'll come back to the handle input change.
And the event type we're going to be using is going to be a change event which we get from react.
And it's going to be of type Htmlinputelement and this will give us the event properties that we have
access to.
So we want to use the event current target dot value here.
And then we want to check to see if the value is greater than or equal to zero.
And then we'll set the quantity because we don't want them to be able to specify a minus number in our
input.
So we'll check to see if the value is greater than or equal to zero.
And if it is then we're going to set the quantity to the value.
And we've got a warning here no doubt because the value as coming in as a string.
And we want to cast this into a number.
So we use the plus symbol there.
And now our value is a number.
And we can check to see if it's greater than zero.
If it is at that point we set the quantity.
So back down to our text field.
Then.
And instead of one we'll set this to the quantity.
So if they don't have it in our basket it's default value is zero.
And as we change the quantity, then we should see that changing in the component as well.
Also, inside our button we'll use an onClick event and we'll use the handle update basket method.
And we'll also disable the button if and we'll add the equals and curly brackets.
And we'll disable the button is if if the quantity is equal to the item dot quantity, we don't want
them to click it.
If nothing's going to change or there is no item and the quantity is equal to zero, so that means they
don't have it currently in our basket.
And we don't want the button to be enabled so they can click on it if they haven't actually specified
more than zero to add to the basket.
And I've got some warnings inside here.
Let's see what those are about.
And we've got the remove basket item.
Of course we've only done one side of the handle update basket.
So those warnings, even though they're noisy, they can be quite useful because that's told me I've
forgotten to do something.
So we need to add inside here.
The else condition of course.
So we'll specify else.
And then we can use the remove basket item.
And this one takes in the product ID.
And that's going to be the product.id and also the quantity.
We can just use the updated quantity inside there.
So let's take a look at our progress.
And if we go back to this we can see if I well let's just refresh the page.
First of all we can see that I don't currently have this in my basket.
Let's just check the basket to make sure I've only got a green woollen hat inside there.
So if I go back then I should be able to increase the quantity.
And then we get the add to basket button.
And if I do add to baskets then we can see that we've now got three inside here in the nav bar.
And I've got the quantity of one inside here as well.
If I refresh the page then that stays the same.
The quantity is one and if I increase then I can add to basket.
Maybe I'd like to change that to update basket if we do have the item.
So I'll just head back to VS code to make that small change.
So we'll go down to the button where we've got the label, and we'll just check to see if we have the
item.
And if we do, we're going to specify update quantity as the label or add to basket if we do not have
the item.
And if I go back and take a look, then we can see that's set to update quantity now, which makes a
bit more sense.
And we should be able to reduce this to zero.
And that should remove it from our cart.
So if I just check we're looking at the green angular board I'll go to the shopping cart.
I can see I've got two of these in there.
Now if I go back and I reduce this to zero update quantity, the cart gets updated and is removed from
here as well.
But what do we see if we remove the green woolen hats?
Hmm.
We still see the order summary.
Our basket is technically empty, but I don't see anything in the background.
Do I want that kind of behavior?
Not really.
So let's head back to the basket page and make a small adjustment there as well.
And when we empty out a basket we do have the basket, but it's just got no items in the basket.
So we'll just check the items length as well here.
So I'll check the if no data or data dot items dot length is equal to zero.
Then we'll just return the your basket is empty there and that's more like it if we go back to the catalog
and let's just add something to the cart, then we see that popping in there.
Okay.
Marvelous.
And the only thing I really want to take a look at next is the checkout.
And we'll start to implement that, although only the very beginnings of it.
And we'll take a look at that next.