So the next step is to make this orders page work.
And actually for this,
we'll have to repeat a bunch of logic,
which be repeated over and over again in this section.
We have to work on the HTML code in there,
add some styling for the order items, and then write some
code for fetching all the orders.
That's not too fancy. And therefore, in order to
not bore you,
I finished this online shop since the only missing parts,
really, were the orders-list and the administration of
orders, which I'll show you in a second.
And you'll find a bunch of files attached that contain the
code that I did change.
And of course I will walk through all those changes together
with you,
step-by-step, in great detail so that you fully understand
what I changed and why I did it. Now for that,
it probably makes sense to start in the order model. In
there, I edit a couple of methods for finding orders:
the FindAll and FindAllForUser methods.
I also added a FindById method,
which will become important for managing orders in the
administration interface. But I'll come back to that. Now,
FindAll and FindAllForUser, as you can see, are really
not that special at all. In FindAll,
I really just get all my orders.
I, then, called transformOrderDocuments,
which is just a helper method here,
which maps all my order documents with help of
transformOrderDocument,
which is another helper method into order objects based on
this blueprint. Nothing fancy there. In the end,
I just instantiate a bunch of order objects and I transform
all the order documents from the collection into such order
objects in the end.
That's what I do here and then FindAll for a user
I do almost the same. But there, of course,
I also have this little filter here where I dive into the
user data field, which I have in my order documents,
and then compare the ID of that user to the user ID,
which I get here as a parameter value and which I then
convert into a mongodb.ObjectID(object).
That's all I do.
So, I find the orders that belong to a given user
by the user ID.
I also have this extra sort method called here on this
overall query, and that does what the name implies.
It sorts the documents that are found and I'm sorting by ID
in descending order.
Thankfully,
the ID's created by mongodb do contain a timestamp,
implicitly, and therefore,
we can use IDs to sort the orders such that the latest
orders are on top.
So, I write at the start of the list by simply
sorting by the ID
in descending order so that the latest ID's come first.
We could also sort like this for finding all the orders,
but I use FindAll in the administration interface and we
can actually also sort like this
when we find all orders. Here, we could also add this after
Find before toArray,
and then we would sort these orders as well.
So actually that's another tiny change I'll make here.
So in the attached order.model.js file,
you will find all these changes and you can simply replace
your order.model.js file with mine, of course.
Now, besides that, I have the findById method,
which does what the name implies.
It finds an order by its ID.
Nothing too fancy.
And then I also transformed that foundOrder document into
an instance of this order clause.
And last but not least,
I also added some logic to the save method so that we now
cannot just create new orders,
but that I also can update orders.
If we already have an ID for this given order on which we're
working, then I know that I want to update it.
Then I convert the ID to a mongodb.ObjectID,
and then with updateOne, finding the proper document by ID,
I update that order.
And updating simply means that I update the status because
in this website, that's the only kind of update
I want to allow to orders
that the admin is able to change
the order status.
And I will show you the front end for this in a second.
That's what I changed in the order model.
I added the utility methods,
and these find methods and the updating functionality.
I did, of course, add these find methods
so that we can get an
output, the orders.
I do that in the orders controller.
Here in orders.controller, I added this getOrders function,
or I populated it with more life to be precise.
And I try finding all the orders for a given user because
this function will be executed for regular users who should
only be able to see their own orders,
not orders of other users.
And, for finding the orders for a given user,
I use a res.locals.uid,
which I get from my session in the end with help of the
check-off middleware there,
I get the user ID from the session and store data in
res.locals.uid thereafter.
And I use that in the orders.controller to, then,
find all the orders for that user by that ID.
Then, I rendered this all-orders template as we did before.
And to that template, I passed the orders I found.
I also added error handling.
And that's all I added in here in the orders.controller.
Other than that, nothing changed here.
In the all-orders.ejs file,
I added more code.
To be precise, I included this code snippet
here, where I output an order-list.
And this code snippet is stored in the shared folder and
there in the includes folder because I also will use it in
the administration area later.
We'll see that in a second.
Now in this order-list.ejs file-
And again,
you find all these new and updated files attached-
In this order-list.ejs file,
I have a simple loop as we added multiple times.
I use an order-list because I do sort to the orders.
So using an order-list makes sense,
because you order clearly matters to me.
And then I loop through all the orders that I got and then I
include another snippet for every order-item.
And that is the order-items snippet here,
where I have an article.
And in that article,
I will have a bunch of markup outputting,
basically some information about the total price of that
order by using the totalPrice right from inside the order
for the product data that's stored in the order.
And keep in mind, the product data that's stored
in the order is in the end,
the cart for which the order was placed.
I also called toFixed(2)
to make sure we always display two decimal places.
Then I have a regular dash output as plain text here.
And then after that, this formatedDate,
which you saw in the order clause constructor function,
and then after this title I have this batch,
which displays the current order status in all upper case
characters, thanks to this transformation function here,
which I call.
Here, I also reuse this batch clause,
which we defined before for this batch here in our
navigation for this cart button here.
Then, I output some order details and here I also have some
special output for administrators.
For administrators,
I also show an address element here,
or I output an address element with more information about
the user who placed the order,
because I think that makes sense.
If you view all the orders from all the users in the
administration panel,
you need all these user details to then ship the order to
your users, if this would be a real online shop.
Therefore, here I output the username.
I ensure that the user can be contacted by using user email
address here for this link.
And I then output the street address,
the postal code, and the city of the user.
And all that data
is coming from the order that we created
and that's stored in the database.
Now, this is only shown on the administration panel.
If you are viewing your orders as a regular user, you, of
course, don't need that extra data.
You know who you are and therefore, then,
I just show details about the order to be precise about the
items that were ordered.
For that,
I accessed the items in that cart, which is in the end,
which is part of that order and output the title of the
product, the total price fixed to two decimal places,
and then also the details on how that total price was
calculated by using the individual product price.
So, really looking into an individual product
and seeing what the price of that would have been
and showing you also the quantity,
so the number of these products you had in your cart,
which then leads to this total price in the end.
Now, if you are an administrator,
I then also show you more options
because then you should be
able to update this order status.
You should not be able to update it as a regular user.
So as an administrator, you get this extra form,
which shows a select drop-down in the end,
where you can switch between these statuses.
You can switch between pending, fulfilled and canceled and
you can then click the update button to, in the end,
submit this form.
And I always include the CSRF token and a hidden input field
that contains the ID of that order,
which should be updated so that this is then also a part of
the form submission.
Though the form here actually
won't be submitted automatically by the browser--
Instead, I wrote a Java script file,
a browser side Java script file,
the order management file here,
where I actually stop that form submission with
preventDefault and then send an Ajax request manually to the
backend so that I can send a patch request.
And so that we again have another example for Ajax requests,
but I'll come back to this script in a second.
For the moment, that's it's for the order item
and with all of that,
with all these capabilities,
you can now visit the orders page as a regular user and view
your orders here.
That's what you see here.
And here,
you see all the details I showed you in code a couple of
seconds ago.