﻿1
00:00:01,140 --> 00:00:03,450
‫Welcome to the last lecture

2
00:00:03,450 --> 00:00:06,360
‫of the Wild Oasis project.

3
00:00:06,360 --> 00:00:08,940
‫So at this point, we have essentially

4
00:00:08,940 --> 00:00:11,040
‫finished the application,

5
00:00:11,040 --> 00:00:14,370
‫and so let's just fix a small thing or two,

6
00:00:14,370 --> 00:00:16,263
‫and then wrap it all up.

7
00:00:18,030 --> 00:00:21,420
‫Now, the main thing that I want to fix in this video

8
00:00:21,420 --> 00:00:25,500
‫is a small bug that we left in our menus.

9
00:00:25,500 --> 00:00:29,100
‫So right here, when I click, then that works just fine,

10
00:00:29,100 --> 00:00:31,800
‫and the same when I click outside.

11
00:00:31,800 --> 00:00:34,920
‫However, when I click here, and then click again,

12
00:00:34,920 --> 00:00:39,450
‫the idea was that this should then close this menu again,

13
00:00:39,450 --> 00:00:41,790
‫but that is not currently working,

14
00:00:41,790 --> 00:00:44,913
‫and so let me show you how to fix this problem.

15
00:00:46,470 --> 00:00:49,263
‫So let's open up our Menus file,

16
00:00:50,760 --> 00:00:54,360
‫and so let's see,

17
00:00:54,360 --> 00:00:56,190
‫yeah, this here is the function,

18
00:00:56,190 --> 00:00:59,760
‫this handleClick where we actually do the opening

19
00:00:59,760 --> 00:01:01,680
‫and the closing.

20
00:01:01,680 --> 00:01:05,163
‫So here, let's add a console.log,

21
00:01:06,420 --> 00:01:08,370
‫let's say, click,

22
00:01:08,370 --> 00:01:11,490
‫and then let's also add a console.log here

23
00:01:11,490 --> 00:01:13,757
‫to the useOutsideClick.

24
00:01:14,910 --> 00:01:18,783
‫So let's, well, I will duplicate this and leave it here,

25
00:01:19,800 --> 00:01:22,263
‫and here, let's now create a new function.

26
00:01:23,460 --> 00:01:28,410
‫And so in this function, we will call the close function,

27
00:01:28,410 --> 00:01:31,803
‫but we will also have a console.log saying,

28
00:01:32,700 --> 00:01:37,700
‫close from click outside.

29
00:01:37,890 --> 00:01:39,720
‫And you don't have to write this code,

30
00:01:39,720 --> 00:01:43,473
‫this is just to show you why we have that bug right now.

31
00:01:44,730 --> 00:01:48,120
‫So let's see what happens when we click here.

32
00:01:48,120 --> 00:01:50,280
‫And so then indeed, we get click,

33
00:01:50,280 --> 00:01:54,360
‫and then as I click again, watch what happens.

34
00:01:54,360 --> 00:01:57,600
‫So we basically, whenever we click there,

35
00:01:57,600 --> 00:01:59,700
‫we first close the menu,

36
00:01:59,700 --> 00:02:04,200
‫and then here, in this next millisecond, it is opened again,

37
00:02:04,200 --> 00:02:06,480
‫and so basically, what is happening here

38
00:02:06,480 --> 00:02:10,230
‫is that when we click here while the menu is open,

39
00:02:10,230 --> 00:02:12,870
‫it is closed for one millisecond,

40
00:02:12,870 --> 00:02:15,810
‫and then it is opened immediately again,

41
00:02:15,810 --> 00:02:18,390
‫and so we need to fix this part

42
00:02:18,390 --> 00:02:21,573
‫where a click from the outside is detected.

43
00:02:23,400 --> 00:02:28,020
‫So the way we do that is to pass in here the second argument

44
00:02:28,020 --> 00:02:31,293
‫and set it back to false.

45
00:02:32,430 --> 00:02:35,250
‫So remember how here, in this custom hook,

46
00:02:35,250 --> 00:02:38,520
‫we are, by default, listening for events

47
00:02:38,520 --> 00:02:41,130
‫on the capturing phase,

48
00:02:41,130 --> 00:02:44,160
‫so we have listenCapturing set to true,

49
00:02:44,160 --> 00:02:47,460
‫and so that is causing the problem in this situation.

50
00:02:47,460 --> 00:02:50,520
‫So instead of listening in the capturing phase,

51
00:02:50,520 --> 00:02:53,640
‫which is where the event goes from the DOM

52
00:02:53,640 --> 00:02:55,500
‫onto the target element,

53
00:02:55,500 --> 00:02:58,860
‫we now need to listen in the bubbling phase

54
00:02:58,860 --> 00:03:01,620
‫where the event goes from the target element

55
00:03:01,620 --> 00:03:03,930
‫back up to the document,

56
00:03:03,930 --> 00:03:06,090
‫and this is actually the default way

57
00:03:06,090 --> 00:03:08,910
‫in which the addEventListener works.

58
00:03:08,910 --> 00:03:13,500
‫And so by setting this prop here, or this argument to false,

59
00:03:13,500 --> 00:03:16,623
‫we will basically go back to that default way.

60
00:03:20,040 --> 00:03:23,520
‫So let's try this, let's reload,

61
00:03:23,520 --> 00:03:25,680
‫and so then we will see that this still

62
00:03:25,680 --> 00:03:29,220
‫doesn't fix the problem, so let's click here,

63
00:03:29,220 --> 00:03:32,790
‫and so now, we basically have the opposite problem.

64
00:03:32,790 --> 00:03:35,100
‫So we click, which will then open,

65
00:03:35,100 --> 00:03:38,940
‫but then immediately, we detect a click from the outside,

66
00:03:38,940 --> 00:03:40,833
‫which will then close the menu again.

67
00:03:42,690 --> 00:03:44,253
‫So let's fix that as well,

68
00:03:46,140 --> 00:03:50,040
‫and so what we have to do is to come here to this function,

69
00:03:50,040 --> 00:03:53,310
‫and then stop the propagation of the event,

70
00:03:53,310 --> 00:03:55,007
‫so e.stopPropagation,

71
00:03:59,250 --> 00:04:01,770
‫and so with this, the event will then never

72
00:04:01,770 --> 00:04:03,780
‫travel up further in the DOM,

73
00:04:03,780 --> 00:04:08,780
‫and can then therefore not be detected as a click outside,

74
00:04:08,850 --> 00:04:12,810
‫so this part here should then no longer happen.

75
00:04:12,810 --> 00:04:13,773
‫So let's see,

76
00:04:15,750 --> 00:04:18,120
‫and nice.

77
00:04:18,120 --> 00:04:21,570
‫So now, it works exactly as expected,

78
00:04:21,570 --> 00:04:24,000
‫and then if we click outside here,

79
00:04:24,000 --> 00:04:26,940
‫then is where we finally get this message,

80
00:04:26,940 --> 00:04:31,940
‫and where the menus close in a situation

81
00:04:32,370 --> 00:04:34,740
‫where we want it to close.

82
00:04:34,740 --> 00:04:39,740
‫Great, so let's just get rid of this one, turn this back on,

83
00:04:40,140 --> 00:04:44,490
‫and then very important, we need to pass in false.

84
00:04:44,490 --> 00:04:47,640
‫So this was really just an issue with the DOM

85
00:04:47,640 --> 00:04:51,570
‫and with how events work, so nothing about React,

86
00:04:51,570 --> 00:04:54,900
‫but still, it is important that you keep knowing

87
00:04:54,900 --> 00:04:56,190
‫about these things,

88
00:04:56,190 --> 00:04:58,620
‫even if you build React applications

89
00:04:58,620 --> 00:05:02,073
‫and not just vanilla JavaScript applications,

90
00:05:03,180 --> 00:05:06,900
‫but anyway, now, this bug is fixed,

91
00:05:06,900 --> 00:05:09,330
‫and the final thing that I want to do now

92
00:05:09,330 --> 00:05:14,330
‫is to just get rid of this uploader,

93
00:05:14,490 --> 00:05:16,860
‫and of course, take one final look

94
00:05:16,860 --> 00:05:20,160
‫at this beautiful dashboard that we just built,

95
00:05:20,160 --> 00:05:24,150
‫and notice how the loading spinner that we created here

96
00:05:24,150 --> 00:05:27,720
‫really showed up only inside this component

97
00:05:27,720 --> 00:05:29,730
‫and not on the entire page,

98
00:05:29,730 --> 00:05:33,240
‫so that was one of the things that we did here.

99
00:05:33,240 --> 00:05:36,370
‫And let's actually upload the bookings one more time

100
00:05:37,320 --> 00:05:41,220
‫just so that later, when we deploy this project,

101
00:05:41,220 --> 00:05:45,273
‫we then still get all this nice updated data.

102
00:05:46,980 --> 00:05:51,420
‫All right, and then let's finally get rid of that,

103
00:05:51,420 --> 00:05:54,843
‫so that should be in our sidebar,

104
00:05:55,830 --> 00:05:56,913
‫and there it is.

105
00:05:59,130 --> 00:06:00,243
‫Here, as well,

106
00:06:03,660 --> 00:06:06,930
‫and nice, so that's gone as well,

107
00:06:06,930 --> 00:06:10,890
‫and we could also remove here the React Query devtools,

108
00:06:10,890 --> 00:06:13,530
‫but I think that they will automatically disappear

109
00:06:13,530 --> 00:06:16,440
‫once we actually are in production,

110
00:06:16,440 --> 00:06:19,320
‫so no need to take that away here,

111
00:06:19,320 --> 00:06:22,140
‫and actually, there are two more things

112
00:06:22,140 --> 00:06:24,450
‫that I want to fix right now,

113
00:06:24,450 --> 00:06:27,360
‫and the first thing is if we open up

114
00:06:27,360 --> 00:06:30,513
‫a booking detail page that doesn't exist.

115
00:06:31,350 --> 00:06:34,740
‫So let's come here to see these details,

116
00:06:34,740 --> 00:06:36,270
‫but let's say that for example,

117
00:06:36,270 --> 00:06:40,833
‫we land on a page which has some ID that doesn't exist,

118
00:06:41,730 --> 00:06:45,120
‫so that will create then a bug,

119
00:06:45,120 --> 00:06:48,510
‫which will be caught in our error boundary,

120
00:06:48,510 --> 00:06:52,410
‫so the boundary that we implemented in the previous lecture,

121
00:06:52,410 --> 00:06:54,780
‫but this is still not ideal,

122
00:06:54,780 --> 00:06:57,570
‫because we get this weird error message,

123
00:06:57,570 --> 00:07:00,930
‫and really, what should be happening is not an error,

124
00:07:00,930 --> 00:07:03,840
‫but just the information that this booking

125
00:07:03,840 --> 00:07:05,610
‫couldn't be found,

126
00:07:05,610 --> 00:07:08,340
‫and so let's quickly come here

127
00:07:08,340 --> 00:07:13,340
‫to our Features, and then Bookings,

128
00:07:13,770 --> 00:07:16,320
‫and this is in the booking detail,

129
00:07:16,320 --> 00:07:21,320
‫and so here, we can say, if no booking, I believe,

130
00:07:23,430 --> 00:07:25,920
‫but let's actually take a look

131
00:07:25,920 --> 00:07:28,170
‫at what the booking is right now.

132
00:07:28,170 --> 00:07:33,170
‫Well, we cannot, because the React Query devtools

133
00:07:34,290 --> 00:07:35,673
‫is no longer there.

134
00:07:37,200 --> 00:07:40,920
‫So I just want to see what the booking is in this case,

135
00:07:40,920 --> 00:07:43,760
‫if it's undefined or...

136
00:07:45,030 --> 00:07:49,143
‫So let's check that, and yeah, it is undefined.

137
00:07:50,370 --> 00:07:54,030
‫So as I was saying,

138
00:07:54,030 --> 00:07:57,570
‫then here, we can do, if there is no booking,

139
00:07:57,570 --> 00:08:01,470
‫then we return again that empty component

140
00:08:01,470 --> 00:08:03,930
‫that I believe we have used before,

141
00:08:03,930 --> 00:08:07,500
‫and there, we can specify the resourceName prop,

142
00:08:07,500 --> 00:08:11,433
‫and here, it's called Booking,

143
00:08:12,420 --> 00:08:15,363
‫and so let's see, let's reload here,

144
00:08:18,510 --> 00:08:20,730
‫and that's a lot better.

145
00:08:20,730 --> 00:08:22,770
‫So now, we simply get the information

146
00:08:22,770 --> 00:08:24,843
‫that no booking could be found.

147
00:08:26,430 --> 00:08:31,430
‫All right, and now to finish, at least for now, at least,

148
00:08:32,100 --> 00:08:35,490
‫let's come here to our, well, actually to our context,

149
00:08:35,490 --> 00:08:37,980
‫to our dark mode context,

150
00:08:37,980 --> 00:08:42,240
‫because remember how initially we set the dark mode here

151
00:08:42,240 --> 00:08:46,560
‫to false by default, but instead of doing that,

152
00:08:46,560 --> 00:08:50,640
‫we can actually use as a default value the setting

153
00:08:50,640 --> 00:08:54,600
‫that the user set in their operating system.

154
00:08:54,600 --> 00:08:58,890
‫So for example, I have dark mode by default

155
00:08:58,890 --> 00:09:01,950
‫on here in my operating system,

156
00:09:01,950 --> 00:09:04,200
‫and so we can get access to that,

157
00:09:04,200 --> 00:09:06,240
‫basically using a media query,

158
00:09:06,240 --> 00:09:09,663
‫which we can run with window.matchMedia,

159
00:09:12,360 --> 00:09:16,740
‫and then here, we kind of pass in a media query.

160
00:09:16,740 --> 00:09:19,050
‫So here we need the parenthesis,

161
00:09:19,050 --> 00:09:24,050
‫and then prefers-color-scheme: dark,

162
00:09:27,720 --> 00:09:28,923
‫then close that,

163
00:09:30,900 --> 00:09:35,073
‫and then we can check if this media query matches.

164
00:09:36,030 --> 00:09:39,270
‫So indeed, in my case, it does match,

165
00:09:39,270 --> 00:09:42,780
‫and so for me, if we now used this here

166
00:09:42,780 --> 00:09:44,220
‫as the default value,

167
00:09:44,220 --> 00:09:47,670
‫then on the first time that I opened up the application,

168
00:09:47,670 --> 00:09:49,983
‫it would already be in dark mode.

169
00:09:51,330 --> 00:09:55,353
‫So let's use that here instead of this false,

170
00:09:56,760 --> 00:09:59,100
‫which is not going to change anything,

171
00:09:59,100 --> 00:10:02,820
‫because at this point, we already have that value

172
00:10:02,820 --> 00:10:04,233
‫in our local storage,

173
00:10:05,370 --> 00:10:09,273
‫but actually, let's check what happens if we remove that.

174
00:10:11,460 --> 00:10:15,390
‫So somewhere here, we should...

175
00:10:15,390 --> 00:10:17,340
‫Yeah, here it is.

176
00:10:17,340 --> 00:10:22,200
‫So here, we can remove this, and so if I now reload,

177
00:10:22,200 --> 00:10:24,573
‫then it should be automatically in dark mode,

178
00:10:26,220 --> 00:10:29,760
‫and indeed, it is, nice.

179
00:10:29,760 --> 00:10:32,910
‫So just another small feature here,

180
00:10:32,910 --> 00:10:36,873
‫but I think this is another really nice one.

181
00:10:38,190 --> 00:10:41,670
‫Now, in the future, if more bugs arise here,

182
00:10:41,670 --> 00:10:46,050
‫so if any of you finds any bug in this application,

183
00:10:46,050 --> 00:10:49,290
‫then please report it in the Q&A section,

184
00:10:49,290 --> 00:10:53,220
‫and then at some point, I will fix it in this application,

185
00:10:53,220 --> 00:10:57,630
‫and so I might then do that exactly in this video as well,

186
00:10:57,630 --> 00:11:00,960
‫but for now, with all this being said and done,

187
00:11:00,960 --> 00:11:04,290
‫we actually finished this project.

188
00:11:04,290 --> 00:11:08,280
‫So congratulations for building the probably

189
00:11:08,280 --> 00:11:12,690
‫biggest project ever in your web developer journey.

190
00:11:12,690 --> 00:11:17,220
‫So this was a really long and a really big one,

191
00:11:17,220 --> 00:11:20,340
‫but I hope that it was totally worth it,

192
00:11:20,340 --> 00:11:24,300
‫and I really hope that you enjoyed it as much as I did,

193
00:11:24,300 --> 00:11:28,650
‫and that you walk away with tons of valuable skills,

194
00:11:28,650 --> 00:11:32,370
‫not only React skills, but also skills

195
00:11:32,370 --> 00:11:35,820
‫on front end development in general.

196
00:11:35,820 --> 00:11:37,830
‫Now, there are a few more things

197
00:11:37,830 --> 00:11:40,710
‫that we could have implemented in this project,

198
00:11:40,710 --> 00:11:43,290
‫but I had to cut it off at some point,

199
00:11:43,290 --> 00:11:46,620
‫otherwise, we could have gone for 10 more hours,

200
00:11:46,620 --> 00:11:49,680
‫but if you feel like developing this even further,

201
00:11:49,680 --> 00:11:52,290
‫I have a few suggestions for you,

202
00:11:52,290 --> 00:11:55,380
‫and the most important one would definitely be

203
00:11:55,380 --> 00:11:59,040
‫to actually create new bookings right here

204
00:11:59,040 --> 00:12:00,990
‫from this application.

205
00:12:00,990 --> 00:12:03,870
‫So basically, right now, if a new guest

206
00:12:03,870 --> 00:12:05,430
‫appears in the hotel,

207
00:12:05,430 --> 00:12:07,920
‫we have no way of creating a booking

208
00:12:07,920 --> 00:12:10,620
‫and checking them in, right?

209
00:12:10,620 --> 00:12:13,320
‫So right now, all the bookings that we have

210
00:12:13,320 --> 00:12:15,870
‫were just part of the sample data,

211
00:12:15,870 --> 00:12:19,290
‫but we don't have any way of creating them,

212
00:12:19,290 --> 00:12:23,370
‫and so this would be a really nice challenge for you,

213
00:12:23,370 --> 00:12:25,770
‫and I actually built this myself,

214
00:12:25,770 --> 00:12:28,110
‫but it is a real challenge,

215
00:12:28,110 --> 00:12:30,240
‫and it's gonna take a lot of time,

216
00:12:30,240 --> 00:12:33,540
‫and so that's why I decided to not include it here

217
00:12:33,540 --> 00:12:34,563
‫at this point.

218
00:12:35,430 --> 00:12:38,700
‫You could also add the feature where a booking

219
00:12:38,700 --> 00:12:39,990
‫can be edited,

220
00:12:39,990 --> 00:12:44,850
‫and you could even add check in and check out times.

221
00:12:44,850 --> 00:12:48,780
‫Now, another thing is that in the real world hotel,

222
00:12:48,780 --> 00:12:53,010
‫the cabins or the rooms actually don't have a fixed price

223
00:12:53,010 --> 00:12:55,020
‫throughout the entire year,

224
00:12:55,020 --> 00:12:59,220
‫so instead, prices vary basically every single day,

225
00:12:59,220 --> 00:13:02,340
‫and so you could somehow implement that

226
00:13:02,340 --> 00:13:04,080
‫in this application as well,

227
00:13:04,080 --> 00:13:07,560
‫so where here, the users could set a different price

228
00:13:07,560 --> 00:13:10,620
‫for every single different day.

229
00:13:10,620 --> 00:13:13,230
‫Next up, another idea that I had

230
00:13:13,230 --> 00:13:17,280
‫is that you could add a restaurant to this hotel.

231
00:13:17,280 --> 00:13:20,790
‫So you could add another item here in the sidebar,

232
00:13:20,790 --> 00:13:23,280
‫which would take the user to a page

233
00:13:23,280 --> 00:13:26,160
‫where they can register a bill value

234
00:13:26,160 --> 00:13:29,940
‫each time that the guest goes to the restaurant,

235
00:13:29,940 --> 00:13:34,350
‫and so then at checkout, that bill would have to be paid.

236
00:13:34,350 --> 00:13:37,050
‫And finally, also during checkout,

237
00:13:37,050 --> 00:13:42,050
‫we could actually lead the user here to a page,

238
00:13:42,720 --> 00:13:44,520
‫so when we click here on Checkout,

239
00:13:44,520 --> 00:13:47,700
‫then that could lead to a page where we could then

240
00:13:47,700 --> 00:13:52,650
‫generate a PDF invoice that we could then mail to the user,

241
00:13:52,650 --> 00:13:56,070
‫since we already have their email address as well.

242
00:13:56,070 --> 00:13:58,980
‫Okay, so these are just a few ideas,

243
00:13:58,980 --> 00:14:03,210
‫and I'm sure you can come up with even more if you want,

244
00:14:03,210 --> 00:14:06,030
‫and if you do implement any of these,

245
00:14:06,030 --> 00:14:10,170
‫then please make sure to share it with me in the Q&A,

246
00:14:10,170 --> 00:14:12,993
‫or maybe even in the GitHub repo.

247
00:14:13,950 --> 00:14:17,910
‫All right, and so now, it's time to finally

248
00:14:17,910 --> 00:14:20,040
‫close up this section,

249
00:14:20,040 --> 00:14:23,310
‫but we do actually have one more thing to do,

250
00:14:23,310 --> 00:14:26,580
‫which is to deploy this project to production

251
00:14:26,580 --> 00:14:29,280
‫to a live server so that you can actually

252
00:14:29,280 --> 00:14:31,380
‫share it with everyone,

253
00:14:31,380 --> 00:14:35,913
‫and so let's go do that in the next super short section.

