1
00:00:00,080 --> 00:00:02,940
In this video, we are going to be wiring our

2
00:00:02,940 --> 00:00:05,740
frontend search feature component to the backend

3
00:00:05,740 --> 00:00:08,300
endpoint we just built so that we can start

4
00:00:08,300 --> 00:00:10,780
getting travel suggestion results.

5
00:00:10,780 --> 00:00:14,260
To begin, first, let's look at what we have

6
00:00:14,260 --> 00:00:16,800
going on in the frontend section of our seed

7
00:00:16,800 --> 00:00:19,960
project, specifically for the search feature.

8
00:00:19,960 --> 00:00:22,120
The search feature is present in the Search

9
00:00:22,120 --> 00:00:24,800
by Location tab on our home page.

10
00:00:24,800 --> 00:00:28,000
Here we can see our search text box, preferences

11
00:00:28,000 --> 00:00:31,660
checkboxes, and submit button.

12
00:00:31,660 --> 00:00:35,420
If we go back to VS Code and locate the index.html

13
00:00:35,420 --> 00:00:38,900
file for our home page and scroll down to

14
00:00:38,900 --> 00:00:46,680
the Input Tabs section, we can see our Search

15
00:00:46,680 --> 00:00:49,640
by Location tab.

16
00:00:49,640 --> 00:00:51,800
And if we scroll just a little bit further

17
00:00:51,800 --> 00:00:56,420
down, we can see our request form with all

18
00:00:56,420 --> 00:01:00,200
our form widgets for the location search.

19
00:01:00,200 --> 00:01:02,300
We have the input text box where we can enter

20
00:01:02,300 --> 00:01:05,480
in a location and get suggestions for destinations

21
00:01:05,480 --> 00:01:07,720
we can travel to.

22
00:01:07,720 --> 00:01:12,280
And we also have our list of travel preferences,

23
00:01:12,280 --> 00:01:15,500
checkboxes for each of the options that are

24
00:01:15,500 --> 00:01:19,120
available for us on this application.

25
00:01:19,120 --> 00:01:21,760
Now if we still scroll further down to the

26
00:01:21,760 --> 00:01:27,660
results section, let's find the results section.

27
00:01:27,660 --> 00:01:30,180
Here at the results section, we can see where

28
00:01:30,180 --> 00:01:32,920
our destinations are going to be displayed.

29
00:01:32,920 --> 00:01:35,160
We have the main wrapper which has been given

30
00:01:35,160 --> 00:01:38,520
an ID of results section and a results container

31
00:01:38,520 --> 00:01:41,000
where the destinations will be dynamically

32
00:01:41,000 --> 00:01:42,760
inserted.

33
00:01:42,760 --> 00:01:44,900
All these containers and widgets have all

34
00:01:44,900 --> 00:01:48,160
been given IDs to target them and reference

35
00:01:48,160 --> 00:01:50,140
in our JavaScript code.

36
00:01:50,140 --> 00:01:52,280
Now speaking of JavaScript, let's head over

37
00:01:52,280 --> 00:01:53,940
to app.js,

38
00:01:53,940 --> 00:01:55,960
where the real integration is going to be

39
00:01:55,960 --> 00:01:57,320
taking place.

40
00:01:57,320 --> 00:01:59,220
Bring up app.js,

41
00:01:59,220 --> 00:02:00,980
pull this aside once again.

42
00:02:00,980 --> 00:02:02,780
And now here in app.js,

43
00:02:02,780 --> 00:02:04,980
we start by defining a constant

44
00:02:04,980 --> 00:02:06,940
for our API endpoint.

45
00:02:06,940 --> 00:02:09,380
We'll be using this in all our front-end API

46
00:02:09,380 --> 00:02:10,360
requests.

47
00:02:10,360 --> 00:02:12,800
And this makes it easy to switch URLs

48
00:02:12,800 --> 00:02:15,400
if we need to change to a production or staging

49
00:02:15,400 --> 00:02:16,840
server.

50
00:02:16,840 --> 00:02:19,420
We also have our DOMELEMENTS section, where

51
00:02:19,420 --> 00:02:21,820
the location form variable targets our search

52
00:02:21,820 --> 00:02:22,500
form.

53
00:02:22,500 --> 00:02:24,320
We also have the variables RESULTS section

54
00:02:24,320 --> 00:02:26,920
and RESULTS container that help target where

55
00:02:26,920 --> 00:02:29,100
we'll be displaying our search results.

56
00:02:29,100 --> 00:02:31,480
To integrate our frontend with our API, we'll

57
00:02:31,480 --> 00:02:33,420
be adding an event listener to handle our

58
00:02:33,420 --> 00:02:35,960
form, submit it to the backend, collect the

59
00:02:35,960 --> 00:02:39,840
results, and display them in our RESULTS section.

60
00:02:39,840 --> 00:02:42,860
A couple of utility functions are also here

61
00:02:42,860 --> 00:02:45,120
to help us with the flow.

62
00:02:45,120 --> 00:02:47,440
So let us take a look at some of them.

63
00:02:47,440 --> 00:02:55,640
First we have our getSelectedPreferences function.

64
00:02:55,640 --> 00:02:58,400
This function helps us collect all preferences

65
00:02:58,400 --> 00:03:01,560
selected by the user.

66
00:03:01,560 --> 00:03:03,800
These are all the checkboxes that the user

67
00:03:03,800 --> 00:03:06,560
clicks in the preferences section.

68
00:03:06,560 --> 00:03:14,600
We also have the limitPreferences function.

69
00:03:14,600 --> 00:03:16,960
This function ensures that the user selects

70
00:03:16,960 --> 00:03:20,220
a maximum of 3 preferences and displays a

71
00:03:20,220 --> 00:03:22,920
message if the user tries to go above that

72
00:03:22,920 --> 00:03:25,880
threshold.

73
00:03:25,880 --> 00:03:30,200
Another utility function is the displaySuggestions

74
00:03:30,200 --> 00:03:32,580
function.

75
00:03:32,580 --> 00:03:34,820
This function takes our destination results

76
00:03:34,820 --> 00:03:37,960
from the API and displays them in our result

77
00:03:37,960 --> 00:03:39,600
containers.

78
00:03:39,600 --> 00:03:47,940
We also have the createDestinationCard function.

79
00:03:47,940 --> 00:03:50,680
Let's go to the actual function definition.

80
00:03:50,680 --> 00:03:51,500
Good.

81
00:03:51,500 --> 00:03:54,120
Now, this function will create a card for

82
00:03:54,120 --> 00:03:56,960
each suggested travel destination with all

83
00:03:56,960 --> 00:03:58,340
the details.

84
00:03:58,340 --> 00:04:01,160
As you can see, it creates a new div, attaches

85
00:04:01,160 --> 00:04:03,720
a class name with our styling library which

86
00:04:03,720 --> 00:04:06,580
which is bootstrap and undoes everything that

87
00:04:06,580 --> 00:04:09,780
has to do with displaying what the destination

88
00:04:09,780 --> 00:04:13,320
cards show to our users.

89
00:04:13,320 --> 00:04:18,680
Other helpful functions in this file are functions

90
00:04:18,680 --> 00:04:23,060
like showToast, equal to definition, this

91
00:04:23,060 --> 00:04:25,580
simply prints out a message to the user.

92
00:04:25,580 --> 00:04:30,040
We also have showLoading, showLoading helps

93
00:04:30,040 --> 00:04:31,920
us to display a progress bar when we are calling

94
00:04:31,920 --> 00:04:32,960
our API.

95
00:04:32,960 --> 00:04:36,460
And we also have the alternate function to

96
00:04:36,460 --> 00:04:40,640
that, hideLoading, which hides our progress

97
00:04:40,640 --> 00:04:42,020
bar.

98
00:04:42,020 --> 00:04:43,920
We'll be using these functions in our integration

99
00:04:43,920 --> 00:04:47,440
flow to request for and display our travel

100
00:04:47,440 --> 00:04:48,740
destinations.

101
00:04:48,740 --> 00:04:53,560
Now let's get to work on our actual integration.

102
00:04:53,560 --> 00:04:55,960
If we scroll down, you can see the section

103
00:04:55,960 --> 00:04:58,920
that has been marked out for us to write the

104
00:04:58,920 --> 00:05:00,960
code to do that.

105
00:05:00,960 --> 00:05:02,480
Scroll down.

106
00:05:02,480 --> 00:05:04,780
And this is our first integration task, to

107
00:05:04,780 --> 00:05:07,680
undo the LocationFormSubmission.

108
00:05:07,680 --> 00:05:09,860
We'll start by attaching an event handler

109
00:05:09,860 --> 00:05:12,500
to our LocationFormHandle.

110
00:05:12,500 --> 00:05:19,800
So here we'll say LocationForm.AddEventListener.

111
00:05:19,800 --> 00:05:22,300
We'll undo the submit operation.

112
00:05:22,300 --> 00:05:24,740
operation, give it an async function because

113
00:05:24,740 --> 00:05:31,720
we're going to be calling an API, and open

114
00:05:31,720 --> 00:05:33,600
up our function.

115
00:05:33,600 --> 00:05:35,860
Inside the handler function, first, let us

116
00:05:35,860 --> 00:05:38,420
prevent the default form submission behavior

117
00:05:38,420 --> 00:05:41,560
and get our data from the form.

118
00:05:41,560 --> 00:05:43,540
We've captured our event here as the argument

119
00:05:43,540 --> 00:05:48,100
to this function, so we say e.preventDefault.

120
00:05:48,100 --> 00:05:51,640
Then let us get our data.

121
00:05:51,640 --> 00:05:56,600
location by saying document.getElementById

122
00:05:56,600 --> 00:06:09,560
and we're going to grab our location input

123
00:06:09,560 --> 00:06:13,640
which is the ID of the text box.

124
00:06:13,640 --> 00:06:17,940
We call the value attribute and trim it of

125
00:06:17,940 --> 00:06:20,780
white spaces.

126
00:06:20,780 --> 00:06:21,860
It's good.

127
00:06:21,860 --> 00:06:23,520
Now let us get our preferences.

128
00:06:23,520 --> 00:06:28,120
So const preferences equals.

129
00:06:28,120 --> 00:06:31,820
And we can simply use our helper function,

130
00:06:31,820 --> 00:06:36,280
getSelectedPreferences.

131
00:06:36,280 --> 00:06:39,380
And we can pass it the variable that we are

132
00:06:39,380 --> 00:06:40,660
using

133
00:06:40,660 --> 00:06:45,300
to get our preference checkboxes.

134
00:06:45,300 --> 00:06:51,840
Scroll down and put it here.

135
00:06:51,840 --> 00:06:53,160
Good.

136
00:06:53,160 --> 00:06:55,220
The next thing we're going to do is to check

137
00:06:55,220 --> 00:06:57,200
if the location is not empty.

138
00:06:57,200 --> 00:06:59,300
If it's empty, we'll be showing a message

139
00:06:59,300 --> 00:06:59,960
to the user

140
00:06:59,960 --> 00:07:02,360
indicating that the search field is empty.

141
00:07:02,360 --> 00:07:05,120
If not, we'll kick start the process of calling

142
00:07:05,120 --> 00:07:06,080
our API

143
00:07:06,080 --> 00:07:08,060
by showing a progress indicator.

144
00:07:08,060 --> 00:07:09,260
So let's do that.

145
00:07:09,260 --> 00:07:14,400
So down here, we'll say, if our location is

146
00:07:14,400 --> 00:07:16,120
empty,

147
00:07:16,120 --> 00:07:19,760
they will simply want to show a toast message

148
00:07:19,760 --> 00:07:20,920
using our showToast

149
00:07:20,920 --> 00:07:22,020
function.

150
00:07:22,020 --> 00:07:28,300
And we'll say, please enter a location.

151
00:07:28,300 --> 00:07:30,380
And the type of warning we want to send,

152
00:07:30,380 --> 00:07:31,920
or the type of message we want to send, is

153
00:07:31,920 --> 00:07:34,880
a warning message.

154
00:07:34,880 --> 00:07:39,160
And we can just return from there.

155
00:07:39,160 --> 00:07:43,740
Then if this does not evaluate to true,

156
00:07:43,740 --> 00:07:46,960
we can kickstart our process by showing our

157
00:07:46,960 --> 00:07:48,960
progress indicator.

158
00:07:48,960 --> 00:07:50,980
After our progress indicator, we can then

159
00:07:50,980 --> 00:07:53,220
kickstart our request.

160
00:07:53,220 --> 00:07:55,220
We'll be wrapping that in a tricard block.

161
00:07:55,220 --> 00:07:58,360
So let us write out the tricard block.

162
00:07:58,360 --> 00:08:08,000
I'm going to say try, catch, error.

163
00:08:08,000 --> 00:08:09,080
Good.

164
00:08:09,080 --> 00:08:12,440
Let's give this a little space here.

165
00:08:12,440 --> 00:08:15,180
Now, inside the try section, we'll now process

166
00:08:15,180 --> 00:08:16,080
our request

167
00:08:16,080 --> 00:08:18,700
and display the results.

168
00:08:18,700 --> 00:08:20,480
So let's write the code for all that.

169
00:08:20,480 --> 00:08:22,980
I'm going to come here, scroll down a little

170
00:08:22,980 --> 00:08:25,160
bit into view.

171
00:08:25,160 --> 00:08:28,660
And here, we'll say const response equals

172
00:08:28,660 --> 00:08:31,040
await.

173
00:08:31,040 --> 00:08:35,400
Then use the fetch API to call our endpoint.

174
00:08:35,400 --> 00:08:36,880
That's the endpoint we created in the previous

175
00:08:36,880 --> 00:08:38,440
video.

176
00:08:38,440 --> 00:08:43,140
We'll then tell it to point to our API base

177
00:08:43,140 --> 00:08:46,320
URL

178
00:08:46,320 --> 00:08:50,880
and go to the endpoint API for slash suggest

179
00:08:50,880 --> 00:08:54,880
by location.

180
00:08:54,880 --> 00:09:03,620
And here, we wanted to use the POST method.

181
00:09:03,620 --> 00:09:09,940
And for headers, we want to set a single header.

182
00:09:09,940 --> 00:09:15,480
We'll say content type.

183
00:09:15,480 --> 00:09:21,480
And that will be application for slash json.

184
00:09:21,480 --> 00:09:22,940
Seeing some squiggly lines here.

185
00:09:22,940 --> 00:09:24,360
Seems I'm missing something.

186
00:09:24,360 --> 00:09:27,140
OK, yeah, these all need to be in a configuration

187
00:09:27,140 --> 00:09:28,620
object.

188
00:09:28,620 --> 00:09:30,660
Yeah, sorry about that.

189
00:09:30,660 --> 00:09:31,960
Back this.

190
00:09:31,960 --> 00:09:33,600
This all need to be.

191
00:09:33,600 --> 00:09:35,540
OK, good.

192
00:09:35,540 --> 00:09:37,760
So define our headers.

193
00:09:37,760 --> 00:09:40,480
Then we can say body.

194
00:09:40,480 --> 00:09:44,880
And that will be json.stringify.

195
00:09:44,880 --> 00:09:48,740
And inside there, we'll simply serialize our

196
00:09:48,740 --> 00:09:49,280
request.

197
00:09:49,280 --> 00:09:57,640
So say location, set location, and we'll set

198
00:09:57,640 --> 00:09:59,880
preferences

199
00:09:59,880 --> 00:10:07,660
to preferences.

200
00:10:07,660 --> 00:10:12,800
As our fetch request, let us bring this here.

201
00:10:12,800 --> 00:10:16,540
So if we get a response, or if we don't get

202
00:10:16,540 --> 00:10:19,100
a response,

203
00:10:19,100 --> 00:10:22,280
or we get a failure, we're simply

204
00:10:22,280 --> 00:10:26,080
going to throw a new exception or a new arrow

205
00:10:26,080 --> 00:10:32,800
and say, failed to fetch suggestions.

206
00:10:32,800 --> 00:10:35,540
However, if we do get something back,

207
00:10:35,540 --> 00:10:37,800
just call this interview, and say,

208
00:10:37,800 --> 00:10:45,340
countData equals awaitResponse.data.

209
00:10:45,340 --> 00:10:48,040
And since we're done with our request,

210
00:10:48,040 --> 00:10:51,440
we can hide our loading indicator

211
00:10:51,440 --> 00:10:57,780
and call our displaySuggestions function.

212
00:10:57,780 --> 00:11:03,300
And this we can pass our data.destinations

213
00:11:03,300 --> 00:11:06,280
because that is the name of the data parameter

214
00:11:06,280 --> 00:11:09,720
where our destinations are stored.

215
00:11:09,720 --> 00:11:10,920
Perfect.

216
00:11:10,920 --> 00:11:13,200
Now let's make sure that we are handling error

217
00:11:13,200 --> 00:11:13,760
situations

218
00:11:13,760 --> 00:11:15,060
in the catch block also.

219
00:11:15,060 --> 00:11:18,080
So let's just do that quickly.

220
00:11:18,080 --> 00:11:21,220
First, we want to hide loading, just in case

221
00:11:21,220 --> 00:11:22,440
any loading

222
00:11:22,440 --> 00:11:24,580
operation is going on.

223
00:11:24,580 --> 00:11:27,300
Then we'll just print something helpful to

224
00:11:27,300 --> 00:11:30,440
our console, which

225
00:11:30,440 --> 00:11:33,960
is the error.

226
00:11:33,960 --> 00:11:39,800
And let us show a message to our user.

227
00:11:39,800 --> 00:11:47,600
Say, error, fetching travel suggestions.

228
00:11:47,600 --> 00:11:52,800
Please try again.

229
00:11:52,800 --> 00:11:57,100
And this message will be a danger type

230
00:11:57,100 --> 00:11:59,220
to indicate that it is something very, very

231
00:11:59,220 --> 00:12:00,980
serious.

232
00:12:00,980 --> 00:12:02,400
Great.

233
00:12:02,400 --> 00:12:05,140
Now we have completed our integration, however,

234
00:12:05,140 --> 00:12:06,820
we need to test everything to make sure that

235
00:12:06,820 --> 00:12:09,260
we have no errors and that it's all working

236
00:12:09,260 --> 00:12:11,360
as expected.

237
00:12:11,360 --> 00:12:15,000
We'll be doing that in our next video.

