Now to make those update buttons work,
it's the same process as always.
We'll need to add a controller action,
a route, and then some
functionality to our model,
and then we need to send the request,
and here I plan to do this with Ajax
so that we don't reload the page,
but instead we just update the parts of the page,
like this price, and the total price,
and the number in the batch year
that needs to be updated.
So therefore let's actually start with the model,
because that is where I will have
the logic for updating our item in the cart.
And now there will be a wide variety of ways
of implementing this.
I'll try to keep it fairly simple
and simply add an update item method
in there where I expect to get
the product ID of the item I want to update.
And then the new quantity of that product,
because it is the quantity that we are changing here.
Now in there, we then have to differentiate
between two cases.
The quantity that is entered here,
could be 0, or even a negative number,
which basically means that we want
to remove that item from the cart.
In that case, I do want to remove it entirely
from the cart.
If it's greater than zero,
I instead know that I want to update
the existing item and change its quantity.
So therefore I'll start by checking new quantity
and check if it's greater than zero,
which means we don't want to remove it.
In that case, I then want to find the item
that should be updated,
and change its quantity
and price, and change the overall cart price.
And actually, I will also have to find
the item that should be removed
if I do want to remove it.
So we can even do that before I checked new quantity.
I can, again, loop through all my items
with that same loop I wrote before
for adding an item,
and therefore, of course,
we could also re factor this into
a separate method that does this.
Here, I will copy it,
and paste it into update item like this.
So again, I move through all the items then,
and then I look for items where
the product ID offer item
matches the product ID I'm getting here
as a parameter value.
And then I want to update the quantity
and total price.
To do that, I'll then create
a cart item helper constant,
which is a new object,
into which I copy item.
So I create a copy of the item
I've found in the end.
This item, I copy it, create a new cart item,
and then on this cart item,
which is that copied old item,
I will set the quantity
that I have for this product,
equal to new quantity,
because we get to that new quantity as
a fixed number, as a input.
I also of course,
need to update the total price,
and that in the end should to be
that new quantity, which I'm getting,
times the product price.
Because the product price hasn't changed here,
we'll handle the scenario that it might change
whilst we're working in the cart later.
So here we assume it hasn't changed.
And therefore we just multiply
the product price with the new quantity.
And then we replace the old cart item with that
new item.
We also need to update the total quantity of the cart,
and that of course depends on the new quantity.
We basically have to increase or decrease
the total cart quantity,
based on that new quantity and the difference to
the previous quantity.
So therefore, I'll calculate that,
the quantity change,
by calculating new quantity,
minus item.quantity,
item.quantity is the old quantity.
So I get the difference between
the new and the old quantity here.
It will be a positive number
if the new quantity is higher,
and a negative number otherwise.
And then here,
the total quantity of the cart,
is basically this total quantity,
total quantity,
plus the quantity change.
That could be a negative number,
in which case it's minus quantity change automatically.
Otherwise, we add that new quantity.
Now for the price, it, of course,
is this old total price
plus quantity change,
times product price.
That is the change in price
that we want to add to the old cart price.
It's not new quantity, times product price,
because I don't want to get
the entire bulk price of the entire item,
but just of the change,
because we add it to the old total price of the cart.
So this could be one way of updating the cart item.
However, this always assumes
that new quantity will be a positive number.
And I had this check here earlier,
which now is only executed once
we already updated everything.
And that's of course too late.
Instead, what I want to do,
is I'll cut that if check,
and then here,
if we found a matching item,
then of course, this way of updating
only applies if new quantity is positive.
So therefore, then we can add
a never nested if check here,
or combine this into one bigger If check,
and compare.
If we have a match,
and new quantity is greater than zero,
then I want to execute this logic,
and then return.
Else if,
we have this condition that doesn't change,
but then, new quantity is actually smaller
or equal to zero,
then of course, we want to execute a different logic.
Then, I want to remove that specific cart item entirely.
So, in this case,
what I want to do is,
I want to reach out to this items,
and call the built in splice method,
which exists on a raise in JavaScript,
which allows us to remove items
from an array,
by specifying the index of
the item that should be removed.
In this case, I, which comes from this loop,
and then the number of items
that should be removed, starting at the debt index.
And here, I want to remove exactly
one item, the one item for which a
quantity equal or smaller than 0 was entered.
This should do the trick here.
Of course, we then also have to update
the total quantity and total price.
And to do that, we need to find out
what the quantity and total price
of that cart item that we removed was.
So for that, we need this item
to which we got access here,
and the total cart quantity is then
the total cart quantity minus item,
so that cart item, which we removed,
it still exists in this variable,
so we can still access it,
it's just not part of items anymore,
but we can access this variable,
and get the quantity here.
And it's this quantity of this item,
which we want to remove from the cart quantity.
And for total price, it's equal
to minus equal to reduce the total price
by a value, and the value by which I want
to reduce the total price is item.totalPrice,
so the total price for this single cart item.
That should be the correct logic.
And now we can wire it up to the cart controller.
There, we can add another function,
the update cart item function, for example,
which of course gets a request
and a response as always,
and which we want to export here,
to make it available outside
of this file.
And in here, I now need to
call this a
function on my cart.
So just as before I get my cart,
by accessing res locals cart,
that's what I also did for adding a item to the cart.
And then on this cart,
which I got from Res locals,
I can call update item
because that is the name I chose
here in my cart model.
I named this update item.
So therefore, that is the function,
the method I wanna call in the controller,
and to update item,
like this,
I want to pass the product ID,
that's what we expect here,
and the new quantity.
And I simply expect to get both values from the request.
It will be a request that has a request body
because it won't be a get or delete request,
it will be a post, or a put, or a patch request,
we'll decide on this later.
But it will have a body,
because post, patch, and put, all have bodies,
and therefore I can access request body,
product ID, for the product ID,
and assume that I get the new quantity
on request body, quantity, let's say.
And then I update the cart item.
And after I updated it, just as before,
I want to save it back into my session,
with req session cart equals cart.
Now, this update cart item controller action,
should be invoked by requests that are sent as HX requests
from insight browser site, JavaScript.
Therefore I'll send back a json response,
with res json.
And then, as always, we can provide a message,
if we want to,
but more importantly,
I want to send back the updated cart data.
Therefore I'll add a updated cart data property here,
and that is a nested object,
where I'll set the new total
quantity,
equal to cart.total quantity,
and the new total price is
equal to cart.total price.
And I also want to send back
the new price for the product that was updated.
So the updated item price is then what?
Well, we could look into the cart items
and search for the item with that product ID,
but since we updated the item here,
with update item,
it would be more convenient if update item
could simply return some metadata
about the update,
instead of returning nothing.
Instead of returning nothing,
we could return an object, where we have
the updated item price,
which is this cart item total price here.
That's the new item price,
which we calculated,
and we could always return more data,
but that's the main data I'm interested here.
So I want to return it here,
and also return it in the else if case.
There, it's just not cart item.total price,
but instead let's say 0,
because of course here,
we removed the entire cart item.
But now by returning this object here,
in update item,
back in cart controller, we can
accept it.
Updated item data could be the name
of the constant that stores the return data.
And we could use that constant that returned data,
to use it here for sending back that data,
and accessing the updated
item price on the updated item data.
Updated item price, because that's
the property name I chose here in cart model
for this property in this object,
which I'm returning here.
So this updated item price,
is what I access here.
And that is what I return
as part of the json response.
That could be the cart controller.
Now we need to wire it up to our route.
So for this in cart routes,
we can register a new route.
And now it's up to you,
whether that should be a post, a put, or a patch route.
Now, typically post makes sense,
if you are about to add and store new data.
Here we are updating existing data.
In such cases, you typically use put,
if you replace the existing data, or patch,
if you update parts of the existing data.
And I think it's fair to say that here
we're updating parts of the existing data.
We're updating the cart items,
but only the quantity of of one single item.
So the path here could be slash items.
Again, it will be slash cart slash items
in the end because of our setting
in the app JS file.
And I want to point at cart controller,
update cart item.
And then this request,
which we send as a patch request
to this path needs to have this data,
which we extract in our controller action,
the product ID and the quantity,
and also the CSRF token because it's not a get request,
and therefore we need to add the CSRF token,
because of our CSRF middleware.
Still, that's the first step.
In the next step, we will now write
the front end code for listening to clicks
on the update button,
and for then sending the appropriate
request.