1
00:00:00,000 --> 00:00:02,000
Now that we worked on the starting page

2
00:00:02,000 --> 00:00:06,000
and the community page and improved the header,

3
00:00:06,000 --> 00:00:09,000
it's finally time to work on that meals page

4
00:00:09,000 --> 00:00:11,000
and it's time to output some meals there

5
00:00:11,000 --> 00:00:13,000
before we then thereafter,

6
00:00:13,000 --> 00:00:16,000
will make sure that users can also share meals.

7
00:00:17,000 --> 00:00:20,000
Now for that, it's this page.js file

8
00:00:20,000 --> 00:00:23,000
in the meals folder on which we'll work.

9
00:00:23,000 --> 00:00:27,000
And there, I wanna output a bunch of meals,

10
00:00:27,000 --> 00:00:28,000
a bunch of meals

11
00:00:28,000 --> 00:00:31,000
which we'll soon store in a database.

12
00:00:31,000 --> 00:00:33,000
But before we'll do that,

13
00:00:33,000 --> 00:00:37,000
let's set up the base markup of this page,

14
00:00:37,000 --> 00:00:40,000
the base structure of this page, you could say.

15
00:00:41,000 --> 00:00:45,000
And here I again wanna have a header section,

16
00:00:45,000 --> 00:00:48,000
and then below that, the main section of this page.

17
00:00:49,000 --> 00:00:52,000
I also again prepared some styles

18
00:00:52,000 --> 00:00:53,000
and therefore, attached,

19
00:00:53,000 --> 00:00:57,000
you'll find another page.module.css file,

20
00:00:57,000 --> 00:01:01,000
the page.module.css file for this meals page.

21
00:01:03,000 --> 00:01:08,000
And we can and should then import this page.module.css file,

22
00:01:08,000 --> 00:01:13,000
again using this special CSS modules import syntax

23
00:01:13,000 --> 00:01:17,000
so that we can access the CSS classes set up in that file.

24
00:01:18,000 --> 00:01:20,000
Because there, for example,

25
00:01:20,000 --> 00:01:22,000
should be a class added to this header,

26
00:01:23,000 --> 00:01:26,000
the header class like this,

27
00:01:29,000 --> 00:01:32,000
I also wanna add a class to the main section,

28
00:01:32,000 --> 00:01:36,000
and that is the main class that's added here.

29
00:01:38,000 --> 00:01:43,000
Now inside of that header, I then wanna have an h1 element

30
00:01:43,000 --> 00:01:47,000
where I say, delicious meals, created,

31
00:01:47,000 --> 00:01:51,000
and then a span, by you.

32
00:01:51,000 --> 00:01:54,000
And I'm using that span for some extra styling

33
00:01:54,000 --> 00:01:57,000
because to that span, I wanna assign a class.

34
00:01:57,000 --> 00:02:02,000
To be precise, the highlight class like this.

35
00:02:05,000 --> 00:02:08,000
Below this h1 element, we can then add a paragraph

36
00:02:08,000 --> 00:02:10,000
which simply outputs some dummy text,

37
00:02:10,000 --> 00:02:13,000
like choose your favorite recipe

38
00:02:13,000 --> 00:02:17,000
and cook it yourself.

39
00:02:17,000 --> 00:02:19,000
It is easy and fun.

40
00:02:20,000 --> 00:02:23,000
You can of course output whatever you want.

41
00:02:24,000 --> 00:02:29,000
Now below that paragraph, I wanna have yet another paragraph

42
00:02:29,000 --> 00:02:34,000
which should receive a className of cta

43
00:02:34,000 --> 00:02:37,000
for call to action, because in there,

44
00:02:37,000 --> 00:02:41,000
I then wanna have a link using the next/link component,

45
00:02:41,000 --> 00:02:42,000
which therefore, of course,

46
00:02:42,000 --> 00:02:45,000
also is imported as it always is.

47
00:02:45,000 --> 00:02:48,000
And I'm using that Link component

48
00:02:48,000 --> 00:02:52,000
to link to that share page,

49
00:02:52,000 --> 00:02:55,000
so to /meals/share,

50
00:02:55,000 --> 00:03:00,000
which will be the page that can be used by users later

51
00:03:00,000 --> 00:03:03,000
to share their own meals with the community.

52
00:03:03,000 --> 00:03:08,000
And therefore, I'll say, share your favorite recipe.

53
00:03:11,000 --> 00:03:15,000
So that's now this header area of this MealsPage.

54
00:03:15,000 --> 00:03:18,000
And we could of course put that into a separate component.

55
00:03:18,000 --> 00:03:20,000
If you wanted to, you could do that.

56
00:03:20,000 --> 00:03:22,000
You just have to make sure

57
00:03:22,000 --> 00:03:24,000
that you bring along the necessary styles.

58
00:03:24,000 --> 00:03:26,000
But here, I'll keep it all in one component.

59
00:03:28,000 --> 00:03:30,000
I will add a separate component

60
00:03:30,000 --> 00:03:32,000
for outputting the meals though,

61
00:03:33,000 --> 00:03:37,000
and therefore, for that, back in my root components folder,

62
00:03:37,000 --> 00:03:39,000
I'll add a meals subfolder

63
00:03:39,000 --> 00:03:42,000
to store any meal-related components.

64
00:03:42,000 --> 00:03:46,000
And there, I'll add a meals-grid.js file.

65
00:03:48,000 --> 00:03:51,000
Now the job of this meals-grid.js file

66
00:03:51,000 --> 00:03:56,000
will be to output a bunch of meal items in a grid.

67
00:03:56,000 --> 00:03:57,000
So therefore, of course,

68
00:03:57,000 --> 00:04:00,000
we start by exporting a component function.

69
00:04:00,000 --> 00:04:03,000
I'll name it MealsGrid.

70
00:04:03,000 --> 00:04:05,000
And I expect to get the meals

71
00:04:05,000 --> 00:04:07,000
that should be output here as a prop.

72
00:04:09,000 --> 00:04:12,000
And then I'll output an unordered list.

73
00:04:12,000 --> 00:04:16,000
And in that list, I'll map through all meals

74
00:04:16,000 --> 00:04:19,000
so that for every meal, we can output a list item.

75
00:04:21,000 --> 00:04:23,000
Now every list item here needs a key,

76
00:04:23,000 --> 00:04:25,000
and the key can be meal.id

77
00:04:25,000 --> 00:04:27,000
because every meal will have an id.

78
00:04:29,000 --> 00:04:31,000
And then inside of that list item,

79
00:04:31,000 --> 00:04:34,000
I wanna output the meal item details.

80
00:04:35,000 --> 00:04:37,000
Now before we work on that,

81
00:04:37,000 --> 00:04:42,000
I also prepared a CSS file, meals-grid.module,

82
00:04:42,000 --> 00:04:43,000
which you'll find attached,

83
00:04:44,000 --> 00:04:49,000
which you should then import into this meals-grid.js file

84
00:04:49,000 --> 00:04:53,000
just as we always did it with all those .module.css files

85
00:04:55,000 --> 00:05:00,000
so that we can add a class here to the unordered list,

86
00:05:00,000 --> 00:05:03,000
a class called meals like this.

87
00:05:05,000 --> 00:05:08,000
And now I'll add another component here,

88
00:05:08,000 --> 00:05:10,000
the meal-item.js file.

89
00:05:10,000 --> 00:05:14,000
And I prepared a meal-item.module.css file,

90
00:05:14,000 --> 00:05:16,000
which is also attached.

91
00:05:16,000 --> 00:05:21,000
And attached you'll also find my finished meal-item.js file,

92
00:05:21,000 --> 00:05:24,000
which is a relatively straightforward component

93
00:05:24,000 --> 00:05:26,000
that simply accepts a bunch of props

94
00:05:26,000 --> 00:05:29,000
and then outputs those props in a structured way.

95
00:05:30,000 --> 00:05:32,000
Now what's interesting about this component

96
00:05:32,000 --> 00:05:34,000
is, for one, that it then has a link

97
00:05:34,000 --> 00:05:38,000
that takes us to a specific meal detail page.

98
00:05:38,000 --> 00:05:42,000
And here, the path is constructed dynamically

99
00:05:42,000 --> 00:05:44,000
with a dynamically injected segment

100
00:05:44,000 --> 00:05:46,000
that will be different for every meal

101
00:05:46,000 --> 00:05:50,000
because we have that dynamic meal details page.

102
00:05:50,000 --> 00:05:54,000
Here, this page, which expects a dynamic value

103
00:05:54,000 --> 00:05:57,000
for that path segment so that we can can visit

104
00:05:57,000 --> 00:06:00,000
that details page for different meals.

105
00:06:00,000 --> 00:06:03,000
And in the end here where I'm constructing this path,

106
00:06:03,000 --> 00:06:05,000
it's this dynamic slug,

107
00:06:05,000 --> 00:06:07,000
which will be different for every meal

108
00:06:07,000 --> 00:06:11,000
that will be used as a concrete value for this placeholder.

109
00:06:13,000 --> 00:06:16,000
So that's one interesting thing in this component

110
00:06:16,000 --> 00:06:18,000
that will have this dynamic link

111
00:06:18,000 --> 00:06:21,000
that will lead us to different meal detail pages.

112
00:06:21,000 --> 00:06:25,000
The other interesting thing is this image component.

113
00:06:25,000 --> 00:06:27,000
It's this next/image component.

114
00:06:27,000 --> 00:06:29,000
And it's interesting here

115
00:06:29,000 --> 00:06:32,000
because the images I'm outputting here

116
00:06:32,000 --> 00:06:36,000
will now not be imported manually from the assets folder.

117
00:06:36,000 --> 00:06:38,000
Instead, we'll be working with meals

118
00:06:38,000 --> 00:06:40,000
that are stored in a database

119
00:06:40,000 --> 00:06:44,000
and their images are stored in the public folder.

120
00:06:45,000 --> 00:06:47,000
Now it turns out that these are the same images

121
00:06:47,000 --> 00:06:48,000
as in the assets folder,

122
00:06:48,000 --> 00:06:51,000
but that's just in coincidence here.

123
00:06:51,000 --> 00:06:54,000
Later, users will be able to upload their own images

124
00:06:54,000 --> 00:06:56,000
and share their own meals,

125
00:06:56,000 --> 00:06:58,000
and that's something we have to keep in mind

126
00:06:58,000 --> 00:07:00,000
when using this image component

127
00:07:00,000 --> 00:07:02,000
because this image component

128
00:07:02,000 --> 00:07:05,000
needs to know the underlying width and height of the image

129
00:07:05,000 --> 00:07:07,000
that's being output.

130
00:07:07,000 --> 00:07:10,000
So not the width and height you wanna have on the screen,

131
00:07:10,000 --> 00:07:11,000
but the width and height

132
00:07:11,000 --> 00:07:14,000
of the image you are trying to render.

133
00:07:14,000 --> 00:07:17,000
And it's able to detect that automatically

134
00:07:17,000 --> 00:07:19,000
when you are using the image component

135
00:07:19,000 --> 00:07:22,000
as we did it in the header on an image

136
00:07:22,000 --> 00:07:25,000
that's imported from the local filesystem

137
00:07:25,000 --> 00:07:27,000
as we're doing it here with the logo.

138
00:07:27,000 --> 00:07:28,000
In that case,

139
00:07:28,000 --> 00:07:31,000
NextJS is able to look up the width and height.

140
00:07:33,000 --> 00:07:34,000
But for those meal items,

141
00:07:34,000 --> 00:07:38,000
we'll load them dynamically from a database.

142
00:07:38,000 --> 00:07:39,000
And then in the database,

143
00:07:39,000 --> 00:07:42,000
we'll have a path pointing to some image,

144
00:07:42,000 --> 00:07:45,000
and NextJS will not be able to resolve

145
00:07:45,000 --> 00:07:47,000
the width and height of such an image,

146
00:07:47,000 --> 00:07:50,000
of such a dynamically loaded and resolved image

147
00:07:52,000 --> 00:07:54,000
simply because the information

148
00:07:54,000 --> 00:07:56,000
is not available at build time,

149
00:07:56,000 --> 00:07:59,000
as it's the case for all imported images,

150
00:07:59,000 --> 00:08:00,000
but only at runtime.

151
00:08:01,000 --> 00:08:05,000
And that's why I added this special fill prop here.

152
00:08:06,000 --> 00:08:08,000
An alternative would've been to explicitly set

153
00:08:08,000 --> 00:08:12,000
the width and height of the images that will be output here,

154
00:08:12,000 --> 00:08:15,000
but the problem is that I don't know that in advance

155
00:08:15,000 --> 00:08:17,000
because we'll also be dealing

156
00:08:17,000 --> 00:08:19,000
with images shared by the user.

157
00:08:20,000 --> 00:08:24,000
And in such scenarios, fill is an alternative.

158
00:08:24,000 --> 00:08:26,000
This then tells NextJS

159
00:08:26,000 --> 00:08:29,000
that it should simply fill the available space

160
00:08:29,000 --> 00:08:33,000
with that image as defined by its parent components.

161
00:08:33,000 --> 00:08:36,000
And I set up appropriate CSS styles

162
00:08:36,000 --> 00:08:39,000
that make sure that this will look good.

163
00:08:40,000 --> 00:08:41,000
And I'm mentioning this here

164
00:08:41,000 --> 00:08:44,000
because it is of course a common scenario

165
00:08:44,000 --> 00:08:46,000
that you're displaying images

166
00:08:46,000 --> 00:08:50,000
where you might not know their dimensions in advance.

167
00:08:50,000 --> 00:08:54,000
And in such cases, fill is a great alternative

168
00:08:54,000 --> 00:08:57,000
to explicitly setting a width or height,

169
00:08:57,000 --> 00:08:59,000
which you should do though

170
00:08:59,000 --> 00:09:02,000
if you know the width and height in advance.

171
00:09:04,000 --> 00:09:07,000
So that's therefore this MealItem component added.

172
00:09:07,000 --> 00:09:08,000
And with that added,

173
00:09:08,000 --> 00:09:11,000
we can output it here in the MealsGrid component.

174
00:09:12,000 --> 00:09:14,000
So here between those li tags,

175
00:09:14,000 --> 00:09:17,000
I'll output the the MealItem like this.

176
00:09:18,000 --> 00:09:22,000
And I'll simply forward all those meal properties

177
00:09:22,000 --> 00:09:26,000
from that meal we have here to that MealItem.

178
00:09:26,000 --> 00:09:29,000
So I use this syntax

179
00:09:29,000 --> 00:09:32,000
to pull out all the properties of that meal object

180
00:09:32,000 --> 00:09:35,000
and spread them as key-value pairs,

181
00:09:35,000 --> 00:09:39,000
so as props in the end, onto this MealItem.

182
00:09:40,000 --> 00:09:42,000
And since the meal I get here,

183
00:09:42,000 --> 00:09:46,000
since the meals I'll have in this meals array eventually

184
00:09:46,000 --> 00:09:48,000
will have all those properties

185
00:09:48,000 --> 00:09:51,000
that are expected as props here,

186
00:09:51,000 --> 00:09:54,000
this approach will work just fine.

187
00:09:54,000 --> 00:09:57,000
Now, of course, at the moment we have no data source yet,

188
00:09:57,000 --> 00:10:00,000
so at the moment, we won't see anything on the screen.

189
00:10:00,000 --> 00:10:02,000
Nonetheless, we can already take

190
00:10:02,000 --> 00:10:04,000
this MealsGrid component here

191
00:10:04,000 --> 00:10:08,000
and go to this page.js file in the meals folder

192
00:10:08,000 --> 00:10:10,000
and output it here.

193
00:10:10,000 --> 00:10:13,000
But at the moment, I'll set meals to an empty array

194
00:10:13,000 --> 00:10:16,000
because, as mentioned, we have no meals yet.

195
00:10:17,000 --> 00:10:21,000
So if we save that and we go to the Browse Meals page,

196
00:10:21,000 --> 00:10:22,000
we see our header,

197
00:10:22,000 --> 00:10:25,000
which allows us to go to that share meal page,

198
00:10:25,000 --> 00:10:27,000
but we see no meals yet,

199
00:10:27,000 --> 00:10:29,000
but that's what we'll add next.

