1
00:00:02,090 --> 00:00:04,440
Now, to show to the details about a single product

2
00:00:04,440 --> 00:00:07,470
when we click view details, we have to add a new view

3
00:00:07,470 --> 00:00:10,450
and then a new route that loads that view.

4
00:00:10,450 --> 00:00:13,360
Now, let's start with the view in the views folder

5
00:00:13,360 --> 00:00:15,260
in the customer products folder,

6
00:00:15,260 --> 00:00:20,260
I'll add the product-details.ejs file, which is responsible

7
00:00:20,480 --> 00:00:23,070
for showing the details about a product.

8
00:00:23,070 --> 00:00:27,010
And here, I'll just copy the structure from all products

9
00:00:27,010 --> 00:00:29,810
and paste it in here, but I'll get rid

10
00:00:29,810 --> 00:00:31,620
of the unordered list, of course,

11
00:00:31,620 --> 00:00:34,963
instead, we're going to add different mark up here.

12
00:00:35,810 --> 00:00:40,810
I'll keep my head include and the products.css file for now,

13
00:00:41,380 --> 00:00:46,360
but here in the body, I now simply want

14
00:00:46,360 --> 00:00:51,300
to have a header in the main section.

15
00:00:51,300 --> 00:00:53,520
So not just a main header at the very top

16
00:00:53,520 --> 00:00:56,760
with the navigation, but also an introductory header

17
00:00:56,760 --> 00:01:00,167
in the main section where I actually wanna have

18
00:01:00,167 --> 00:01:03,610
the image of that product,

19
00:01:03,610 --> 00:01:07,470
and then, side by side to that image so to say,

20
00:01:07,470 --> 00:01:12,470
a little div for grouping and styling reasons,

21
00:01:12,650 --> 00:01:14,820
with an ideal product info,

22
00:01:14,820 --> 00:01:18,260
which I will use in my CSS styles later.

23
00:01:18,260 --> 00:01:22,260
And in that div, I want to have h1 tag

24
00:01:22,260 --> 00:01:24,403
with the actual product name.

25
00:01:25,320 --> 00:01:28,563
We'll replace it with a real ejs code in a second.

26
00:01:29,520 --> 00:01:33,140
Below that the product price, let's say in a paragraph

27
00:01:34,190 --> 00:01:37,120
and below that, I also wanna have a button

28
00:01:37,120 --> 00:01:39,873
which allows us to add this product to a cart.

29
00:01:40,990 --> 00:01:43,800
And then after this introductory header,

30
00:01:43,800 --> 00:01:46,700
I want to have a paragraph here,

31
00:01:46,700 --> 00:01:50,400
which outputs the product description,

32
00:01:50,400 --> 00:01:52,583
which we also store in the database.

33
00:01:54,130 --> 00:01:57,020
That's the general markup that I wanna have here,

34
00:01:57,020 --> 00:01:58,380
but it will only look good

35
00:01:58,380 --> 00:02:01,030
if we have the proper styling for it.

36
00:02:01,030 --> 00:02:04,130
I will actually also add another id domain here,

37
00:02:04,130 --> 00:02:06,310
and that's the product details id,

38
00:02:06,310 --> 00:02:09,030
which I also want to use in the styles

39
00:02:09,030 --> 00:02:12,240
so that I can specifically style this main area

40
00:02:12,240 --> 00:02:15,560
and the header in there for the product details differently

41
00:02:15,560 --> 00:02:17,393
than I have it on the other pages.

42
00:02:18,850 --> 00:02:23,350
Now, let's go to products.css and add the styling.

43
00:02:23,350 --> 00:02:27,470
To save some time here, I will provide the finished styles

44
00:02:27,470 --> 00:02:30,250
to you, attached to this lecture,

45
00:02:30,250 --> 00:02:32,560
so that you can download them and paste them

46
00:02:32,560 --> 00:02:35,000
into your products.css file. Of course,

47
00:02:35,000 --> 00:02:37,080
we will then walk through them together

48
00:02:37,080 --> 00:02:40,303
so that you understand why I prepared these styles.

49
00:02:41,400 --> 00:02:46,240
So, I did not paste those styles into my products.css file,

50
00:02:46,240 --> 00:02:51,240
again, you find them attached, and I added these rules here.

51
00:02:52,390 --> 00:02:55,710
So not too much code in all of them, not too fancy.

52
00:02:55,710 --> 00:02:59,120
In the end, what I have in there are a little bit of margin

53
00:02:59,120 --> 00:03:03,040
and padding for the header, which is at the top of the page,

54
00:03:03,040 --> 00:03:05,250
a background color for the header,

55
00:03:05,250 --> 00:03:08,810
and I have this gap because on a desktop

56
00:03:08,810 --> 00:03:11,440
on a bigger screen size, I'm setting the display

57
00:03:11,440 --> 00:03:13,790
to flex for the header so that items

58
00:03:13,790 --> 00:03:15,840
are next to each other on bigger screens

59
00:03:15,840 --> 00:03:19,640
and are below each other on smaller screens.

60
00:03:19,640 --> 00:03:22,290
Therefore, of course, I could have also added gap here

61
00:03:22,290 --> 00:03:26,300
in these desktop styles. I did add it here though;

62
00:03:26,300 --> 00:03:27,683
either approach works.

63
00:03:29,300 --> 00:03:31,550
Now, that's the header. For the image in the header,

64
00:03:31,550 --> 00:03:33,570
which should show the product image.,

65
00:03:33,570 --> 00:03:37,490
I'm making sure that it takes the entire width of the header

66
00:03:37,490 --> 00:03:41,130
by default on small screens, on bigger screens,

67
00:03:41,130 --> 00:03:44,420
I restrict the width and also the height then,

68
00:03:44,420 --> 00:03:47,170
and on big screens, since we're here already,

69
00:03:47,170 --> 00:03:49,990
I didn't also use the transform property,

70
00:03:49,990 --> 00:03:52,130
which is a default CSS property

71
00:03:52,130 --> 00:03:54,450
to rotate the image a little bit,

72
00:03:54,450 --> 00:03:56,670
and I rotate around the set axis here,

73
00:03:56,670 --> 00:03:59,362
which is basically a two-dimensional rotation here

74
00:03:59,362 --> 00:04:02,900
on this page. So that it's a little bit rotated,

75
00:04:02,900 --> 00:04:06,710
just a little visual sugar that I'm adding here.

76
00:04:06,710 --> 00:04:10,100
Then I have some margin in all directions here

77
00:04:10,100 --> 00:04:12,420
on bigger screens. And if you go back

78
00:04:12,420 --> 00:04:14,440
to the smaller screens for the image,

79
00:04:14,440 --> 00:04:17,950
there, as I said, the width is 100%,

80
00:04:17,950 --> 00:04:21,880
height should be 6rem, so that was 6rem here,

81
00:04:21,880 --> 00:04:26,290
not just 6 and object fit is cover.

82
00:04:26,290 --> 00:04:28,910
That of course will then also apply to bigger screens

83
00:04:28,910 --> 00:04:31,570
since I'm not overriding it there in the media query

84
00:04:31,570 --> 00:04:34,120
so that the image is not distorted.

85
00:04:34,120 --> 00:04:38,280
I give it rounded coordinators and then a little a border,

86
00:04:38,280 --> 00:04:41,630
so a little border around the image, and that's it.

87
00:04:41,630 --> 00:04:44,860
Then for the product info, which is this div

88
00:04:44,860 --> 00:04:48,130
with the names on, there, I make sure that all

89
00:04:48,130 --> 00:04:50,460
the text in there is centered,

90
00:04:50,460 --> 00:04:52,810
and for the product description,

91
00:04:52,810 --> 00:04:55,070
which I want to add out half down here

92
00:04:55,070 --> 00:04:58,000
and therefore actually we should add an ID

93
00:04:58,000 --> 00:05:02,590
of product-description to this paragraph.

94
00:05:02,590 --> 00:05:05,840
For this description, I am also adding

95
00:05:05,840 --> 00:05:07,700
a background color and some padding

96
00:05:07,700 --> 00:05:10,833
and very important. I'm adding white space pre wrap.

97
00:05:11,768 --> 00:05:14,390
That is a property I also introduced early on

98
00:05:14,390 --> 00:05:17,420
in the course already, which ensures that line breaks

99
00:05:17,420 --> 00:05:19,710
and white space are not omitted

100
00:05:19,710 --> 00:05:23,170
and ignored as they normally are when HTML code

101
00:05:23,170 --> 00:05:26,299
and text in your HTML documents are being parsed,

102
00:05:26,299 --> 00:05:28,520
but then instead they persist,

103
00:05:28,520 --> 00:05:31,860
and they are rendered and output on the screen.

104
00:05:31,860 --> 00:05:33,580
So that if you had line breaks

105
00:05:33,580 --> 00:05:37,160
in your product description when you created the product,

106
00:05:37,160 --> 00:05:40,690
those line breaks are persisted and shown on the screen.

107
00:05:40,690 --> 00:05:42,423
That's why I have this setting.

108
00:05:43,787 --> 00:05:47,460
And that is basically it. On bigger screens in product info,

109
00:05:47,460 --> 00:05:49,280
I aligned the text to the left,

110
00:05:49,280 --> 00:05:52,313
on smaller screens it is aligned in the center.

111
00:05:53,610 --> 00:05:57,040
So that's that. Now we have the styles,

112
00:05:57,040 --> 00:05:59,100
we have the template, We now need

113
00:05:59,100 --> 00:06:01,100
to route and the controller action

114
00:06:01,100 --> 00:06:04,240
to serve that template, when we request

115
00:06:04,240 --> 00:06:06,723
the details of for a single product.

116
00:06:08,750 --> 00:06:12,530
And for this, of course, let's go to product routes

117
00:06:12,530 --> 00:06:15,420
and add a new route here; a get route

118
00:06:15,420 --> 00:06:18,380
since you wanna get that page, for products

119
00:06:18,380 --> 00:06:21,540
slash and then the ID placeholder,

120
00:06:21,540 --> 00:06:23,890
because of course we want to use the same route for

121
00:06:23,890 --> 00:06:26,053
different IDs for different products.

122
00:06:27,640 --> 00:06:29,520
Now we need a controller action

123
00:06:29,520 --> 00:06:31,740
and hence the product controller.

124
00:06:31,740 --> 00:06:36,140
We can add a new function an async function actually,

125
00:06:36,140 --> 00:06:39,810
since we will use async await in there where I get a

126
00:06:39,810 --> 00:06:43,820
product, we can also named us get product details,

127
00:06:43,820 --> 00:06:47,400
name is up to you, where we have req response and next

128
00:06:47,400 --> 00:06:50,130
as always for these middleware functions

129
00:06:50,130 --> 00:06:53,580
and route handler functions are just middleware functions

130
00:06:53,580 --> 00:06:54,980
in the end.

131
00:06:54,980 --> 00:06:57,560
And here we can get a product by using

132
00:06:57,560 --> 00:06:59,410
our product model again.

133
00:06:59,410 --> 00:07:03,420
And then the find by ID method that we got here.

134
00:07:03,420 --> 00:07:08,420
And then here I can get my ID by accessing req.params.id,

135
00:07:09,750 --> 00:07:12,420
because that's my dynamic route parameter,

136
00:07:12,420 --> 00:07:16,670
and we can await this and this might fail.

137
00:07:16,670 --> 00:07:20,890
So we should actually wrap this with try catch here,

138
00:07:20,890 --> 00:07:23,870
as we did it many times before in the course

139
00:07:23,870 --> 00:07:27,973
and call next error, if we do have an error here,

140
00:07:29,300 --> 00:07:31,600
if we don't have an error, if we got a product.

141
00:07:31,600 --> 00:07:34,840
So if this first-line and tried did not crash,

142
00:07:34,840 --> 00:07:37,270
then on the upper hand, I wanna render

143
00:07:37,270 --> 00:07:40,580
this product details template we worked on before,

144
00:07:40,580 --> 00:07:43,970
which can be found in a customer folder and they are

145
00:07:43,970 --> 00:07:48,393
in the products folder and there it's product-details.

146
00:07:49,441 --> 00:07:53,700
And to this template, I now want to pass the product data.

147
00:07:53,700 --> 00:07:57,270
So now here I pass a second parameter value tutors render

148
00:07:57,270 --> 00:07:58,550
method.

149
00:07:58,550 --> 00:08:00,950
And here I provide my product under

150
00:08:00,950 --> 00:08:03,333
a product key to that template.

151
00:08:05,790 --> 00:08:08,960
Now I want to make that controller action available outside

152
00:08:08,960 --> 00:08:13,563
of this file. So I added like this to my exported object,

153
00:08:14,860 --> 00:08:17,850
and back in products routes, we can now connect it,

154
00:08:17,850 --> 00:08:20,070
connect this route to products,

155
00:08:20,070 --> 00:08:22,673
controller, get product details.

156
00:08:25,640 --> 00:08:29,060
Now in the product details EJS file.

157
00:08:29,060 --> 00:08:32,230
I can now output the actual product data

158
00:08:32,230 --> 00:08:36,193
by replacing name here with product.title,

159
00:08:38,120 --> 00:08:43,120
the price with maybe dollar sign and then output dynamically

160
00:08:43,330 --> 00:08:47,640
with EJS product.price. So these are the fields we have

161
00:08:47,640 --> 00:08:50,360
for every product in the database.

162
00:08:50,360 --> 00:08:51,860
We'll take care about the button later,

163
00:08:51,860 --> 00:08:53,460
we'll ignore it for now.

164
00:08:53,460 --> 00:08:58,460
Here in the description. I'll output product.description.

165
00:08:58,490 --> 00:09:02,510
And even though this data, of course is all generated

166
00:09:02,510 --> 00:09:04,850
by the administrator and therefore by us.

167
00:09:04,850 --> 00:09:07,080
And it's probably not malicious.

168
00:09:07,080 --> 00:09:10,000
Please note that I'm escaping all that data

169
00:09:10,000 --> 00:09:14,090
by using this equal sign EJS tag here.

170
00:09:14,090 --> 00:09:16,830
You learned about that on the security core section,

171
00:09:16,830 --> 00:09:20,310
you wanna escape all the user generated content,

172
00:09:20,310 --> 00:09:22,890
even if the user is you and it's less likely

173
00:09:22,890 --> 00:09:26,170
to be dangerous, still, you never trust your users.

174
00:09:26,170 --> 00:09:28,720
You wanna escape their input. If you're outputting it

175
00:09:28,720 --> 00:09:31,310
on the page to prevent, for example,

176
00:09:31,310 --> 00:09:33,423
against cross site scripting attacks.

177
00:09:34,950 --> 00:09:38,200
But that's just a side note. We, of course, also here,

178
00:09:38,200 --> 00:09:42,550
want to output product.imageURL.

179
00:09:42,550 --> 00:09:46,860
Please note that image URL is a field we can access because

180
00:09:46,860 --> 00:09:50,860
in our product model, which we use for fetching the data,

181
00:09:50,860 --> 00:09:55,093
in find by ID we return a instance of that class

182
00:09:55,093 --> 00:09:58,965
of that product class. And every instance has

183
00:09:58,965 --> 00:10:02,750
this update image data method,

184
00:10:02,750 --> 00:10:05,380
which is being called automatically when

185
00:10:05,380 --> 00:10:08,320
an object is created based on that class.

186
00:10:08,320 --> 00:10:13,320
And in that method, I am setting an image, URL property

187
00:10:13,560 --> 00:10:16,993
to that URL for which the image can be requested.

188
00:10:19,190 --> 00:10:21,640
So therefore back in product details,

189
00:10:21,640 --> 00:10:25,070
I can access product.imageURL here

190
00:10:25,070 --> 00:10:29,273
and here as a all text I'll use product.title.

191
00:10:32,500 --> 00:10:36,410
With all of that, if we now reload and click view details,

192
00:10:36,410 --> 00:10:38,440
we should be taken to the details page,

193
00:10:38,440 --> 00:10:42,020
which looks like that cart button has not the look I want,

194
00:10:42,020 --> 00:10:45,350
I'll change this in a second, but the rest looks okay.

195
00:10:45,350 --> 00:10:47,770
And if we view this on a smaller screen,

196
00:10:47,770 --> 00:10:49,303
this also looks quite okay.

197
00:10:50,790 --> 00:10:52,650
So that's my product detail page.

198
00:10:52,650 --> 00:10:54,060
And of course it looks more fancy.

199
00:10:54,060 --> 00:10:56,630
If you add more text here to your product,

200
00:10:56,630 --> 00:10:59,130
but it is a good start. It allows us to interact

201
00:10:59,130 --> 00:11:01,960
with that product. Now, of course,

202
00:11:01,960 --> 00:11:05,460
I wanna make sure that this add to cart button looks

203
00:11:05,460 --> 00:11:07,900
properly. And most importantly,

204
00:11:07,900 --> 00:11:11,943
that it works that we can start adding products to the cart.

