Now, to show to the details about a single product
when we click view details, we have to add a new view
and then a new route that loads that view.
Now, let's start with the view in the views folder
in the customer products folder,
I'll add the product-details.ejs file, which is responsible
for showing the details about a product.
And here, I'll just copy the structure from all products
and paste it in here, but I'll get rid
of the unordered list, of course,
instead, we're going to add different mark up here.
I'll keep my head include and the products.css file for now,
but here in the body, I now simply want
to have a header in the main section.
So not just a main header at the very top
with the navigation, but also an introductory header
in the main section where I actually wanna have
the image of that product,
and then, side by side to that image so to say,
a little div for grouping and styling reasons,
with an ideal product info,
which I will use in my CSS styles later.
And in that div, I want to have h1 tag
with the actual product name.
We'll replace it with a real ejs code in a second.
Below that the product price, let's say in a paragraph
and below that, I also wanna have a button
which allows us to add this product to a cart.
And then after this introductory header,
I want to have a paragraph here,
which outputs the product description,
which we also store in the database.
That's the general markup that I wanna have here,
but it will only look good
if we have the proper styling for it.
I will actually also add another id domain here,
and that's the product details id,
which I also want to use in the styles
so that I can specifically style this main area
and the header in there for the product details differently
than I have it on the other pages.
Now, let's go to products.css and add the styling.
To save some time here, I will provide the finished styles
to you, attached to this lecture,
so that you can download them and paste them
into your products.css file. Of course,
we will then walk through them together
so that you understand why I prepared these styles.
So, I did not paste those styles into my products.css file,
again, you find them attached, and I added these rules here.
So not too much code in all of them, not too fancy.
In the end, what I have in there are a little bit of margin
and padding for the header, which is at the top of the page,
a background color for the header,
and I have this gap because on a desktop
on a bigger screen size, I'm setting the display
to flex for the header so that items
are next to each other on bigger screens
and are below each other on smaller screens.
Therefore, of course, I could have also added gap here
in these desktop styles. I did add it here though;
either approach works.
Now, that's the header. For the image in the header,
which should show the product image.,
I'm making sure that it takes the entire width of the header
by default on small screens, on bigger screens,
I restrict the width and also the height then,
and on big screens, since we're here already,
I didn't also use the transform property,
which is a default CSS property
to rotate the image a little bit,
and I rotate around the set axis here,
which is basically a two-dimensional rotation here
on this page. So that it's a little bit rotated,
just a little visual sugar that I'm adding here.
Then I have some margin in all directions here
on bigger screens. And if you go back
to the smaller screens for the image,
there, as I said, the width is 100%,
height should be 6rem, so that was 6rem here,
not just 6 and object fit is cover.
That of course will then also apply to bigger screens
since I'm not overriding it there in the media query
so that the image is not distorted.
I give it rounded coordinators and then a little a border,
so a little border around the image, and that's it.
Then for the product info, which is this div
with the names on, there, I make sure that all
the text in there is centered,
and for the product description,
which I want to add out half down here
and therefore actually we should add an ID
of product-description to this paragraph.
For this description, I am also adding
a background color and some padding
and very important. I'm adding white space pre wrap.
That is a property I also introduced early on
in the course already, which ensures that line breaks
and white space are not omitted
and ignored as they normally are when HTML code
and text in your HTML documents are being parsed,
but then instead they persist,
and they are rendered and output on the screen.
So that if you had line breaks
in your product description when you created the product,
those line breaks are persisted and shown on the screen.
That's why I have this setting.
And that is basically it. On bigger screens in product info,
I aligned the text to the left,
on smaller screens it is aligned in the center.
So that's that. Now we have the styles,
we have the template, We now need
to route and the controller action
to serve that template, when we request
the details of for a single product.
And for this, of course, let's go to product routes
and add a new route here; a get route
since you wanna get that page, for products
slash and then the ID placeholder,
because of course we want to use the same route for
different IDs for different products.
Now we need a controller action
and hence the product controller.
We can add a new function an async function actually,
since we will use async await in there where I get a
product, we can also named us get product details,
name is up to you, where we have req response and next
as always for these middleware functions
and route handler functions are just middleware functions
in the end.
And here we can get a product by using
our product model again.
And then the find by ID method that we got here.
And then here I can get my ID by accessing req.params.id,
because that's my dynamic route parameter,
and we can await this and this might fail.
So we should actually wrap this with try catch here,
as we did it many times before in the course
and call next error, if we do have an error here,
if we don't have an error, if we got a product.
So if this first-line and tried did not crash,
then on the upper hand, I wanna render
this product details template we worked on before,
which can be found in a customer folder and they are
in the products folder and there it's product-details.
And to this template, I now want to pass the product data.
So now here I pass a second parameter value tutors render
method.
And here I provide my product under
a product key to that template.
Now I want to make that controller action available outside
of this file. So I added like this to my exported object,
and back in products routes, we can now connect it,
connect this route to products,
controller, get product details.
Now in the product details EJS file.
I can now output the actual product data
by replacing name here with product.title,
the price with maybe dollar sign and then output dynamically
with EJS product.price. So these are the fields we have
for every product in the database.
We'll take care about the button later,
we'll ignore it for now.
Here in the description. I'll output product.description.
And even though this data, of course is all generated
by the administrator and therefore by us.
And it's probably not malicious.
Please note that I'm escaping all that data
by using this equal sign EJS tag here.
You learned about that on the security core section,
you wanna escape all the user generated content,
even if the user is you and it's less likely
to be dangerous, still, you never trust your users.
You wanna escape their input. If you're outputting it
on the page to prevent, for example,
against cross site scripting attacks.
But that's just a side note. We, of course, also here,
want to output product.imageURL.
Please note that image URL is a field we can access because
in our product model, which we use for fetching the data,
in find by ID we return a instance of that class
of that product class. And every instance has
this update image data method,
which is being called automatically when
an object is created based on that class.
And in that method, I am setting an image, URL property
to that URL for which the image can be requested.
So therefore back in product details,
I can access product.imageURL here
and here as a all text I'll use product.title.
With all of that, if we now reload and click view details,
we should be taken to the details page,
which looks like that cart button has not the look I want,
I'll change this in a second, but the rest looks okay.
And if we view this on a smaller screen,
this also looks quite okay.
So that's my product detail page.
And of course it looks more fancy.
If you add more text here to your product,
but it is a good start. It allows us to interact
with that product. Now, of course,
I wanna make sure that this add to cart button looks
properly. And most importantly,
that it works that we can start adding products to the cart.