Build & Deploy Full Stack AI Mock Interview NextJs App Using React
Build & Deploy Full Stack AI Mock Interview NextJs App Using React
Introduction
0:00
There are many video you will find on the internet about NAN automation. But
0:06
have you ever built a real life web application using NAN? So today we are
0:11
going to build an AI mock interview web application which we are going to
0:17
develop with the help of React, NexJS, NAN and lot of different text stack. Hey
0:24
there and welcome back to Tubuji channel. Today in this video we are going to build
a fullstack SAS AI mock
0:32
interview application completely from the scratch. In this application we also
0:38
added a live streaming authar who can take your mock interview. Let me walk
0:43
through the application first and then we'll talk about the all the text stack
which we are going to use to build this
0:48
application. If you see we have this beautiful landing screen and I'm going to tell
you how easily we can add this
0:54
landing screen for any SAS application. Then simply uh with the help of clerk we
1:01
added the uh Gmail and email password authentication. Once you sign in you
1:07
will redirect it to the dashboard where you will find that I already created uh
1:12
some of the mock interview but you have option to create a new interview.
1:18
Once you click on this create interview, you will find the dialogue where you have
option either you can upload the
1:23
resume or even you can add a job description with the title and the description.
Now let's upload resume. So
1:31
over here I will select the resume. Okay, here you will find the preview of that
selected file and then simply click
1:38
submit. Once you submit this, it will trigger this enh uh AI automation
1:44
workflow where it will generate the AI mock interview question and it will
1:49
return back to your application. You going to learn how we can set up this en
1:55
automation workflow in your local machine as well as on the cloud. Obviously for
that one we are going to
2:01
use a hostinger en feature which you can use it so that you can run your
2:06
application in the production as well. Obviously, I'm going to tell you each step
by step
2:12
implementation so that you can easily integrate it. Once your interview questions
are ready, it will redirect
2:18
you to this page where you can start the interview. On the click of it, it will
2:23
redirect you to the interview session page where you can connect the call. Now,
once you connect the call, it will
2:29
connect to a live uh aar agent. So let's try this out
2:34
about yourself and boom if you see our call is get
2:40
connected to this author agent where he can listen whatever I speak on the right
hand side you will see this conversation
2:46
which is getting printed out. Can you describe your experience with microservices
architecture and how you
2:51
have utilized it in your projects? I just pause and unmute this one. But if
2:57
you see overall this UI where we have this button to unmute and mute, connect
3:02
the call. You can even end the call and on the right hand side you will see this
conversation. This is the agent which
3:08
will talk and ask you the mock interview question. We also uh added this aar with
3:13
the help of Akul. Akul provide you the streaming authar API which is uh very
3:20
easy to integrate and with the help of Aul we added this uh streaming authar into
our application.
3:27
Now all of these questions and everything we are saving into the convex database.
Convex is a realtime database
3:34
and it's open source where we store all of the uh interview session the user
information all of this data to the
3:41
database. Once you're done with this one, you can simply end the call and then
within a
3:47
few seconds, it will generate the feedback for you. Once it ready, you will see
this feedback and your
3:54
interview record. You can even see this feedback any time with the feedback. Right
now, we don't have a suggestion,
4:00
but you will see the rating as well. If I check the previous old interview and
4:05
you click on the feedback uh you will find the feedback the suggestion for your
interview and the overall rating
4:12
everything uh AI will give you the response and we just need to add it. Obviously
this model
4:20
uh or this automation workflow will help us to generate the feedback as well. Okay,
just within a few drag and drop
4:27
and it will uh remove all the complicated logic and make our life
4:32
easier and that's all which we are going to build in this particular project. But
4:38
obviously uh we have the free tire and paid uh tire okay because this is a SAS
4:45
application user only create two interview daily and that limitation we added with
the help
4:52
of arjet you don't need to add any complicated logic because arjet will take care
of a rate limiting board
4:59
detection even the email validation and attack protection. Obviously there are
5:05
lot of feature you will find with the arjet and it's free to start. You can just um
go to this link in the
5:12
description and you can just get started with the arjet. I explain the complete
5:18
integration into our application to limit the user. Okay. Then if you want
5:23
to create unlimited interview simply uh you can have option to upgrade this
5:29
plan. Now it's very difficult for any developers or any user to add a payment
5:34
gateway to your web application. And in order to remove all of these complicated
5:39
logics code we are using clerk subscription billing feature where
5:45
within just one line of code you can add a pricing table into your application and
it will automatically uh do all the
5:53
job for the payment gateway. You don't need to do anything. Just add the plan to
the dashboard and it will u display
6:00
it on your screen. How easy it is, right? Everything we're going to learn in this
particular project. And if you
6:06
are new uh to any of the text tag, don't worry because I'm going to teach you
6:12
everything from the basic. So guys, if you are new to this channel and did not
6:17
subscribe to our channel, please do subscribe. Don't forget to press notification
bell icon so that you will
6:23
not miss any update. Uh if uh you want a source code of any of my project simply
6:29
go to the tubegury.com where you will find all the courses and the source code for
each of my project.
6:36
Also recently I launched brand new uh product called Krabic Studio AI which
6:42
will generate an AI short film video for you within just few line few clicks. Now
6:50
inside this you can create uh consistent character videos for a complete movie.
6:56
Not only that but you can edit each scene one by one. You have multiple video style
to generate like 3D pixar,
7:04
Gibli, cinematic, realistic anim and you can generate and export your video under
7:10
just 2 minute. Simply click the link in the description and join it for free.
7:15
You will get a free credits. Also you can explore the existing uh user created
7:21
project. You'll find it and it's very very interesting guys. Okay. You will see
this 3D animated video which you can
7:29
generate by just typing a one or two line of uh prompt. Okay. And you don't
7:35
need to do anything. This Kraix studio will take care of generating this video
7:41
for you and you can generate unlimited video. So go to the graphic studio, try
7:47
this out and generate the social media video. Start your own YouTube channel,
7:52
Instagram channel and just post this video.
Project Setup
7:59
First thing first, we need to create a react application and for that one we are
going to use a Njs. NexJS is a React
8:06
framework to develop the web application as it provide a lot of different feature
like built-in optimization, React server
8:14
component or client server rendering. The most important feature is and routing.
NextJS provide a folder based
8:21
routing. You don't need to add any configuration for the routing like React or
other frameworks. Also with the help
8:28
of middleware you can control your routing and the authentication for a
8:33
specific pages. Everything is included inside the NexJS which makes your
application secured much faster and
8:41
optimized. So it improve the performance of any react application. Now in order
8:47
to create a NexJS application this is the command line. In order to create just you
need to copy it and inside the
8:53
terminal you can just paste this one. So we'll open the terminal at the folder
where
8:59
you want to create a project. If you are using a Windows, make sure to open a
command prompt and simply paste this
9:05
command. Now at latest will in install the latest version of the NexJS every
9:11
time. So if you want to uh install any specific version, you can just mention
9:16
that version number and then click enter. After entering, you need to provide the
project name. So here we'll
9:23
say AI mock interview app
9:29
and then click enter. Then it asks do you want to use Typescript? So say yes
9:35
as we are using a TypeScript. If you don't know how to use TypeScript don't worry
because if you know the JavaScript
9:42
a little bit then you can easily um build an application with the help of
TypeScript. So we'll say yes to this
9:49
question. No to the ESL. Yes to the tailwind CSS. So it will automatically install
the TWIN CSS version 4 for us.
9:57
Then no to the source directory. Yes to the app router which is very important. And
then no to the turbo pack. No to the
10:04
import ally. And then if you see it started installing some uh dependency
10:11
like react, react DOM next and some dev dependency for the TypeScript and the
10:16
Telvin CSS. Once once it finished you can simply open a VS code. Open a folder
where you
10:25
just created this particular project. So in my case it is inside the documents
10:36
and here is a AI mock interview application. On the left hand side you will see
some
10:42
files and folders. Let walk through each uh folders and file one by one. The very
10:48
first folder which is the app folder which contain your all the pages u the
10:54
code which you are going to return in order to display the content. The app folder
contain a global CSS file uh
11:01
which is the CSS uh which is applied throughout the application. Then the
layout.tsx tsx file which is the root
11:08
layout of your application which contain the fonts the metadata which is quite
11:14
important for the SEO purpose and the HTML body tag through which your
11:20
children is going to render. Now all your pages are going to render through these
childrens. Then you have page.tsx
11:27
file which is the default page of your application. Now once you run this
application you'll get to know that how
11:33
this page.tsx tsx is getting rendered on the browser. Then we have node modules
11:39
folder. Uh obviously we are not going to touch to the uh this particular folder
which contain whatever the packages
11:45
library you install that packages which is inside this node module. Then the public
folder contain all your images
11:52
assets which you want to use from your uh local folders.
11:58
Then we have the next doconfig.ts TS file which contain the configuration related
to your NexJS application. Then
12:05
package.json which contain name version of your application along with the
12:10
script to run your application or to build or to test your application. Some
dependencies along with their version
12:17
and then de dependency with their version as well. At the last we have this
tsconfig.json which contain a
12:23
configuration related to the TypeScript. Now in order to run your application
12:29
simply go to the terminal, click new terminal and then it will open a terminal
inside your VS code only. You
12:37
can even drag this up and it will automatically open a terminal for you. Then
simply run a command npm rundev.
12:44
Click enter. Then it will open a port 3000 on the URL localhost. Right on
12:51
localhost it will open. So simply open that inside your browser. Click on that one.
It will open automatically. And
12:58
then boom. If you see now we have this default page getting rendered on the
13:04
screen. Now if I go to this page.tsx file,
13:10
whatever the content you saw that is rendering on the screen. Now if I delete
everything and just keep the empty div
13:16
and then save it, you will see nothing on the screen. But let's write something. So
here we will say subscribe
13:23
to tube guri YouTube channel. So guys if
13:28
you did not subscribe to our channel please do subscribe. As soon as I save it you
will see the text is rendering on
13:35
the screen. NextJS pro uh support and hard reload. So you don't need to reload
13:41
it manually. As soon as you save and make some changes to your file and save it, it
will automatically update your
13:48
web application inside your browser. Now this is how you can create the NexJS
13:54
application and run it very first time. Now next thing we need to set up an UI
14:01
component library which is based on Telvin CSS called shad CN. Shad CN is a
14:07
popular UI component library in among the developers. So it very easy to
14:13
integrate and it provide a lot of different component as well. Simply go to the
UI.shadcen.com shaden.com.
14:21
Go to the documentation. Select the framework from the installation page. Then this
is the
14:27
command line in order to initialize the shaden inside your project. Simply select
the npm, copy this npm command.
14:36
Then inside the terminal, click add a new terminal and then paste the command.
14:42
Then you can select the base color whichever you want. Click enter and then it will
update the
14:49
CSS variable inside the global CSS. Then uh it will also create some files like
14:56
component.json which contain the configuration related to the shad CN and
15:02
then live folder as well. Inside the global CSS you will see all the variable
15:07
which is added from the shaden. You can change this variable with some different
15:13
colors which we are going to learn in upcoming uh chapters in this video. Now
15:21
let's try to add this button component. Now whenever you want to use any
15:27
component from the shad CN there are bunch of component you have to make sure you
will install that component first
15:33
using the command line. So we'll copy this particular command for the button
component. Simply open a terminal and
15:40
then add this button component. Once the button component is added, you will see
15:46
in the root directory you have brand new folder called components. Inside the
component under the UI com folder, we
15:54
have this button.tsx file. This button.tsx file is added by the shad CN.
16:00
Obviously, you have full control to customize this particular button. It's up to
you. Now if you want to use this
16:06
particular component I'm going to simply add this component button from the
16:12
component/ UI/button and here let's say subscribe and then
16:18
simply save it. Now if I go back to your application make sure you will import
16:23
this button component. Okay. And then save it. Once you save you might see
16:29
this problem. See the button not look good. Right? It happens sometimes. It's
16:35
depends on the us use use case as well or user as well. So simply go to the global
CSS remove this TWW animate CSS
16:43
and then boom if you see now button is perfectly visible inside the browser.
16:48
Now you can put this back and then save it. Obviously nothing will happen. Okay.
16:54
So it may be due to the cashier or due to bug inside the shadian. So that's how you
can fix it.
17:01
So that's how you can um set up the shad cen for your
17:06
application. Now the last thing that we want to update is the font for our
application and it's quite easy. Simply
17:14
we'll go to the app folder. Inside that we have layout.tsx. If you see we have
17:20
default font added. I will remove this font. Make sure to remove this class name as
well. And then whichever font
17:27
you want to use simply you can search it on the Google fonts.
17:33
Go to the Google font browse the font which you want. Okay there are bunch of
different fonts you can use it. In my
17:39
case I want to use the outfit font which is my favorite one. So simply I will use
17:45
this outfit and if you see I I'm getting the suggestion and this outfit form I'm
importing from the next /font/google.
17:53
Now make sure to initialize this font. So over here we'll say constant outfit
17:59
is equal to outfit and then we'll say subset
18:10
and latin. Now this outfit font you need to pass to this body so that it will
18:15
apply throughout the application for each of the page. So we'll say class name and
outfit dot class name and then
18:23
save it. Now if I go back to our application.
18:28
So here make sure it's just a subset okay not a string and then save it. And boom
if you see our
18:36
font is now changed to this outfit font. And now whenever you add any component,
18:42
any text or anything you write on the screen, it will automatically
18:47
uh apply this outfit font. Okay, so that's how you need to uh update the
18:53
font for your application.
Landing Screen
18:58
Now let's add a landing screen for our app. Obviously our main focus is an
19:03
application logic but for any application we need a landing screen so that when
user come to our app he can
19:11
see what this app all about. So in order to add the landing screen we are going to
add the header which we are going to
19:18
add uh simply a logo and the button to sign in and get started and the hero
19:23
section which tell us about our application. So let's go back to our app
19:29
and here we have the page.tsx tsx file. This will be our default screen. So, I will
remove everything from here. Now,
19:35
first thing we need to add an header, right? And then we want to add a hero
19:40
section and then save it. Now, obviously, uh we
19:46
cannot build everything from the scratch. So, in order to get this readym made
component, we are going to use this
19:52
assertinity UI. Asertinity UI is based on the chats here. You don't need to uh
19:59
install or initialize any new components. So simply go to this site, go to the
components and here you will
20:04
find a bunch of different components. See okay. Now whichever you like, you can
just pick that one. For example, you
20:11
want to build this hero section. Just click on this and here we have uh if I
20:16
go to the CLI, this is the readym made component. It will get added to your uh
project or if you see this is the simple
20:22
example that you can directly use is in your project. So now let's copy this npm
20:29
command. Let's use this particular project. We'll go to this terminal and simply
add this. Once you install it
20:36
will install this particular component. Now in order to use it simply go to the
code and here is the hero section and
20:43
also we have the navigation bar which is the header section. So first we'll copy
20:48
this header section. So I will copy this navigation code as it is. Then we'll go
back to our app and inside this app
20:56
folder I'm going to create an underscore components folder. So all the component
21:01
which is shared across the application we can keep inside this underscore component
folder. Now when we create a
21:07
compon or give the component uh folder name start with the underscore thenjs
21:12
will not consider as a route. Inside this we'll create header.tsx
21:17
file. add a default template and then simply paste this code and then save it. Now
if
21:25
you see I just added uh just three four words and then it automatically create
21:31
added the template inside my VS code. That is possible because uh in a VS code
21:37
extension you can just use the React Redux snippet tool extension. Make sure
21:42
to install this and then you can also install the tailwind CSS intellisense
21:48
which help us to write a tailwind CSS classes much faster. Once you have a header
component I will add this header
21:55
component inside this home screen. Once you add go back to your application
22:00
refresh the screen and boom if you see we have this beautiful header section
showing on the screen. Now obviously
22:07
inside the header we are going to rename these things. So here we'll say AI mock
22:13
interview and then you can add a button for login.
22:19
It's up to you how you want to add. Okay. Next thing if I go to the hero
22:24
section we want to add this hero component. So I will copy everything from the hero
component.
22:32
Then go back to your application and inside this component folder I'm going to add
hero
22:40
tsx file. Let's add a default template and simply paste the component which you
22:47
copied. Now uh over here we don't need a navigation bar. So I will remove that.
22:54
Then we need to import this motion. Right? If you don't have this motion installed,
22:59
so I will just see the example, right? So if you see that beautiful animation get
added, right? It's up to you if you
23:06
want to add this motion component. Uh if you don't have simply go just search on
23:11
Google npm motion. So this is the motion
23:16
component we need to add. So I will copy that. Make sure to input that inside the
terminal. So it it will get installed
23:24
and then import that motion. So if I go to the
23:29
code, this is the this is how you can use it.
23:36
Oop. Now make sure that this component on the client side
23:42
once you add it and refresh the screen. Right now nothing is showing on the
23:48
screen because we did not added this hero component inside our uh page. So I will
add this hero component. Now save
23:55
it and go back to your app. And boom. If you see how beautiful our um hero
24:01
section is ready within a few clicks, you just need to copy this uh UI things
24:06
your component and then you can simply import that. For the logo uh we can
24:12
change this logo. So I'm going to use this logo placeholder. You can just simply go
to this untitled.com/lo.
24:19
Here you will find a free logo. Okay, it's a SVG file. So whichever you like, you
can simply copy that. So in my case,
24:27
I'm going to copy uh I'm just searching the best one which
24:32
matches to my um application. So let's use this one.
24:40
Okay. So I will use this logo. Copy that. SVG file. Go to the public folder.
24:47
Inside this, we'll create a logo SVG file and simply
24:52
paste it here. Once you paste inside your header, you can add it. So for
24:58
this, instead of this div, I'm going to add an image tag. From the next/ image,
25:03
provide a source tag. Now here you don't need to provide a complete path. You just
need to provide / logo. SVG and
25:10
NexJS will automatically uh find this particular file inside the public folder.
Give the alt tag as a logo
25:16
inside the wid we'll say 40 height to 40. Save it. And if I go back boom our
25:23
logo is showing on the screen how easy it is. Now just update this content
whichever
25:30
content you see on the screen. Right? So first thing uh inside the hero
25:35
I'm going to update the title. So which is over here.
25:44
So over here I will say master job interviews with AI
25:53
powered practice sessions. Okay. And if I go
25:59
back, boom. Same thing. I'm going to update the description as well. And here
26:05
I will paste that.
26:10
If I go back, this is how it will work. And I think that's all we needed. Okay.
26:17
At the last, we want to update this image. So I already have the demi image that
I'm going to use. So I will copy
26:25
this image inside my public folder.
26:30
And I will rename this to hero.png. And then simply I'm going to replace
26:37
over here. So we'll say hero.png file. And boom. See. So that's how you need to
26:43
update your hero section. And within a five minutes, our hero section or hero
26:48
page is ready. That is our landing screen. Now before moving to the next chapter, I
26:55
wanted to update the default color for our application. The default theme color or
primary color we can say. Currently
27:03
the primary color which is kind of black and we want to update that and simply
27:08
for that one you need to go to the global CSS because all the tailwind CSS
variables uh imported by the shadian is
27:15
moved to the global CSS with the tailwind CSS version 4. over here if you scroll
down you will see this primary
27:22
right and currently they uses this format called okay LCH and obviously you
27:27
don't know the how it works right now obviously if you have the hex code so in
27:32
this case I already have this hex code the question is how to convert in this
particular format simply if you try to
27:38
add something like this some hex code it will not work guys okay
27:43
so this is it will not work so the question is how to do it so simply go to this
okac.com
27:51
and paste this hex code over here. It will give you this relevant uh okles
27:57
format code. Copy that and then paste it here. Once you paste then go back to
28:04
your application. Obviously this button currently uh it's a not a shad cen
28:10
button. So I will go to this header and instead of this one now I'm going to use
28:16
a button component. And here we'll say get started.
28:21
And boom. If you see now our button get changed. Same thing I'm going to update
inside my hero section.
28:30
So if I go to the hero.tsx file where we have the two button called explore
28:36
now. So I will change this button
28:47
something like this. See uh you can provide a size
28:52
large. Perfect. So that's how you need to update it. If you have any question, any
28:58
doubt until this point, let me know in the comment section.
Authentication
29:05
Now it's time to add an authentication into our application. Authentication is very
crucial and
29:10
important part of any application. It help us uh to access your data from
29:16
unauthorized user. Now let's consider that you are on the landing screen. That
landing screen don't need an author
29:22
authentication. Obviously it is publicly accessible. But in order to access the
29:27
dashboard, any API endpoints, database or any pages that need an
29:33
authentication, we need to secure our application and that's where we are going to
use a clerk authentication.
29:40
Clerk provide a complete secure authentication to your NexJS
29:45
application. Obviously it provide a lot of different feature like multiffactor
authentication, SMS uh email password
29:52
authentication, magic link, the social sign on and many others. It is very easy
29:58
to integrate and it secure our complete application by just few line of code.
30:04
Clerk is not only provide an authentication service feature but it also provide an
subscription billing
30:10
feature where you can add a payment gateway within just one line of code
30:15
with the help of clerk billing. You can add this pricing uh subscription model into
your application and that also we
30:22
are going to learn in this particular project. Now simply click the link in the
description about the clerk. Then
30:29
simply sign into your clerk account. If you don't have an account, make sure to
create one. Then once you sign in, you
30:37
will redirect it to a dashboard. If you see, I already have bunch of project I
created with the clerk. Now I will
30:44
create a new project by going to this top. Click create application. Here you
30:50
can enable whichever the sign-in option you want. Give the application name
30:59
and then on the right hand side you will see the preview with the help of clerk UI
component you can easily add this
31:06
beautiful sign-in window as well simply once you select the all the sign-in
31:11
option click create application once the application is created you can select
31:16
the specific framework then you will get this mpm command in
31:22
order To install the clerk HDK into your NexJS application
31:28
inside the terminal, simply paste this command and then it will install the clerk
inside the NexJS. Then follow the
31:36
step-by-step guide in order to add this clerk and let's get started with this
31:41
one. So simply copy this environment variables. Go to your env.local file. So
31:47
if you don't have inside the root directory make sure to create a one.
31:53
So I will paste this. Then once you save you need to create a middleware.ts file.
31:58
Now middleware help users to protect your pages. So you can write all the logic
inside this middleware.
32:05
So I will create a middleware.ts file inside the root directory. Copy all the
content and simply paste it
32:12
here. You don't need to understand for now. Then you need to wrap your application
inside the clerk provider.
32:18
So you can simply go to your layout.ts
32:25
file. So go to the root layout inside here. I will wrap this complete
32:31
uh application inside the clerk provider. Something like this.
32:38
Now it means our application is now secured with the help of clerk. And then go to
the nextjs guide. Now obviously
32:45
that link uh which is in the description make sure to click it so you'll redirect
it to that particular page. Now inside
32:51
here uh you need to create a custom sign in and signup page that is very important
32:57
right. So it your application sign in signup page will be on the your own domain.
So I will copy this complete
33:04
path and then I will go to this app folder. Inside this app folder make sure to
create a new folder called o. Okay.
33:12
So I will keep the sign in and sign up page inside this o folder. Then we'll click
plus sign and paste
33:19
this path. Once you paste this path, it automatically create a sign-in folder as
well along with the file. Then copy this
33:27
content as it is and then paste it. Then you have to add this signin page as
33:34
a public route inside your middleware. So I will copy middleware as it again
33:39
and I will replace with the existing middleware code with the new one. Then you
have to copy this environment
33:45
variables inside your env.local file. And the last you can just run the
33:52
application. But don't forget to add a signup page as well. That is also very
important. So I will copy the sign-in
33:58
page uh route where we want to create this particular page. So I will go to this
34:04
O folder again. So I think we created in wrong folder. So I will move this to O.
Okay. Make sure that
34:11
I will select the O again. I'll paste this uh path then copy the content paste it
34:18
here save it update your middleware by adding this line inside your public route
now inside the middleware we are
34:25
telling that okay these two are the public route okay and you don't need
34:31
authentication for that one and that's what the logic is written under this
middleware
34:36
after adding this you need to add an environment variables as well so I will add
that inside the envlo local file and
34:43
now I will reload our application. Now obviously if you see on the local
34:50
3000 as well it asking me to sign in but we want this particular page or a home
screen or default landing screen uh to
34:59
be a public and you don't want to add authentication for that one. So inside the
public route you can simply add
35:05
slash it means you don't uh it is a public route and don't need an authentication.
Now if I go to the local
35:11
3000 say I can able to access without any authentication but consider that you
35:16
have a route called dashboard and you want to access that. If I click enter
obviously it asking me to sign in
35:21
because that dashboard route is uh is completely protected by the clerk
authentication. How cool it is right
35:29
this is how easily you can protect your all the routes now let's bring this
particular UI component in the center of
35:36
the screen. So I will go back over here go to the o sign in page
35:43
and I'm going simply add a div inside the div I will add this sign in component I
will make it flex item to be
35:51
in the center justify content center and we'll give height to screen
35:57
over here if you see now it's coming in the center of the screen same thing I'm
going to do so let me close this
36:03
terminal for the signup sign up screen. So I will remove this. We'll add a div
36:13
and then add a sign up over here. We'll make it flex item to be in the center.
36:18
Justify contain the center and height to the screen. And then your signup page is
also now
36:25
ready. You can go to the signup by clicking this signup button. Perfect. Right. I
think we need to add
36:31
justify center. Make sure it's side to be screen and then boom. Okay. So that's how
you can
36:38
add authentication. Now you have option to sign in with the email password or you
can sign in with the Google as well.
36:44
Now before that on the homepage make sure when you user click on get started
36:50
you'll redirect it to the dashboard page and obviously if user is not logged in
then it will ask us to sign in. So I
36:57
will go to the header where we have this button. Now we cannot wrap this button
inside the link tag with the H reference
37:05
and we'll just say dashboard. Currently we don't have the dashboard route. We'll
create one later on. But for now just
37:12
create this add this link with the H reference. And same thing I'm going to add
inside the hero when user click on
37:20
explore
37:26
and make sure to import this link from the next slide uh link. Now obviously
37:32
it's act like a anchor tag only but it is optimized for the nextjs application.
37:38
Now if I click on get started see it ask me to login first then select the
37:44
account. Once you select the account then you can able to access the dashboard
page. Currently we don't have
37:49
dashboard page. So it might give us the 404 error. See but once we created the
37:55
dashboard page then you don't need to do anything. So that's how guys you need to
add an authentication into our app.
38:01
Later on we are going to also learn how easily we can add the payment gateway the
pricing subscription model with the
38:08
help of clerk.
Database Setup
38:14
Now it's time to set up a database for our application where all our application
data we are going to store
38:20
under that particular database and for that one we are going to use a convex
opensource database. Convex is not just
38:28
a database but it provide you a realtime updates. It's a type safety and available
for a number of different
38:35
framework as well with the help of automatic catching feature. Convex uh
38:40
database is quite faster than any other database as well. Along with that one,
38:45
convex also provide a file storage feature where you can store images, files also
with the help of chrome job,
38:53
you can run a background uh scheduleuler or background job or it also have the
39:00
server function so that you don't need a dedicated server. If you want to use
convex everything is bundle under the
39:08
one particular database called convex database. I am I use this convex in many
39:15
of my projects and I love it. And today we are going to use convex into our app.
39:21
In order to get started with the convex, click the link in the description and uh
39:26
obviously it's free to use. So you don't need to pay uh in order to develop your
application. Simply create an account on
39:33
a convex. And once you create the account you will jump onto the dashboard. If you
see I already have
39:40
bunch of different project running on a convex over here. Simply create a new
39:45
project and give the project name. So I will say AI mock interview app and
39:52
then say create. Once you create the project you will see at the top currently you
are in the development
39:59
mode. But later on once we deploy our application and finishes you can even switch
it to the production in just one
40:06
click. On the left hand side you will see some option. The one is to create a
40:11
new table. Under the health you will find uh which API or a database called
40:17
fail. Everything you will find over here. Under the function you will see all your
serverless functions file in
40:24
order to store your files and data and all other information you will find on the
convex.
40:31
Now the first thing we are going to integrate convex to our app. So click the link
in the description so that you
40:37
will jump onto this convex neckjs quick start guide where we need to install the
40:43
convex hdk. So this is the command line in order to install inside your neckjs
project. So copy it. Go back to your
40:50
application inside here inside the terminal. I will just paste it. So it will
install the
40:56
convex for us. Next, copy this command in order to run the convex in a
41:02
development mode. So I will run this command. Now it will uh ask do you want
41:07
to select create a new project or do you want to choose existing project. Now we
already created a project through the
41:13
dashboard. So we'll say choose existing project and then I will search for the AI
mo interview or mock interview app
41:22
2.0. Once you select it will start convex function locally. Once you run
41:28
this command you will see new folder get added called convex inside your root
directory. Inside here
41:35
there are sever several files and uh uh folders. Okay. So you don't need to
41:41
touch to any of this one. Also inside the env.local file you will see the
41:48
convex development uh key and the URL is added. Okay. That is only uh helpful or
41:54
applicable in a development mode. Okay. Now once you add all of these things you
42:00
need to wrap your application inside the convex provider. You don't need to worry
42:06
about this one because we are creating the brand new table and everything from the
scratch. So simply uh create a new
42:14
provider called convex client provider. And inside that you need to wrap your
application.
42:20
So let's go to this app folder. Inside this we'll create a new file called
42:26
convexclient provider.tsx. Inside this I will copy all of this
42:31
content as it is and we'll paste it here. Okay. And then save it.
42:38
After that, I think that's all we needed. Okay. So, I will go back and over here
instead of
42:46
importing that convex client provider uh directly inside the
42:52
layout.tsx file, we can go to the layout and then we'll wrap this children inside
42:58
this convex client provider.
43:04
Now make sure go to your app and you will not see any changes. Next thing
43:10
we'll create another file called provider.tsx
43:16
and then add a default template. Now this provider will helpful uh you will
43:21
learn later on but for now make sure to add this provider.tsx. through this we'll
render the children
43:31
and then this provider we're going to use it inside the convex client provider
43:37
so I will wrap this children inside our provider
43:43
something like this and I will also make sure that this provider is on also on the
client side
43:49
so most important thing we kept this layout on the server side and this provider on
the client hand side.
43:57
Next, that's all we needed. Now, it's time to create a schema. Means we need
44:02
to create a table inside our convex database. So, I will go to the convex folder.
44:08
Inside this, we'll create a new file called schema.tsx
44:15
or we'll say ts only. And inside here we'll simply say export default
44:24
define schema. Now inside the define schema we'll create a new table called user
table and
44:32
we'll say define table. Once you define the table you can provide the column and
44:37
their type. Now make sure that define schema and define table are you are importing
from the convex server. Then
44:44
over here we'll say name the V which is the value. Make sure to input this convex
value and then it contains the
44:53
type. Here we'll say image URL of that particular user. So we'll
45:00
say V of type string. then the email
45:11
and then uh I think that's all we needed for now and then save it. Once you save,
45:18
make sure inside your terminal you don't have any error while running the convex.
Here it's saying the convex function is
45:25
ready. Now as soon as you save this one, let's go back to your convex dashboard
45:31
and over here you will see a brand new table automatically added because we created
the schema file which is sync to
45:38
this particular development server. Now over here obviously you will not see any
record because we don't have any record
45:44
but when you I click add document you will see these three fields which you can
addit and that's will be already
45:50
added. Now you don't need a unique ID or created by column because convex will
45:56
automatically add a unique um identification record number to each of
46:01
the record. So you don't need to worry about that. Okay. So that's how you need
46:06
to create a tables inside the convex. Now the next thing whenever user log
46:12
into our application we need to save the user information and for that one we can
46:17
create a convex function which is a server uh list function. Okay. So simply go to
the convex here we'll say
46:26
users.ts TS and inside this all related data
46:33
users database related functionality like inserting record fetching the record
everything we can define inside
46:39
the user. So simply over here we'll say constant export first export constant
46:47
create new user is equal to mutation as
46:52
whenever you want to insert a record update a record or delete a record you can use
mutation but when you want to
46:58
fetch the record then you can use a query. Now this mutation you need to import
from the generated server inside
47:05
this will provide an argument. this argument whichever the argument you want to
fetch it or pass it to this
47:11
particular um function you can define over here. So for example name provide a
47:17
type make sure to input this v dot string then email
47:24
and then the image URL.
47:30
After this you need to provide an handler. Handler contains actual logic.
47:35
So here is a sync. It takes two argument. One is ctx and then uh second
47:41
is arguments and then arrow function. Then over here first thing we need to
47:47
check if user already exist. Okay. And second if not then insert new
47:57
user to database. Okay. So whenever uh user log into our application we need to
48:04
first check if it already exist or not and depends on that one we need need to take
an action. So over here we'll say
48:10
constant users is equal to await ctx dot db dot
48:20
query and then you need to provide a table name which is user table dot
48:30
filter and then inside this filter you need to add equal to or you can say Q
48:37
dot Q dot equal to and then you need to write q dot
48:43
fill give the field name which is email and compare that with the arguments do
email once you have that
48:51
make sure to collect means you have to select everything okay
48:56
so over here we say collect now once you have all the user you can
49:03
simply check the logic over here so we'll say if user users
49:10
or user do.length is equal to equal to zero. It means no user found with that
49:15
particular email. Then you can simply insert a record. So we'll say user result is
equal to await
49:26
ctx dot db dot insert. give the table name which is user table dot
49:36
or inside that only you need to provide the values. So if you see we need to
provide an email from the arguments do
49:42
email then the image URL again that is we'll get it from the argument dot image
49:48
URL and the name that is also we can get it from the argument dot name okay and
49:55
then over here we'll say con I think we don't need to do anything but over here
50:01
you can simply keep all the data inside this data field okay and over
50:08
Here we'll say dot dot dot data. Perfect. We'll just simplify it because
50:13
we want to return and the last. So here we'll say return all the data and then
50:19
result as well. So we'll say underscore id as result dot
50:29
or result dot ID I believe or maybe uh for now we
50:35
will just hold it. We will see we'll check the result what is the result we are
getting over here. Okay. And if user
50:42
is if you already have the user then you can say that user information. Now make
50:48
sure you will return the first user every time because with that email we'll
50:53
only get one user. Okay. And then save it. And this is how the create new user
50:58
convex function is ready. Now in order to create a new user go to the provider
51:05
over here. First you need to define this particular convex mutation. So we'll say
constant create user is equal to use
51:14
mutation. This is the react convex hook. And this use mutation we are going to
51:20
use. To this use mutation you need to provide which API you want to use. So we'll
say API. Make sure to import from
51:27
the convex generator API dot users dot create new user. Now we'll create a new
51:34
method called constant create new user. Inside this method we going to call this
mutation. So we say constant result is
51:42
equal to await create new create user and then you need
51:49
to provide an argument inside this. Now you need to provide email. Then you need
51:54
to provide an image URL and then the last the name. Now all of these three
52:00
value we can get it from the clerk use user hook. Okay. So before that I will
52:07
mark this as a async. Now over here we say constant. Get all the user information.
So login you can get all of
52:14
this login information from this use user hook which is importing which we are
importing from the clerk neck.js. JS
52:22
and then if you want to get user email just say user dot primary email address
52:27
dot email address for the image URL we'll say user dot
52:32
image URL and for the name we'll say user dot full
52:39
name. Now make sure this particular method we only run whenever we have the
52:44
user information.
52:49
Now if it's empty I will just put something like this. Okay. So if full
52:54
name is not there it will save it as empty. So just just to ignore this warning.
Next this particular method we
53:00
need to call whenever the user information is available. So we'll use the use
effect. Whenever this component
53:06
get load this use effect will get execute only once. But whenever the user
information is available we want to
53:12
execute this use effect. So that's the reason I pass this user. Then over here
53:17
we'll say user and and create new user method because we want
53:24
to call this method. Okay. And then at the last I'm going to save the
53:32
result. Now under this user for now when we
53:37
insert a new record I also going to return the result.
53:49
Oh not here uh over here
53:57
or just pass result like this. Don't uh add a spread operator. Then inside the
54:02
provider we are consoling the result. Now let's go back to your application. I
54:07
will open the inspect panel. Go to the console. Right now we don't have anything.
So let refresh the screen.
54:15
And obviously we are not getting anything. But if I go to the convex db
54:21
let's refresh this one. Still we don't have any u record added. There is a
54:28
small mistake over here. So if you see this provider name is started with the P and
our component name is also started
54:35
with the P. Maybe inside the convease client provider the import statement is
incorrect. Okay. So I will remove that
54:41
and I will add it again. So I don't know why it's not taking
54:47
capital P. But if I save this one and now if you see we got the data inside
54:52
this data we have image email every all the details right and not only that but
54:58
if I go to the convex database here you will see a brand new record get inserted
55:04
inside this user table where we have a user email image URL name along with
55:09
that one the unique convex ID get attached to each of this record which is
55:14
quite helpful when you want to connect the multiple table together. Okay, so that's
how you need to uh create a
55:22
convex database, integrate with your application and create a convex function in
order to connect the your app and a
55:30
database and they so that they can communicate with each other. Now next what
whichever information we geted from
55:37
the uh convex function right the user unique ID along with the user
55:43
information like name email we want to share that across the application
55:48
so that whenever you want to add any record inside the database you can refer that
users ID and for that one we are
55:57
going to use a context so simply uh we'll create a new folder called context
56:03
inside the root directory and inside that we'll keep all our context. So here we'll
say user
56:09
detail context dot tsx. Simply we'll say export constant
56:17
user detail context is equal to create context. Make sure
56:23
you are importing from the react. Uh I will provide a type any and here
56:29
I'll provide it as a null. Now context is very powerful react hook or is a
56:35
state management uh hook which uh you can use it to share your data across the
56:42
different different components. You don't need to pass from one component to other.
Once you define wrap your
56:47
application inside the context provider you can share it across the application.
And let me show you how to do it. So
56:54
simply once you define this context go to the provider and inside the provider wrap
your children under that user
57:02
detail context. So here we'll say user detail context dot provider. To this
provider you need to define default
57:09
value and then over here pass the default
57:16
state. So I will just define that at the top. So here we'll say user detail comma
57:22
set user detail is equal to use state
57:29
and then I will pass it over here. So we'll say user detail comma set user detail
and
57:36
then save it. Now whenever you get this result simply set the user detail with
57:42
the result. You can define a type any here
57:50
and then save it. Now in any component whenever you want to use this user
57:55
detail or want to update uh user detail information you can simply do it with the
help of that context. Now you can
58:03
simply uh in order to avoid a long length creating um defining the context I will
say export
58:10
constant use user detail
58:15
context is equal to arrow function and I going to simply return
58:23
create context and inside this uh you can provide a
58:29
context name. So we'll say user detail context. So from next time I'm going to show
you how easily we can access this
58:35
one. Okay. But for now make sure to implement this context and add your user detail
information so that you can
58:42
access it later on.
Dashboard Layout
58:47
Now let's create a dashboard layout. So as per this mockup we are going to
58:53
create first the new screen called dashboard. On the dashboard we have to make sure
on the header section we are
59:00
going to add three menu option. One is dashboard upgrade and how it works. Now
59:06
on the dashboard when user don't have any interview created at that time we
59:11
are going to show this empty state which uh on which user can uh create a new
59:17
interview on the click of this create button. Okay. And once user created the
59:22
interview then we are going to show that uh card so that he can come and access any
time. But for now this is the empty
59:29
state and very first time when user come to this dashboard this is how it will look
like. So first thing first we'll go
59:36
back to our application and inside this app folder we are going to create routes
folder. Inside this routes we going to
59:44
keep all our um routes. Okay. So under the one folder
59:49
we can keep it. Inside this we'll create a dashboard and in under that we'll
59:54
create a page tsx file. Let's add a default template
1:00:00
and we'll rename this to dashboard and then save it. Now if I go to
1:00:08
local 3000/ dashboard I can able to access that dashboard. See? Okay.
1:00:14
Perfect. So that's how it works. Second thing, we need a dedicated header to the
1:00:20
dashboard. Right? So, um we are going to add a routes
1:00:26
under this routes folder which uh obviously we are going to add a
1:00:31
layout inside the routes folder and that particular layout is only applicable to
the all the routes which come under this
1:00:39
uh routes folder. Okay. So, we'll create a layout.tsx tsx
1:00:45
and I will add a default template here. I will name it as a dashboard layout.
1:00:51
Make sure to render this children. Okay. So you can give type any doesn't matter.
1:00:58
And over here we'll say children. Perfect. Now on this screen if I go to
1:01:04
the local host 3000/ dashboard you will not see any change. But for this particular
routes we need to create a
1:01:10
dedicated header. So we'll create underscore components under this routes. So all
the component which is uh shared
1:01:18
across these particular routes we're going to keep inside this component folder.
Inside here we are going to add
1:01:26
app header dot tsx file. Let's add a default template and then save it.
1:01:34
Now simply copy the content from the header as it is. So I will copy this now. I
will paste it here. But make sure
1:01:42
to import this image and we don't want this button. So instead of this we are
1:01:48
going to add one div and then we want to add user button. Now this user button
1:01:54
component is from the um clerk. Okay. Once you add this and then you have to
1:02:00
add this app header inside your root layout because we want this header throughout
the application except the
1:02:06
home screen. So whatever the routes we added under this route folder for that route
we want this app header. So we'll
1:02:14
add this save it and boom see now on this one if you see with the help of
1:02:20
this clerk component we got this beautiful drop-down to manage the user's
1:02:25
profile account. Next thing we want to add some option. So inside the app
1:02:31
header we'll define some option. So here we'll say menu option
1:02:38
here we'll say name we'll say dashboard and then we'll also define a path let's
1:02:46
say dashboard then second and then third for second
1:02:51
we'll say upgrade and here we'll say how it works
1:03:00
and for upgrade I will say upgrade only okay and save it Now this option we need
1:03:06
to iterate. So I will add a ul tag. Inside this we'll say menu options
1:03:14
dot map option, index and the arrow function. Over here we'll add l tag and
1:03:21
simply add option dot name. Over here we add we'll just okay let's
1:03:28
keep it as it is for now. Save it and let's see whether we are getting this option
in. If you see we have these
1:03:35
three option. Now for this UL tag we'll make it flex and give cap to five. So it
1:03:40
will be in one line also. I will uh just hide this logo. I
1:03:48
will just keep this uh SVG file only. And then we have this beautiful options.
1:03:53
For this option I will make the text larger on hover.
1:04:00
We'll increase the or we'll just scale this to 105. And for smooth animation
1:04:06
we'll say transition all or transition all.
1:04:14
And if you see on hover it change beautifully. Make sure you will add the
1:04:20
cursor pointer. So whenever we hover the pointer get changed. Perfect. Next thing
after
1:04:29
updating the header we'll go back to our dashboard screen and on this dashboard
1:04:34
screen first we'll give some margin and padding. So we'll say padding Y to let's
1:04:40
say 20 padding X to 10. Depends on the screen size we going to update the padding.
When the p medium screen size
1:04:46
we have we will apply padding 28 and on larger screen we can apply padding to 44
1:04:52
and extra large we can apply padding let's say 56. And once you apply this is
1:04:57
how it look like. Then just bring this down over here. We'll
1:05:05
add an H2 tag and we'll say my dashboard.
1:05:12
Then we'll add one more text over here. We'll say
1:05:18
welcome and we want to give the username. Now in order to get the username you can
use the use user hook
1:05:25
from the clerk. If you are using the hook on the client side so obviously you need
to mark this particular component
1:05:31
on the client side and here we can add username. So we'll say user dot
1:05:38
uh full name and then save it. See now obviously we'll increase the size. So
1:05:44
here we'll say text larger and then I will make this text gray 500. For this
1:05:50
welcome we'll say text 3 XL and then save it. I will also increase the font
1:05:57
bold. Perfect. On the right hand side we want want to add a button in order to
create
1:06:04
a new interview. So that will be the dedicated button right? So whenever you want
to create a button you can simply
1:06:10
add it. So we'll add a button component over here. I will say create
1:06:16
interview and we want button on the right hand side also you can change the size to
1:06:23
large or you can keep as it is. Uh then we
1:06:30
want to bring everything in one line. So I will again wrap this both the div and
1:06:36
the button in a another div so that we can mark this as a flex justify between
1:06:42
and then item to be in the center. See so that's how we have to do it. Now
1:06:49
let's add an empty state something like this. So for that one
1:06:54
uh you can create an empty state.tsx as a separate component
1:07:01
and simply add this component over here. Now this component can be visible if user
don't have any interview created.
1:07:08
So over here I will create a state called interview list, set interview list is
equal to use state
1:07:17
and and initially it will be just empty. Now over here we'll say if interview
1:07:24
list is uh is equal to or we can say.length
1:07:29
length is equal to equal to zero then we can simply show empty state.
1:07:38
Now go to the empty state but in meantime if you check we are getting this empty
state. Okay. Now inside the
1:07:44
empty state we'll give a margin top to let's say uh 14. Then we want to add an
1:07:51
image from the local. So I already added one image inside the public folder
1:07:57
called interview.png. Okay, I will share these assets with you for a free. I will
1:08:02
keep the link in the description so you can go ahead and check it out. Um, then in
alt tag we can add as a
1:08:11
empty state. Then for the source I will say interview dot PNG.
1:08:21
Then give some specific width. So for width I will say 100, height 200. Save
1:08:27
it and make sure it's rendering on the screen. See? Perfect.
1:08:32
I will just increase this size. Let's say 130. Okay. After that, we want to
1:08:38
add a text. And here we can say I will just copy from this documentation. You
1:08:44
can also get this uh access to this documentation. I will put the link in the
description.
1:08:52
So margin top to two text larger and I will also make text gray to 500.
1:09:00
Okay. Um I think we can make text larger. Okay. Yeah. And then we want to
1:09:07
add a button as well. I will say create
1:09:17
interview. Now let's bring everything in one line. So we'll say flex flex column
1:09:22
and then item in the center. Perfect. Also give gap to let's say five.
1:09:29
And then we want to add a border to it. So add a border. We want a dash border. So
make sure to add also give padding.
1:09:36
So let's say 10. And you can give border. Let's say some border width as
1:09:42
well. Okay. I think we can give more width.
1:09:47
Let's see how it looks. I think that's pretty good. And then you can round it
1:09:52
the corner. Perfect. If you want you can uh add some color. So I will say
1:09:59
background gray 250. And that's how uh our empty state the
1:10:05
dashboard layout is ready. As simple as that. No complication. Whenever user come
to our app uh he feel simple and
1:10:13
clean and easy to uh play around it.
Upload Resume & Job Description
1:10:20
Now once user click on this create button we want to open a dialogue in
1:10:26
which we are going to add a two option. One user have option to upload the resume
and with the help of resume our
1:10:33
AI will generate the questions and then the interview will start or user even
1:10:39
can upload the job description by entering the job title description and the years.
Obviously on the dialogue we
1:10:47
are going to add a shadian tab navigation. So depends on whether user want to
upload the resume file or want
1:10:54
to enter job description. You can choose between them and on the click of submit
then our AI model will generate the
1:11:01
question. That workflow we'll implement later on but for now we'll implement this
dialogue with these two different
1:11:08
components. So we'll go back to our application and inside this
1:11:15
inside our route where we have this dashboard along with the empty state.
1:11:21
Now on this empty state we have this button called create interview. Right. So
under this component we are going to
1:11:28
create create interview dialogue dot tsx
1:11:34
file. Now we'll add a default template and then save it. Now we want to use a
1:11:39
dialogue. So we'll go to the shad scen and search for the dialog component.
1:11:45
Now if I click on this one, this is how it will it works and that's what we wanted.
So I will copy this npm package
1:11:54
inside the new terminal. Paste it so that it will install. In meantime, I
1:11:59
will go back to our uh this chart documentation. copy this import statement
1:12:06
and simply paste it here.
1:12:12
Then we'll copy this dialogue as well or such the simple use case and then that
1:12:17
also we'll paste it here. And this is our dialogue now is ready. Now simply we
1:12:25
are going to move u this create dialogue button. So I will
1:12:31
remove it from here and I will put it inside this dialogue trigger. Now this dialog
trigger actually help us to open
1:12:37
the actual dialogue. So make sure to import this button and then we'll simply copy
this create interview dialogue and
1:12:44
then I will paste it here. Something like this. Okay. And then save both this
1:12:49
file. Once you save we'll go back. And if I click on this create interview, see the
dialogue open. How cool right? So
1:12:56
that's what we wanted. Next, same thing you have to implement for this button as
well.
1:13:03
So I will just go to this page.tsx file where we have this button. I will remove
1:13:09
this button and instead of that I will add create interview dialogue. So when I
1:13:14
click on this one, it will open that dialogue. Now let's implement the dialogue
content. So we'll go to this create interview dialogue. Inside this
1:13:22
we have the header and for the title I will just say please
1:13:29
submit following
1:13:34
details and then inside the description we want to add the file upload activity but
1:13:42
before that we have to make sure that we want to show both the content right. So
1:13:47
in order to switch from one uh section to other we are going to use a shadian
1:13:53
tab components. Now this tab component is quite easy. See and how cool it is.
1:13:59
So that's what we want. So I will copy this u npm package in order to install
1:14:05
and once it install you can copy this import statement.
1:14:12
Oop copy. Let's copy it again. And then we'll paste it here. And then copy this
1:14:19
example as well. And then paste this. Oh, sorry. We'll
1:14:26
copy this again. And we'll paste it here. And then save it. Now just wanted to show
how it looks for now. So if I
1:14:32
click on this one, you will see this tab. Perfect. Now uh we'll uh update
1:14:38
this name. So here we'll say resume upload. and then
1:14:45
job description. Now for this trigger, obviously this
1:14:50
trigger is very helpful in order to navigate between these components. So I will
just say resume upload and here
1:14:58
we'll say job description. Now by default
1:15:05
uh the when you open the dialogue the resume upload tab will be active and
1:15:11
over here whenever the resume upload is there it will show this content. So what
whatever you put inside this tab content
1:15:18
it will show and same thing I have to do it for this job description and then save
it. Now if you see we have the two
1:15:24
different uh tabs with the resume upload and the job description. uh you if you
mention it as a full
1:15:32
that's also fine and u I will also give margin top to let's say five okay now
1:15:41
for both the both of these particular section we are going to create a separate
component so under this
1:15:46
component we'll say resume upload tsx let's add a default template and we'll
1:15:53
create another component for job description tsx text and add a default
1:16:00
template for that one too. Once you add, make sure to import this component inside
the create interview dialogue for
1:16:08
this tab content. So this tab is for the resume upload. So we say resume upload
component and this one is a job
1:16:16
description. Now make sure it's working. See the job
1:16:21
description and then resume upload. Now also for the dialog content uh we
1:16:28
can increase the size of the dialogue. So in order to change the width so I will
provide a class name to this dialog
1:16:34
content and then just provide a minimum width let's say 4 excel and if I change
1:16:40
this one let's open this and that's how it looks. See I think we can make it to
let's say 3 excel. I think this is much
1:16:47
better. Now for the resume upload we need uh an option to upload the file
1:16:53
right and we want to allow only a PDF file. Now for that one I'm going to use
1:17:00
an assertinity uh UI component called file upload and you can just search it
1:17:05
under the components and this is how it looks. On the click of that it will open a
file explorer from where you can
1:17:12
select the file. Now in order to add it into your application, go to the CLA, copy
this command, npm command, and then
1:17:20
make sure to install. Once you install this command, you can simply use it. So this
is the code for
1:17:27
that one. And I will copy this div inside the resume upload. Let's paste it
1:17:34
here. And make sure to import this upload.
1:17:43
or better you can just copy paste it.
1:17:50
Now let's define this handle file upload. So that logic is already there. So I will
just copy that and we'll paste
1:17:56
it here. I bring this down and make sure to import the use state as we are using a
1:18:02
react hook. So I will make this as a client the use client. And now if I go
1:18:08
back here we have this beautiful upload uh section. Cool. Right now make sure to
1:18:16
provide um cancel and submit button. So you can provide it to the dialogue
1:18:22
only. So inside the dialogue content maybe in out of uh let's put it inside
1:18:29
dialog content here you can provide a dialogue uh footer as well. And to this
1:18:34
footer you can say dialogue close button
1:18:39
and one button I will say for a cancel.
1:18:46
If I go back you will see this cancel button I will put a variant as
1:18:53
ghost something like this. And we want one more button
1:19:00
which is called a submit.
1:19:06
and save it. See uh over here I will say class name flex gap to six. So some
1:19:12
space between these two buttons. Okay. Now we'll go back to this resume upload.
Make sure uh I'm going to add some
1:19:19
border. So over here we'll say a border and we'll make a rounded to 2 excel.
1:19:28
I think it's very light border is already there. So I will remove that. The rounded
is also there but it's light
1:19:35
so you can just change the color if you want but it's there. Okay. Now on the click
of it you have to make sure it
1:19:42
will only accept the PDF file and in order to do that simply we have to go to
1:19:48
this file upload. Under this file upload component obviously that this component is
um inserted by the asset UI here.
1:19:57
Search for the input. So I will just search input this one and for this one
1:20:04
here you need to add an accept field and which will only accept the PDF. So we'll
1:20:10
say application / PDF. Now if I go over here if you see everything is disabled
1:20:16
except the PDF. Right now I don't know whether I have the PDF and if you see I have
this PDF. If I click open you will
1:20:23
see that selected PDF file. And on the click of this submit button first we
1:20:28
want to store this PDF file at some location and then from that URL we are
1:20:34
going to uh fetch all the content of that PDF. That one I'm going to explain how
step by step we are going to
1:20:41
implement it but for now I hope this I I hope you understand this particular
scenario. Now second let's implement the
1:20:49
job description section. Uh it's quite straightforward. So, we'll go back
1:20:54
to this job description component. Over here, we'll add a label and we'll
1:21:02
say job title. To this job title, obviously, we want to
1:21:08
add an input field. So, for that one, I will I'm going to use a shadian input
1:21:13
component. Just search the input. Make sure to install that.
1:21:21
And then once it install you can add this input field here. You can add a
placeholder example
1:21:28
like full stack um react developer something like this.
1:21:35
Okay. Uh next maybe you can wrap this in a div tag that will be good.
1:21:46
So I will just copy this. Here we need a job description. Now for
1:21:52
the job description is better you can use a text area that also you can easily
1:21:57
uh use it from the shaden component. So I will copy this text area npm
1:22:04
package so that we can install that and then we'll add a text
1:22:09
area inside the placeholder. So you can say enter
1:22:16
enter or paste
1:22:22
job description. Okay, something like this. And I think
1:22:27
that's more than enough because in job description you also have the experience
level, right? So you don't need to
1:22:32
mention everything. Let's save this one. Go back to your application. And this is
how it look like. Uh I think pretty
1:22:40
good. I will just give a margin. So here we'll say margin top to six
1:22:46
and um I think let's add some border to this one. So we'll add a border. We'll make
rounded excel padding to 10.
1:22:57
And I think you can also add a minimum not minimum. Yeah, let's add minimum
1:23:05
height to let's say 200 pixel. I don't know whether it will
1:23:11
work or not. Or let's add directly the height only.
1:23:17
Oh, that I I was adding in placeholder. So, let's add it inside the class name.
1:23:26
I think this is much better. See, now after adding this information,
1:23:32
obviously user will enter the details and on the click of submit, we have to u
1:23:37
pass it to the AI model. Now, make sure you'll accept this value. So, over on this
section, let's accept that first.
1:23:44
So we'll say job title or instead of mentioning over here
1:23:53
uh you can handle directly inside this create interview dialogue. So inside
1:23:59
that I'm going to write constant on handle input
1:24:04
change. Now this will take two value. One is the fill of type string and then value
is of
1:24:12
type string again. Okay. And we'll define
1:24:17
constant job or we'll say form data comma set
1:24:23
form data is equal to use state.
1:24:29
Now whenever we'll get the data we'll say set form data which is equal to previous
value and then we'll say dot
1:24:37
dot dot previous value and then fill and their respective value.
1:24:46
So over here right now I'm going to add a type any and here as well let's give a
1:24:51
type any but later on we'll update that type as well. Okay and then save it. Now
1:24:57
this on handle input change I'm going to attach first to the job description. So
here we'll say on handle input change to
1:25:04
this on handle input change. Go to the job description. Make sure to pass this on
handle input change
1:25:12
with a type any. And then whenever there is change in the input so we'll say on
1:25:19
change obviously it will emit the event and then we'll say we'll just say on handle
1:25:26
input change we'll call this method make sure in this one um we'll pass a field
1:25:31
name the field name will be the job title and then the value the value you will get
it from the event
1:25:38
dot target do value. So whichever user entered that value will be inside this
event.target target dot value. Same
1:25:45
thing you have to do it for the text for the text area.
1:25:50
So over here we'll say job description. Okay. And then save it. So that's how
1:25:58
you have to implement it. Now for the resume upload is little bit different because
this is a file, right? And on
1:26:04
submit we just need to get the uploaded file.
n8n AI Automation to Generate Interview Questions
1:26:12
Now once user upload the file obviously we need to generate the interview questions
and that's where there are
1:26:19
there is a small work application workflow that we need to implement in order to
generate the interview question
1:26:25
depends on the user resume. Now let's uh focus on this workflow where first thing
1:26:32
user will upload that PDF file to the cloud storage and for that one we are going
to use an image kit because it
1:26:38
provide a free cloud storage and very easy to integrate as well. Once we
1:26:43
uploaded the file it will generate the unique file URL that URL we are going to
pass to this N8 workflow model.
1:26:51
Obviously in this particular project we are going to use this uh nate automation
1:26:57
tool in which we are going to implement all our application flow so that it will
1:27:03
be very easy uh to generate the specific output. You don't need to write the
1:27:08
bunch of code within just drag and drop. It will generate the complete workflow
1:27:14
for us. Now obviously first thing we will set up the web hook uh so that we can use
that web hook to make an call to
1:27:21
execute this particular request. To this web hook we are going to pass the htt
1:27:26
http request in order to fetch the file data whichever the file we updated or
1:27:31
uploaded to the cloud storage and then we need to extract that uh text from that
file data. That is very important.
1:27:38
That particular text we are going to send it to the AI model along with our system
prompt. Now you can use any AI
1:27:45
model like chat GPT Gemini there are bunch of others as well you can use anything
okay and at the last once we
1:27:53
get the result we'll return that result to that web hook response and then at the
last we will save that to our
1:27:59
database as simple as that right now if you try to write a logic uh inside the
1:28:05
reactjs uh code it will be very complicated you have to implement each
1:28:11
of these particular functionality in order to get the result. But with the N8
automation workflow, it will be very
1:28:17
easy. Now, if you don't know what is the NATE, it is an AI workflow automation
1:28:22
and it's very uh popular currently. So, you can do a lot of automation, you can
1:28:29
run complicated workflow as well. So, this is the official website, but the problem
1:28:35
here is it is not a paid even though it's open source. So either you have to use
the cloud service like in this case
1:28:42
it's $20 and that's too much right otherwise you have to run locally
1:28:49
but once your application in the production obviously you need to deploy it
somewhere right and you have to pay
1:28:54
the charge for it the most and best solution for that one is an hostinger
1:29:00
hostinger is a self-hosted platform where you can um deploy any AI workflow
1:29:07
everything is already set up. You just need to trigger it in order to start working
on the hosting. The plan is
1:29:14
started just under $5. So you can choose whichever you feel it's a best and trust
1:29:20
me no one is providing this chip this particular service also along with this
1:29:26
inate workflow hostinger also provide a lot of different services like a domain
1:29:32
uh then you can also buy the shared hosting cloud storage uh cloud hosting
1:29:37
as well VPS and many other within very couple of bucks and then you can deploy
1:29:43
and start building your own SAS applications and start earning money. So
1:29:48
go ahead, click the link in the description so that you will jump onto this
hostinger and you can buy the NA
1:29:54
platform. But if you don't want to spend any money while you are in the
development, then also we're going to
1:30:00
learn how we can set up N8 locally for a free. Okay, but first thing let's set up
1:30:06
on the hostinger and then we'll see how can we set up on on your local machine. So
first thing we'll click the link in
1:30:13
the description you will jump onto this hostinger. Go to the application. Uh once
you are on this hosting just log
1:30:21
to the dashboard once you are on the hostinger if you see my uh internet is already
running. Okay but uh you can
1:30:29
select your VPS hosting click setup. Select the nearest location uh to you.
1:30:34
So in my case it's United State. Click continue. So I think I missed previous step
and
1:30:41
here uh on the OS template just search N8. Okay, once you search you will find
1:30:47
different option. Select this basic option that is enough for you. You don't need
an readym made workflow. Once you
1:30:53
select select the Mar scanner is completely optional thing. Go to the next step.
Enter the password. You can
1:31:00
enter the VPS host name. It's already there obviously and then click continue.
1:31:07
Oops. And then once you click continue it will
1:31:13
uh host the NA platform for you. After that uh it will appear on your
1:31:18
dashboard. Just click on manage. Currently if you see it's running. Okay.
1:31:24
And in order to access it just click on this manage app. Here you'll find the URL.
Okay. Here you can see your
1:31:30
application is running. Uh very first time it will ask you to sign up. You have to
enter username, password, email
1:31:37
and your full name. Okay. And just simply sign in. And once you sign in, you will
see the N8 platform like this.
1:31:45
Okay. Simple and clean. Obviously here at the top you will see an option called
1:31:51
create workflow. Just click on it and then it will redirect it on a workflow with
this uh uh default template. Okay.
1:32:00
Now first thing first obviously you can refer this documentation. Okay. Okay, that
is very important. I will put the
1:32:06
link in the description in order to follow step-by-step guide. Now, very first
thing that we need to do is to set
1:32:11
up this web hook. Obviously, this particular part will be on the uh client
1:32:16
side because obviously we need to add a logic to upload the uh file and all. But
1:32:22
later on, if you see this is the web hook uh we need to set up. So, I will go over
here. I will click on this add
1:32:28
first step and then search for the web hook. See this one. Now on once you
1:32:34
click on this one you will see this test URL and the production URL as well. Here
you will find an HTTP method. So right
1:32:42
now uh I will make this as a post request. Okay. And then you can set up a path if
1:32:49
you want. So over here you can rename this to let's say generate
1:32:56
interview question and then this will be your webbook
1:33:04
endpoint. Uh for authentication you can set up and some authentication if you want
and I will keep this immediate
1:33:10
response as a immediate one. Okay and that's all that's how easy it is. Uh on this
dashboard you will see your web
1:33:17
hook correct is get added. Okay. Now in order to test this web hook is quite
1:33:23
simple either uh you can use a postman. Okay. But uh the another easier thing if
1:33:32
you see this uh chrome extension called request bin HTTP API client from there
1:33:37
you can make end request. So I will say send request. Obviously it's redirecting to
this particular page. Go to this
1:33:43
request bin. Then I will copy this production URL or you can use the test
1:33:48
URL because we did not move this production yet. So I will copy it. I will paste it
here. Okay. And make sure
1:33:55
it's a post request. Now to this API request go to the body
1:34:00
and inside the body we are going to pass resume URL. Okay. Now you can get the
1:34:08
URL from anywhere. Obviously, we need to pass it. But this is the sample PDF URL
1:34:13
I'm going to use. So, oops. So, over here I'm going to pass it.
1:34:21
Okay. If you want to pass any other parameter, you can pass it. But right now, I
will keep as it is. Then inside
1:34:28
the inate workflow, make sure to listen this test event. Okay. So, just click on it
and it will start listening it as you
1:34:34
are in the test mode. So, you have to man trigger manually. Then simply click send.
And over here if you see it's
1:34:42
saying workflow was started. And if I go over here you will see
1:34:47
this request. Okay. Obviously it has the resume URL over here. And that is what we
wanted. Perfect. Now first step is
1:34:55
complete. The next step is uh we need to set HTTP request in order to fetch a
1:35:01
file data. So over here click on this plus icon in order to add a new node and
1:35:07
I will simply add HTTP request. Just search on this tool section. Inside the
1:35:13
HTTP tool request you need to add a get request only. To this get request you
1:35:18
need to pass uh some URL. Okay. So over here search for this PDF URL. So we'll
1:35:24
say resume URL. just pass it over here because that's what we want to uh from
1:35:31
that we need to get the data right so that's the reason I pass and now click
execute step once you execute the step
1:35:38
you will see this file uh we get it as a output perfect so second step is
1:35:45
completed now third step is and extract the data from the file so we are on this
1:35:51
particular step now we need to extract the data so again I will click on this node
1:35:56
And in order to extract the data just search extract from file. Click on it. It has
a different different method. So
1:36:03
search for the extract from P PDF. So I will click on this one. Over here you will
see an option called extract from
1:36:10
PDF. Obviously you will see another options as well. I will keep this input data as
a binary. But over here
1:36:18
because that's only have things we have. So I will keep as it is. But if you
execute this step, you will see a proper
1:36:25
output. See, obviously there are bunch of things, but we are only need to deal
1:36:30
with this particular text because this text is actually fetch from the file. See
the resume information, right? Now
1:36:38
obviously once we extracted this particular file, now the next important thing we
need to connect to the AI
1:36:44
model. So over here I will again click on this plus icon and click on this AI.
1:36:50
Over here you'll find a different different provider like uh Google Gemini, OpenAI
and bunch of other.
1:36:57
Now you can use anything okay if you have any API key ready you can use that one.
Many of the user want to use free
1:37:04
one. So uh you can use this open router but for easy integration I'm going to
1:37:09
use this open AI chart GPD. Now over here once you click on this one I will
1:37:16
select this option called message model. Okay. Now into this one you can select
1:37:21
the message model everything uh very first time it will ask you to add an API
1:37:26
key as soon as you select that particular model. So make sure to get the API key
from open AI platform. Okay.
1:37:35
And then you can get that API key from there. So make sure because other than
1:37:40
that it will not work. So you have to get the API key first.
1:37:45
After this, make sure to select the model, a specific model. So over here, u
1:37:52
I will select the cheapest one which is the mini model. So you can select the one
whichever you want. I will select
1:37:58
this 40 mini. Let's select 4.1 mini. Now inside the
1:38:04
prompt, okay, you can write a prompt whichever prompt you want. So here we'll say
generate 10 interview
1:38:12
questions depends on user resume data
1:38:18
provided by user. Make sure
1:38:23
uh response will be in JSON format and
1:38:33
and we can say and or we can say will be
1:38:41
question and answer fill. Okay. After this make
1:38:47
sure this is the system prompt. So I will select the role as a system prompt. Now I
will add another message and in
1:38:53
inside this message we need to pass this extracted data from the uh PDF file.
1:39:00
Okay. So I will pass this to this particular prompt and obviously we can say that
okay this is the user prompt.
1:39:06
Then we have to make sure that uh we want an output as a JSON only. So I will
1:39:12
enable this option. Okay. Now once everything is set up execute this step.
1:39:18
So we'll execute this step and we'll wait to finish it. Obviously it's very fast.
So within a few seconds you'll get
1:39:25
the result. And boom. If you see we got the result. Inside here I will uh you
1:39:31
have option the schema table. I will select the JSON easy to understand. Inside
here you will find an interview
1:39:37
question. Inside that we have question and the answer as well. See for each of
1:39:42
them we have the question and answer. Obviously it generated 10 interview question
related to the user's resume.
1:39:49
How cool right? And that's how our workflow is almost ready. Now once you
1:39:54
have this output obviously you need to return this output back to that particular
web hook this particular web
1:40:00
book. So you can add or you can just search again the web hook but in this
1:40:05
case make sure to select the respond to web book which return data for your
webbook. Obviously here uh you can say
1:40:13
that okay first incoming item you can send it as a response and once I execute
1:40:19
this one you will see this response this particular response is going to send to
the user or to the particular web and
1:40:26
that's how our complete workflow is ready now once you ready with this
1:40:33
workflow don't forget to save it otherwise you will lose the changes. Now test this
complete workflow from our uh
1:40:41
API request. So I will say execute workflow. Currently we we are in the test mode
only. And this is the test
1:40:48
URL. So we'll send the request. Once you send the request, if you see it's still
executing and on this part you will see
1:40:55
the complete execution. Currently it generating a response from this AI model. And
if you see that it's a
1:41:01
loading and boom over here we'll find the result. Cool, right? So that's how
1:41:07
you need to do it. Obviously, whenever you test it, we have to make sure that it
will listen the uh event. But if you
1:41:14
want to move this to a production, it will move in just single click. Just enable
this from inactive to active. Now
1:41:22
say got it. And from this webbook, if I click on this one, you will find the
production URL. Copy this production
1:41:29
URL. And then you don't need to do anything. it will just replace your uh
1:41:37
API endpoint. I think that's all. And now if I send the request if you see it's
loading and obviously you don't
1:41:43
need to wait uh listen it because it is in the production mode right so it will
give you the final result and here we
1:41:51
go. Okay so this complete completed logic we just added with the help of
1:41:56
this uh inate automation workflow within just few steps. So that's how this is
1:42:02
the simple use case for this particular project. But there are lot of different uh
feature that we can add it. If you
1:42:09
want to learn more about this N8 and want to build such a kind of project where we
can use the NATE uh as an AI
1:42:17
automation tool, let me know in the comment section. I will definitely consider you
a project and we'll build in the upcoming videos. Now another
1:42:24
important thing uh many of user don't want to pay it while they are doing in
development. So in that case what to do?
1:42:31
Obviously we you can set up this N8 locally and let me show you how. So
1:42:36
simply first thing we'll go to this N8 official website okay and go to the
1:42:41
documentation. Inside the documentation you'll find an option called quick quick
1:42:48
start. Just go to the quick start inside here I think.
1:42:56
Let me go to go back again somewhere I miss it. So we'll say selfhost. Okay,
1:43:02
make sure to select that option called selfhost. And inside the selfhost you'll
find an option called installation or
1:43:10
maybe select on this npm option. Inside this npm option, you have to install it
1:43:17
uh using this npx in command. Okay, if you want to install globally, just use this
command. So simply I will execute
1:43:25
inside the terminal. Okay, you can execute anywhere and it will uh install this N8
globally.
1:43:34
In my case I got error because um it need a permission. I'm using Mac OS. So
1:43:40
for Mac OS you need a specific permission also. Uh after that you have to run this
command. So basically I will
1:43:46
use this sudo directly this command. So it will automatically start running uh
after installing it. Okay. So if you see
1:43:53
it asking me to enter the password as well and then it will ask do you want to
proceed say yes you can even uh install
1:43:59
the specific version of this inate um tool. Okay so you can you just need to
1:44:04
mention that particular um version which you want to install and then it will
1:44:09
start working and if you see right now it's still installing it. So we'll wait to
finish this installation
1:44:16
and right now if you see it's running on this particular port okay 5 6 7 8. So I
1:44:22
will open this port on the browser here. If you see the same way you will see on
1:44:27
the hostinger as well it will ask you to sign up. So I will add some detail
1:44:35
and we'll add a password as well over here. You can just keep everything
1:44:40
if you don't want anything. Okay. And this is how your workflow get started.
1:44:46
Same thing whatever you saw on the hosting uh platform everything is same
1:44:51
everything you will get all the tools all the features you find on any but the most
important thing with the hosting it
1:44:58
is in the production mode you don't need to set up and host it manually okay but
for the development purpose uh obviously
1:45:05
definitely you can use your local inate platform
1:45:12
now let's call this web hook into our application we I have to make sure we'll
select the file and upload it to the
1:45:18
cloud storage and for that one we are going to use an image kit. So simply
1:45:24
first I will go to the imagekit.io. Image kit provide a cloud storage not
1:45:29
only for image and video but you can also store the files. Image kit also has
1:45:34
a lot of different AI transformation feature which you can explore it. Once you are
on this image kit I will put the
1:45:40
link in the description. Just go ahead and create a new account and inside this you
will find a media
1:45:46
library where you can easily upload the image. Now in order to integrate this image
kit
1:45:53
I'm going to use this uh image kit NodeJS HDK. Simply copy this npm command
1:46:00
go to your project and then paste it here. Then you need to set up and initialize
1:46:07
this image kit by providing the public, private and the URL endpoint. So let's
1:46:13
copy this. And I'm going to keep uh all of this
1:46:18
configuration on the server side. So we'll create a dedicated API in order to
upload the file and then process the
1:46:25
request as well on the click of submit button. So inside the app folder, we're
going to create a new API folder because
1:46:32
we want to create a API endpoint. And here we'll say generate
1:46:38
interview questions. Okay. Dot or we'll say
1:46:44
interview question.tx. That's fine. And then we'll say tsx.
1:46:50
Oh, this need to be a folder name actually. So make sure you'll create a folder
name. So this will be our endpoint. And then inside this we'll
1:46:57
create a route. tsx file over here we'll say export
1:47:05
constant a sync function this need to be a post request
1:47:11
it just need to be an export as sync function uh over here we'll say request
1:47:17
and then next request okay now once you save this one make sure to copy this
1:47:23
image kit here we're going to initialize make sure to import this image kit as well
as we already installed. So you can
1:47:30
use this u image kit import statement and then we need to set up a public
1:47:35
private and URL endpoint. So I will go to this env.local local file inside this
1:47:41
I will add image kid URL endpoint
1:47:48
then image kit URL public key
1:47:55
and then we also want a private key.
1:48:02
Okay. So these three things obviously we need to update. Now in order to get this
public uh endpoint URL and private key
1:48:09
you can simply uh head to this image kit dashboard. Now image kit is free to use.
1:48:15
So you can try this out. Under this you will see an option called developers option
at the bottom of this sidebar.
1:48:21
And on the right hand side you'll see API key. If you don't see any API key make
sure to create a new one. On this
1:48:27
one you will see the URL endpoint. Simply copy that and paste it inside your
env.local file. Same thing, copy
1:48:34
the public key, paste it and then you can copy the private key as well
1:48:41
and paste it here. Once you copy all of this detail, simply I will head back and
1:48:48
as you know that the initialization is ready to use. Now if you scroll down there
are lot of different method that
1:48:54
you can find it out but we need a file upload section right where we want we
1:48:59
can easily upload the file. So before in uh add a logic to this file upload first
1:49:06
let uh upload that particular file and set it and send it to this post API
1:49:11
request from the UI side or client side. So I will go to this routes and under
1:49:17
this components where we have create interview dialogue right. So on this one
1:49:25
whenever user upload the file from this resume upload we need to send to this
1:49:31
particular uh component. So we need to send back. So simply instead of setting
1:49:37
this over here I will set this file I'll pass back and
1:49:44
we can put a type any okay now on this create interview over here I will accept
1:49:50
that and then at the top I will create a
1:49:58
state called file comma set file and use table. Okay. So
1:50:06
that we can simply set the value. So here we'll say file and set file to
1:50:12
file. You can type of type as anything file.
1:50:18
Maybe you also need to set that type over here.
1:50:25
Something like this. Okay. So once you set this file, let's save this one. It means
whenever user upload the file from
1:50:32
our UI component it it is now setting up uh on the inside the parent component as
1:50:39
well. Okay. And on the click of submit you will see that. Now next thing we'll
1:50:46
write a method called constant on submit.
1:50:51
And this method obviously uh inside this method we need to call that API endpoint.
But before that it is very
1:50:58
important uh to send this file in the form of form data to the post API
1:51:03
request because this is a file right so you can't just pass a JSON body request
1:51:08
you need to send in the form of form data so I will define a form data is equal to
new form data
1:51:18
and then here we'll say form data dot appen
1:51:24
then we'll say file and then we need to pass that file which user selected.
1:51:30
Now obviously we are getting this error because file might be a null. So here we
say null as well
1:51:38
and here we need to write a condition if file is not there then return nothing.
1:51:44
Okay, after this I will add try catch block.
1:51:51
Then exception e here I will just console the log for the error and inside
1:51:57
the try block we simply call constant result is equal to await exos. So make
1:52:04
sure you have this exio installed in order to make an h uh http uh api call.
1:52:11
So if you don't have this particular library uh so make sure to install it. So just
type npm AIOS. Okay. So it is
1:52:19
the HTTP client library in order to make an API call. Once you add make sure to
import this Exio
1:52:26
let me import it manually. So here we need to write import AIOS from Exio so
1:52:33
that you can apply any method. So in this case we want a post request. So we'll say
slash API slash
1:52:42
generate interview questions.
1:52:49
I will make sure that's correct. And then we need to pass a form data.
1:52:55
Once the you pass this form data, let's save this one. As we are using aait over
1:53:00
here, I will make this as a async. And then inside the console log we'll say
1:53:06
result dot data. Okay. Now we'll go step by step. We'll first upload the file to
1:53:12
the image kit. Okay. Now this onsubmit we need to attach to this submit button. So
over here we say on click
1:53:20
and attach this onsubmit. Now make sure to set a loading state. So here we say
constant loading comma set loading is
1:53:29
equal to use state. And initially it will be false. Whenever you click on unsubmit
we'll set the loading. So here
1:53:36
we'll say set loading to true. And once the everything is finished I will use
1:53:42
finally block. Okay. To set the loading as false.
1:53:51
We don't need to use this I think. Yeah. And then save it. Okay. Uh whenever the
1:53:57
loading is true we need to disable this submit button. So here we'll say disable
1:54:02
when the loading is true. And also if you don't have any file selected so here
1:54:08
we will say if not file selected then also disable this button. Now if I go
1:54:13
back and open it this dialogue you will see oh I don't know why it's not disabled.
Let me refresh this. And if
1:54:21
you see now it's disabled. Now once I upload the file so let's upload this
1:54:27
fullstack developer file and then the button is enable okay so that's how you
1:54:32
need to do it now second thing obviously we need to make an API call okay and
inside this
1:54:39
route tsx we need to get the form data now in order to get the form data we'll
1:54:44
say constant form data is equal to await request dot form data
1:54:53
Then we'll say constant file is equal to form data dot get and then obviously if
1:55:00
you remember we gave the field name as a file over here right so this information
1:55:05
we are getting and here we'll add as file as this is a file right so add it
1:55:12
as a file over here we'll say if not a file then uh we'll just keep it at is as it
1:55:19
is okay or we can if you did not Right, that's also fine. Now we need to convert
this U file into
1:55:26
a buffer. So we'll say constant bytes is equal to await file
1:55:34
dot array buffer and then we'll say constant buffer is equal to buffer dot
1:55:42
from bytes.
1:55:47
Then inside the try catch block. So over here I will add try catch block just in
1:55:52
case if it fails our application will not stop right. So that is very important. So
over here we will say
1:55:58
upload u pdf is equal to await image kit dot
1:56:05
upload and then inside this you need to pass
1:56:10
uh this parameter. So obviously the file uh it can be a binary file name you need
1:56:16
to pass okay you can give any file name and then if you want to make any
1:56:21
extension transformation you we actually don't need it but make sure to pass this
is public as a true so over here we'll
1:56:28
say uh file and for the file I will say even though if you upload the file let's
1:56:34
try to upload the direct file u and I'm not sure whether it will work or not
1:56:39
okay so it need to be a buffer if you see This need to be buffer. So here we say
buffer only. Okay. Then we need to
1:56:48
pass a file name. Now file name I will give it as a current time stamp. Okay.
1:56:53
Which will be the unique every time. Uh here we'll say dot2 string
1:57:00
dot PDF because we are just accepting PDF file. And here we have one more field
called
1:57:07
is publish set it as a true. So it will the that particular file uh is available
1:57:13
to access immediately once you uploaded this one. Um you'll you can just return
1:57:21
the next response dot JSON with the uploaded PDF dot URL. Okay, right now we
1:57:28
are just returning the uploaded file URL. Obviously later on we need to u make an
web hook call but for now we'll
1:57:34
test this scenario. So let's save this one. Go back to your application. I will
refresh this with an all the new
1:57:40
changes. Then I will click on create interview
1:57:45
upload the file. So over here let's upload this sample resume file and then
1:57:53
it's selected. In meantime I will also open the inspect panel to observe if there
there is any error and the result.
1:58:00
If I click submit if you see we have loading right and boom. If you see we
1:58:05
have an error actually. Uh so let's find this what is the actual error. So if I
1:58:11
go to the console where you are running your application go to your bottom over
here you'll find
1:58:18
an error. Right? So it's saying file dot array is not a function.
1:58:23
So basically uh this one is not working. I expected we are getting error at this
1:58:31
position. So we have to make sure that we are just passing a single file and not
the array.
1:58:36
That's the reason we are getting this error. So when we upload the file inside the
resume upload over here if you see
1:58:43
we are setting all the files. So we just need to get the first file. Okay. Or you
1:58:48
can also add the restriction that only fade the first file as well. And now if
1:58:53
I save this one, go back to our application and over here obviously we have just
1:59:00
written the URL. Okay. So you can just write the URL as well.
1:59:06
And now if I go over here, let's click upload. We'll upload the file.
1:59:14
And if I go to the inspect panel inside the console, we'll click submit. And
1:59:20
then we'll find the URL of that particular file. And obviously it's get uploaded on
image kit. And we have this
1:59:27
PDF as well. If I open this one, boom. If you see this PDF also you can just
1:59:32
verify by going to this image kit. And this is the brand new file we just uploaded.
Perfect. Now we have this file
1:59:40
URL, right? And we also have this complete workflow. Now we need to just
1:59:46
get the data. Obviously we need to call that particular web hook in order to get
the data as simple as that. So to do
1:59:54
that let's uh go to our web hook inside this I will open this web hook and we
2:00:01
need this production URL. So I will copy this production URL. Let's go back to your
application and over here we need
2:00:08
to call inate web
2:00:16
hook. Okay, something like this. Now inside this we'll say constant result is
2:00:22
equal to await exos dot post request your web hook URL
2:00:30
and then the inside that you need to pass the body parameter which is nothing
2:00:37
but the if I go over here this resume URL. Okay, that you need to pass.
2:00:45
So I pass this resume URL and that URL you can get it from the upload response dot
URL. Now you might see this name I
2:00:53
changed okay while debugging the that particular error code. So don't worry it's
the same uh if you want you can
2:01:00
just change this name and now once we pass this one we get the console.log
2:01:05
result dot data. Now you can return this result directly. So over here I will
2:01:11
return this response as well and then save it. As simple as that. If you see,
2:01:16
we completely over all the logic because we kept inside our workflow. So inside
2:01:23
this workflow, we kept all our logic, all the steps. So you don't need to write uh
inside your React application.
2:01:30
Now let's test this out. So I will refresh the screen. Let's upload the file
2:01:38
and then I click submit. Now right now it's still working. Okay, because it will
take some time. Uh at this uh
2:01:46
button, we need to show some kind of loader. Okay, and in the network tab, you will
see uh that particular API is
2:01:52
still in the pending status. Okay, it means it generating the response for us. And
boom, the it's showing 200 status.
2:02:00
If I go to the console and here we have the result. Now inside the message, we
2:02:05
have the content and here we have this all the questions. How easy it is,
2:02:10
right? So that's how we need to get these all the questions
2:02:16
uh from the U AI model. Okay. Now make sure as we are reading data our
2:02:22
questions is inside the message and under again that we have the content and then
the questions. Now inside the
2:02:29
workflow you can even mention that what is actually actual result you want. Okay.
Obviously uh the in the response
2:02:36
we have this message we have this annotation content and lot of other thing we
don't want all of these bunch
2:02:41
of code so better you can refine this one so I will go to this workflow go to this
respond way and then right now
2:02:49
actually uh it just sending everything as it is okay
2:02:55
because that's what we are saying that okay you have to respond with the first
incoming result um let's keep as it is
2:03:02
for now because I I don't see any option here uh to update it. If you know any
2:03:08
option just make sure uh put it in the comment so that other user can get to know.
2:03:19
But right now we are good with this one. We are getting the questions and
everything. Now the last step in our
2:03:24
workflow is to uh save this result into our database. And that is again very
2:03:31
straightforward. First you need to create a new table inside the convex. So I'll go
to this convex under the schema
2:03:37
over here. We'll create a new table called
2:03:42
interview session table.
2:03:48
Over here we'll say define table and then we need to add uh all the details.
2:03:55
So here we say interview questions which is of type uh any I will mention
2:04:02
okay then you can add PDF URL
2:04:09
or we'll say resume URL
2:04:16
which is of type string and who created this particular um inter
2:04:24
equation right user's email. So we'll say user id and that user id we need to
2:04:29
connect with this user table. So we'll say v dot id and then you need to provide a
table name. So we'll say user
2:04:37
table. So whenever you want to fetch any data from the inter session it also fetch
the user information with that
2:04:43
particular user ID. Here I will also add a status field
2:04:48
whether this u particular interview session is completed or not. Okay. So
2:04:53
this is the basic thing. Obviously later on we can add more field into this
particular table. For now I think uh
2:04:59
it's good. So once you add this schema make sure inside your convex it's uh in
2:05:05
the convex database it's updated. So I will just refresh this and here we have this
interview session table. Perfect.
2:05:11
Now we'll create a convex function in order to save that data.
2:05:18
So go to the convex and inside this we'll create interview
2:05:24
questions tsx. Okay. So this is the mutation we are going to add. Um I will
2:05:30
just say interview for now
2:05:36
and then make sure it's a ts. Sometimes tsx might not work because it is on the
2:05:41
server side. Inside this similar like this users right we need to create a
2:05:46
mutation. So we'll say export constant save interview
2:05:53
questions is equal to use mutation
2:05:58
inside this we need to get an arguments. So for the oops sorry uh just need to
2:06:04
get arguments uh so arguments is uh questions. Okay
2:06:12
obviously it is type any make sure to import this v and then any type then uh
2:06:20
the user ID so I will say UID of type ID and then you need to pass the user ID
2:06:28
the table name for that one. So we'll say user table and then we also need the
2:06:34
PDF URL. So we'll say resume URL of type string. Then add an handler
2:06:48
of type a sync and the arrow function. Oh, this need to be a mutation only, not
2:06:54
use mutation. Okay, so make sure to update that. Now inside the handler we'll say
constant result is equal to
2:07:02
await and here we'll define ctx comma arguments. So we'll say ctx dot db dot
2:07:11
insert give the table name which is interview session table and then the
2:07:16
argument which you need to pass. So interview question we can get it from the
argument dot questions.
2:07:22
Then we need to pass resume URL which we can get it from the argument dot resume
URL and the user id.
2:07:29
So we'll say arguments dot user id. Okay the status you can set it as a draft or
2:07:36
we can say uh draft only. Okay not so important for
2:07:42
now. And then save it. Once you save you can return this result as well. Now this
2:07:48
result contain the unique ID that is uh very important for us. So let's save this
one. After saving go back to your
2:07:57
route.tsx make sure you are just returning the uh questions data. Right?
2:08:04
So if you see we have this message inside that we have the content. So we
2:08:09
say result dot message dot content
2:08:14
okay dot questions. So the only that data we need it. So so
2:08:22
that's why we are written that data. If you want to test this out let's test this
out. So we'll say create interview
2:08:29
upload it. Uh we'll upload this file and then click submit. Obviously it will
2:08:35
take a few seconds to generate the questions and then you got only the questions
and their answer as well.
2:08:42
Perfect. Now the next thing uh make sure you will add the loading indicator to
2:08:49
this submit button whenever the loading is true. So I will go to the create
interview dialogue over here. For this
2:08:56
button I will simply add a loader icon.
2:09:02
To this load icon I will add animate spin and I'm going to show this loader icon
2:09:08
whenever there is a loading. So we'll say loading is true then only show it.
2:09:14
Okay. And then save it. Next over here obviously once we get the data
2:09:19
we need to save to database right. So as you know that we already defined the
2:09:25
mutation. So let's use that. So we say constant save interview
2:09:32
question is equal to use mutation and define that API. So inside the
2:09:38
interview we have this save interview question mutation uh I will use that
2:09:43
over here. So we'll say constant response is equal to await say enter question and
then you need to
2:09:50
pass the value the question obviously which is inside the um response data
2:09:59
right then the resume URL that you can get it from the I think we need to get
2:10:04
this resume URL as well um from this route right so what we can do we can
2:10:13
let Let me clean this out. And inside this we'll say questions as
2:10:19
result. Let me undo everything because I need this complete path. I don't want to
2:10:26
write it again. And then you can clean this here. We'll
2:10:32
say questions and paste this. And then
2:10:38
resume URL. Obviously this resume UR URL we already have inside this upload
2:10:44
response. So we'll say upload response dot URL. Okay. And now
2:10:51
over here we'll say response dot data dot questions and then response dot
2:10:56
data dot resume URL. Okay. So both the field uh we are getting now.
2:11:05
Now we are getting this warning. I will just ignore this warning. And the last we
need a user ID. Now this user id you
2:11:12
can get from the user detail hook right which we already have. So we'll say user
detail comma set user detail is equal to
2:11:21
use user detail context. You don't need to define a complete uh text. Okay. You
2:11:27
can just define like this. But if you are getting the error something like this
right it's a
2:11:33
TypeScript error. um you can directly use using this use context and then
2:11:39
inside that you can define the detail context okay and from this user detail we
already have the user ID so we'll say
2:11:46
underscore id perfect and in the response
2:11:51
I will just console this response for now okay so that we'll get to know but right
now let's save this one let's save
2:11:58
this route tsx file as well and let's take this out with a new uploading file
2:12:04
So I will upload select this file upload it and then click submit. And now in this
case if you see we have this
2:12:10
beautiful loading indicator right it means okay your uh resume is processing
2:12:16
and generating the question as well from our um in a uh automation tool. Okay.
2:12:23
And boom if you see we got the question we got the resume. Not only that we but
2:12:29
we also got an ID of the inserted record. And that is what we really wanted. So if
I go to our database
2:12:37
inside the convex, you will see a brand new record with the interview questions.
2:12:42
Um then we also have the resume URL, the draft and everything set up correctly and
inserted perfectly fine. Okay.
2:12:50
So now make sure this particular ID need to be saved. Not saved but we need to
2:12:55
redirect and use that ID as our uh record ID. Okay. so that we can navigate
2:13:02
uh to the next screen. But up to this point, I hope you understand. If you have any
question, any doubt, let me
2:13:08
know in the comment section. Now implement the similar functionality
n8n Workflow for Job Description
2:13:15
for the job description. Once user have the title and the description, we want to
generate the interview question.
2:13:21
Currently our workflow only handle the PDF upload functionality where you can
2:13:26
upload the PDF and then it will extract data from it and pass it to the AI model.
But what we have the title and
2:13:33
the description that's where we need to create an uh condition that depends on
2:13:40
what data you user is passing to this web hook. Then we have to take action. There
is the uh two way you can do it.
2:13:46
Either you can create a complete new uh workflow. Okay, if you don't want to go in
a complicated way or you can simply
2:13:52
add inside the same workflow. So simply I'm going to add one node in between this
webbook and HTTP request. So inside
2:13:59
here I will add simply a flow and inside that if you see we have this if loop right
now this if condition will check
2:14:06
if user has the PDF URL or resume URL or not. So we'll say if resume URL string
2:14:13
exist. Okay. So if this resume URL string is exist it means uh we should
2:14:19
execute this particular workflow. Okay. But if the string is not exist then we
2:14:25
can simply connect this model to the open AI message model. Okay. Now
2:14:30
obviously in to this model we are going to uh pass uh job description and title and
that
2:14:37
information we are going to send it to this AI model. So let's say uh first what we
can do make sure to set up this
2:14:45
model. So I will say a mini model maybe JPT mini one or mini one that's fine.
2:14:53
And for now I'll keep like this only. So first thing I will open this
2:14:58
workflow. I will listen to this test event. Okay. So we'll go step by step.
2:15:03
copy this uh test URL in order to test this one and then I will pass it to this
2:15:09
particular API endpoint. Now we want to pass resume URL as a null. Okay, but
2:15:15
here we want to pass a job title. So we'll say job title let's say full stack
2:15:22
developer. Okay, now obviously uh you can pass any job description. Okay, for the
testing
2:15:29
purpose, I will just say 3 years of experience. Okay, and that's all we
2:15:36
needed. Now, simply send this request. Once you send this request, right now we
2:15:41
are getting two 200. It means it executed perfectly fine. Next step, if I
2:15:46
go to the next step, inside here, you will find we have the resume URL, job title
and job description. Currently,
2:15:52
the resume URL is null. It means it will not go to this particular uh flow. Now
2:15:58
it will come to this one. Right? Now in that in this particular flow let's say
2:16:03
execute previous node so that you can get the title and the description. Now before
that you need to write a system
2:16:09
prompt. Now inside the system prompt I'm going to just simply say that depends on
2:16:16
user job title and job description
2:16:23
generate 10 interview questions.
2:16:29
Okay. Now also make sure to say that okay give me question
2:16:36
and answer inside questions
2:16:42
object list with fill question and
2:16:47
answer. Okay so it will give in the same way. So you don't need to u parse it in
2:16:52
a specific order or map it in a specific order. Then here we will say that okay
this is a system prompt. Then we'll add
2:16:58
another message and this will be the user prompt and in that one in that in this
one we have to write a job title
2:17:05
and you have to pass a job description as well. Okay. So both the things make sure
to pass
2:17:11
and here I will enable this output content as a JSON. Okay. Now once I
2:17:17
execute this step let's say what kind of output we are getting right because this
step will pass our prompt and the system
2:17:24
prompt uh to the AI model and it will give you the specific answer for us
2:17:30
and here is the result see perfect right and that's how it works now one more
2:17:36
important thing uh for the testing purpose I will just say two interview question
okay and then we'll go back now
2:17:42
we want to execute all the workflow completely so we'll say execute workflow. I
will go to this particular
2:17:48
page. Then I will just send this request. Okay. And once you send the request, if
you see it's loading and
2:17:55
currently everything executed. Okay. I think uh we missed something.
2:18:01
Let's see what's the issue. Okay, we got the answer but we did not
2:18:06
return the answer. Similar like this web hook, right? So we need to send or we need
to attach a respond to web hook
2:18:13
over here. Okay. So we'll say first incoming and then execute. We got the result. I
think that's pretty good. Now
2:18:21
let's try this again. And now I will send it again. Okay. So
2:18:26
once you send this request you will find currently generating the response and
obviously it comes to this point because
2:18:33
we are not passing the resume URL and here we go and we have this questions
2:18:38
and answer as well. So that's how easy it is. So make sure in existing workflow
2:18:44
you can add this condition so that it will handle both the uh condition even
2:18:49
though you've uploaded the PDF file or even you provided the uh job title and
description.
2:18:56
Now next thing let me close all of this tab for now I will go back obviously
2:19:01
inside the resume upload. So I will go to this sorry I will go to the uh interview
dialogue right where we have
2:19:08
this onsubmit button. Now inside the form data we already saving the job title and
the
2:19:16
description. That job title description I'm going to append to this particular
file.
2:19:21
And over here I will say form data dot append.
2:19:27
And we'll say job title with form data dot job
2:19:35
title. Okay. So maybe uh you can rename this job form data something like this.
2:19:40
Okay. So it will not conflict with our state which we define at the top.
2:19:46
And when we are sending data here as well I will send as a form data underscore.
Same thing I'm going to do
2:19:53
for the job description and here we will say job description.
2:20:00
Okay. uh here I will remove this condition and when if file is not there I will
pass as
2:20:07
a null only or you can pass as a I don't know whether
2:20:12
just a empty string maybe okay and then save it now once you make an
2:20:19
call to this particular API endpoint I will go to this API route
2:20:24
over here let's get both these variables so we'll say job title
2:20:32
Job description over here we say job title field and then job description as
2:20:39
well if file is not exist. So inside this uh
2:20:45
if condition right instead of we are just written no file form but in this case now
we'll handle our uh logic.
2:20:54
So basically we want to call this one. So maybe we can just hide this and I
2:21:01
will add condition if file exist then only execute all of these things as it
2:21:06
is or maybe we can completely call this
2:21:13
situation and else
2:21:18
I'm going to use this web hook to call inside this else condition. Now instead
2:21:24
of this one I will pass resume URL as a null. Okay. Then the job title I will
2:21:30
pass as a job title and for a job description I will pass as
2:21:36
a job description. Once we get the result obviously uh we
2:21:42
don't have the resume URL so I will pass it as a null only. And uh for the
2:21:48
questions obviously we'll get it from this result data. So we have this uh
questions as well and then save it. Now
2:21:55
let's test this out the complete scenario and obviously uh make sure to save it. So
once you save obviously we
2:22:02
are already in the production so you don't need to worry about that. Let's refresh
it. We'll go to the inspect
2:22:07
panel to see the result as well.
2:22:12
And here we will say create interview. We'll upload the file.
2:22:18
Oh, so I think we don't need to we want to test the different scenario. So here
we'll say full stack
2:22:25
react developer. You can add the big description. I will just say uh six
2:22:31
years of experience
2:22:36
needed. Okay, something like this. And then click submit. Now once you click
2:22:43
submit I will make sure that our interview question right now if you see it's
pending it means it's generating
2:22:48
the interview question for us. So we'll wait to finish it and if you see we got the
result as well o over here uh it
2:22:57
just return the resume URL. Okay that's weird. So the the reason was were not
working
2:23:03
because we've initially uploaded the resume upload right. So that's the reason it
executed that f uh file. So
2:23:10
over here now I will just write it. I reloaded the application and trying
2:23:15
again. So let's say submit and right now if you see it's loading inside the
2:23:21
network tab it's saying pending. So we'll wait and boom. If you see we got
2:23:26
the questions and the answer. Obviously we have an issue with the convex because
2:23:32
uh convex is not storing a null value because we did not make it as optional. By
default when you define the schema
2:23:39
inside the convex it is a required field. So in order to make it an
2:23:44
optional field you can add v dot and option v and here we'll say v dot
2:23:50
optional. So this url will be now optional field.
2:23:55
Okay something like this and then save it. Obviously if you want to store the job
title and the description you can
2:24:02
also save that too. It's a completely optional thing. So right now we are going to
save it. So I will add a job
2:24:08
title as optional field again. Okay. And it is of type string and job
2:24:16
description. And this one as well I want to add it as
2:24:23
an optional field. Okay. And then save it. Once you save,
2:24:31
we'll go back to this table. And here you will you will see this two new
2:24:36
column called job description and job title. Perfect. Now let's go back to our
2:24:42
route over here. It's written completely uh everything. Okay. So we don't need to
worry about this. But I will go to this
2:24:49
dialogue and inside this dialogue when we update this interview question, right? We
need to update this particular
2:24:55
convex function. So go to this save interview uh question API inside the
2:25:00
convex. So we'll go to this interview.ts. Over here we'll accept more value. Make
sure the resume URL
2:25:08
we'll mark it as an optional only.
2:25:15
Then you need to pass uh get the job title. This is an optional field and it
2:25:21
is of type string and then the job description. So over
2:25:28
here I will say job description. Now inside the handler make sure to pass
2:25:33
this value. So we'll say job title as arguments dot job title and then job
2:25:42
description as arguments dot job description. Okay.
2:25:47
So this field we are uh saving now. So and also once you add this field make
2:25:54
sure to say update or pass that field as well. So over here we'll say job title
2:26:00
as form data dot job title and then job
2:26:05
description as form data dot job description.
2:26:12
Perfect. Let's save this one and let's test this out one more time. So
2:26:19
I will refresh this screen. Create a interview. I'll go to the job description. In
this case, we'll say
2:26:26
full stack react developer 4 years of experience. Obviously, you
2:26:34
can add more description and then click submit. If you see we still have this error
2:26:40
saying convex is not matching this resume URL as a null value, right? It may be go
to the uh in order to check
2:26:46
this go to this convex and if you see we have this error, right? As you know that
we already have one record inside this
2:26:52
convex and in that previously we did not set resumeum error as optional field. If
2:26:57
I remove this go back and uh I will stop this convex deploy first and resume it
2:27:06
again. Okay. And maybe in this case uh
2:27:11
it will work completely fine hopefully. But you can just go to the schema
2:27:18
file. Make sure that it is an optional field. Okay.
2:27:24
And then if you see we don't have any error. And now let's test this out. So we
have
2:27:30
full stack 4 years of experience. Let's click submit. So we still have the error.
So I check the documentation. So
2:27:37
in convex if you want to allow a null value, we have to write something like v.un
union and then you have to say v
2:27:46
dot uh null okay so it it means you are allowing the null value as well and then
2:27:52
I will remove this optional field same thing I'm going to do with the job title
2:28:00
and then job description and then save it now I will test it again one more
2:28:06
time and if you see we got the result okay we have this questions and that is
2:28:11
also saved into our database. Uh see right now obviously we mentioned it as
2:28:18
only two questions. So that's why it's getting two questions only. Okay. So that's
how guys you need to handle the
2:28:24
job title description uh section as well. Similar like a resume. Just quick update
um uh if you don't want to pass a
2:28:32
null value in order to uh get rid of that complicated logic inside the convex
2:28:37
simply pass an empty array something like this. If you see this resume URL, I'm
passing as a empty string. Same
2:28:44
thing you can do it for the title and for the description as well and then save it.
Create Interview Limit using ArcJet
2:28:52
Now, as you know that this is our SAS application and we want to add a free
2:28:57
and paid uh subscription model to our app. Obviously, for a free model, we
2:29:02
want user to generate only two interview daily, right? with some limited feature
access and email support. But for the
2:29:10
paid user, we allow user to create unlimited daily interview with the full feature
access and email support. But
2:29:16
the question is how to add daily limit and how to track it. Obviously, you need to
write a lot of complicated logic. You
2:29:23
need to save user uh record into database and that's little complicated
2:29:29
and that's where the ARJ play very important role. ARJ is a broad protection, rent
limiting, email
2:29:35
validation and attack protection u developer first approach to the security. It
help us to act add the rate
2:29:44
limiting into our application the way which we wanted. But along with that one you
can add the board protection email
2:29:51
validation and there are many other feature which you can integrate with the help
of ARJet. It's free to use and very
2:29:58
easy to integrate as well. within few line of code you can protect your
2:30:03
application from any unauthorized access u along with some validation
2:30:09
you don't need to write a computer logic arj will take care of everything you just
need to add simple line of code and
2:30:17
then you are good to go simply click the link in the description or uh go to the
2:30:22
arjet.com over here you can simply go to the documentation
2:30:28
where you will how to integrate it. Obviously, uh whichever feature you want to
use, you
2:30:34
can simply add that. For example, in our case, we want to use a rate limiting
feature. So, I will go to the quick
2:30:39
start guide and obviously you can watch video as well. But you can uh follow the
2:30:45
step-by-step guide from the documentation. I will put the link in the description
and uh within a few line
2:30:51
of code uh you can add the rate limiting feature. So, let's do and let's
2:30:56
integrate that. So first thing you need to install the arjet. So simply copy this
go back to your application
2:31:06
and inside the new tab I will add this. Now you can protect all your API key with
the help of arjet where you want to
2:31:12
add the rate limiting. Then you need to set up an arjet API
2:31:17
key. Right? So simply over here I'm going to add
2:31:25
in um this environment variable inside the unvi.local file
2:31:32
and in order to get this API key simply you can create an account.
2:31:40
So I will login with a Google account and if you see one of my application is
already using this um ARJ right so I
2:31:49
will click on new site here you give the site name so we'll say AI mock interview
2:31:55
210 and simply click create once you create you will find this uh ajet key
2:32:02
simply copy that go back to your application inside the env.lo local file, paste
it. Then I will go back to
2:32:09
the documentation and inside the arkjet/out.ts, you can simply paste this line of
code.
2:32:15
So inside the API, we'll create a new endpoint. So I will just add a plus sign and
it
2:32:22
will also create the folder called arjet with an route.ts file and then I will
2:32:28
copy all the content as it is. Okay. Now let me walk through this. So first thing
2:32:33
it initialized this arjet. Okay. And we already have this key inside.locer
2:32:38
file. Now inside the rule it define the rule okay for your rate limiting. Now
currently the mode is live but you can
2:32:45
uh use it as a dry run to just to log. Okay. Now for the characteristics
2:32:51
whichever field you going to pass which is the unique field you can pass this one.
Let's say user ID which is the your
2:32:57
unique field. So make sure to pass. Now the refill rate is five means after certain
time it will again add um the
2:33:04
five tokens you can say into your bucket. Okay. And obviously the interval
2:33:10
currently in this example the inter uh the interval time is 10. So after 10 second
it will refill your bucket and
2:33:17
the capacity of bucket is 10. Okay. Now whenever you call this particular arg
2:33:23
right. So it's up to you how many uh token you want to deduct from the bucket.
Okay. And after every taken
2:33:30
second, your bucket will be added with the five token every time the maximum token
capacity is 10. So make sure to
2:33:37
understand this logic. Now next thing uh this is a simple get API where you user
2:33:42
ID is pass. Right now this is just a demo uh get request. Okay, you can just remove
it once you test this out. Now
2:33:49
over here if you see the your application this particular API is protected with
this arjet by passing the
2:33:56
user ID and the request is five means uh it will check if there is a five tokens
2:34:02
and then it will deduct it. Okay but the but in inside the bucket if you don't have
any um tokens then it will simply
2:34:10
deny and it will return that you only have too many request. So make sure um
2:34:16
this actually this line is very important okay to protect it and then once the
decision is made you can just
2:34:23
check whether it's a denied or it allow us to uh call them particular API. So
2:34:28
let's try to call this one. So I will go to the new tab. I will go to the local/
2:34:34
API/jet and click enter. As soon as I enter this one you will see the message
2:34:40
hello world. I will refresh this again. again I'm able to see this but if I refresh
it again it's saying too many
2:34:46
request and I have to wait for a 10 seconds after 10 second see it started but if I
refresh it many times see over
2:34:54
here you'll see uh it will add five tokens into our bucket after 3 second 2
2:35:00
second like that right now you again have tokens see okay so that's how this rate
limiting
2:35:07
with the ajet works and that's what we wanted now in this particular ular case.
2:35:12
So if I go back to our code, currently it refill every 10 seconds. But if you
2:35:18
want to refill every 24 hours, you just need to mention it here. Okay, in order
2:35:24
to uh refill the bucket every 24 hours. So that's how it works. So right now I
2:35:31
just change this to 8 84,000. I think that is nothing but the 24 hours. And
2:35:36
you can mention something like this as well. Okay, I don't know. But it's better
you can just define the number.
2:35:43
So this need to be 8 6 4 0. Okay. Now
2:35:49
after this uh we are just allowing user only two interview create every day.
2:35:56
Okay. And then you have to wait for the next day. Now I will move this arjet
2:36:02
column because we cannot export it from here. We want to use in another function as
well. So I will export it inside the
2:36:09
let's say you can add it inside a li folder if you want or simply you can
2:36:15
create utils folder and inside this we say ajet
2:36:22
ts past this line of code make sure to export this one okay so that you can use
2:36:28
it anywhere inside the application make sure to import this token bucket and inside
the route now I will import
2:36:35
this AJ from the utils. Perfect. Okay. Now this is just example. If you don't
2:36:40
want you can just remove that. Now it's time to protect our general interview. So I
will go to this route.tsx. Now
2:36:47
inside the general interview question that's where we want to test this out. So
after uh getting all the data over
2:36:55
here I will add this condition. Okay which is decision await aj protect. I
2:37:02
will make sure to import this one. just copy from the example. Now inside this
2:37:07
user ID we are going to pass an actual user uh email. Maybe you can add the
2:37:13
email. Okay. And that email you can get it. So here we'll say constant user is
equal to await
2:37:21
current user. Okay. So this current user uh we are importing from the clerkjs
2:37:26
server and from the user you'll get the user email. So here we'll say user dot
2:37:34
dot primary email address dot email address
2:37:40
and here uh make sure you'll pass the user id something like this okay I will
2:37:46
again make sure it's correct one so primary primary email address dot email
2:37:54
address okay uh obviously here you need to have uh some string if it's not there
2:38:00
so I will pass an empty and then I requested with the five tokens. Perfect.
2:38:06
Then uh obviously it will just console the decision as well. But over here I
2:38:11
will write a condition if decision dot reason
2:38:18
dot remaining. So here uh it has a method called remaining. If is equal to
2:38:24
equal to zero means there is a no token left in the bucket and and we will say
2:38:32
I think for now I'll just keep like this okay then we'll return
2:38:38
next response dot JSON with the status
2:38:45
as 4 29 and then we'll say result as
2:38:53
No free credit left remaining.
2:38:59
Try again after 24 hours. Okay. So this result will return back. Now we have
2:39:05
this error. Uh maybe you can add ts ignore and then save it. Now whenever
2:39:13
you call this particular API aj will protect our application. We'll check if
2:39:18
user already have a token and his daily limit is exceed or not. Okay. If it
2:39:23
exceed then it will return that you don't don't have any uh free credit you
2:39:29
have to try after 24 hours. But if user has the credit then it will go to the next
uh logic. But now you might have a
2:39:36
question that what about the pay user. Now once we added the subscription model
once we add that later on in this
2:39:42
particular project then we're going to add up extra condition over here. But for
now I think we are good. Okay. Now
2:39:47
let's save and you can test this out. So I'll go back to our application.
2:39:53
Now for the testing purpose um I'm just going to update this object
2:40:01
with only one condition. So I will add a capacity of five only and we'll refresh
2:40:06
the screen. Go to the inspect panel.
2:40:11
Now we are trying very first time. Okay. So it might allow us to create the
2:40:16
interview. But before that one more important thing. Now when we call this API
right we'll get the result and here
2:40:23
inside the result we need to check a status. So we say result dot data dot
2:40:29
status if equal to equal to 4 to 9. Okay. Then we'll return empty. And here
2:40:37
uh we'll just console with the message. So we'll say result dot data dot result.
2:40:43
Okay. And uh I will also add the status to this one as well. So we say status uh
2:40:52
200 just uh whenever there is a u error
2:40:58
means no limit rate then it will return the status and that I will I'm checking
that status only. Okay. So it will not
2:41:05
try to add uh anything to our database. Now let's create a new interview. Uh
2:41:11
let's add it from the job description. So here we say full stack react developer
2:41:19
3 years of experience then click submit and now if you see uh
2:41:27
oh so it's saying no free credit left because I already uh try this out right so
maybe that's the reason it's not it's
2:41:34
saying that you don't have any credit and if you see inside the console it's saying
remaining zero right uh let's do
2:41:41
one thing we can update this arjet with only 2 seconds. So after 2 seconds
2:41:48
uh it will update that. So now it might get updated. Uh maybe I
2:41:56
will just change this to now I will just change this to extra let's say 5,000
2:42:02
seconds after 5 10 minutes maybe. And now click submit.
2:42:08
But still it's showing. Uh that's weird. So let me try this out again with the
2:42:14
two seconds.
2:42:24
So there is some issue. Let me check this out because currently
2:42:29
it's still showing the rate limiting is uh zero. Okay. With this particular reset.
Okay. So if you see this reset
2:42:35
window, it's already set right and it's hard to clear this off even though we
2:42:41
set this capacity because the reset window is now after a certain amount of time.
So uh for this one um let me find
2:42:49
out some solution because we we have to test this out right and if you see now
2:42:54
reset window is one okay let's
2:43:03
so in this case if you see I submitted but I change this capacity to 10 okay and if
you see we got the questions as
2:43:10
well okay now if I try one more time uh it will allow me because uh we have the
2:43:17
capacity in the uh bucket but now next time it will not
2:43:23
allow me and it will just resting me out but again the interview time I will
2:43:28
increase to let's say 5,000 maybe and now if click submit it will allow me
2:43:36
again here I will just check the remaining is
2:43:41
five so it will allow me one more time maybe okay and now if you see it giving
2:43:46
me that you already reach free limit. Okay, obviously after 5 thou uh maybe
2:43:52
after 4983 seconds it will allow me uh and it will add a bucket with the five
2:43:58
uh credits. But that's how you have to add the limit for testing purpose. I will
suggest you just keep the uh
2:44:04
interval shorter so that you can test this out quickly otherwise you have to wait
for a day. So make sure to update
2:44:11
this. But with the help of this ARJ if you understand we completely protect our
2:44:16
application. We did not uh need to write a complicated logic u maintain a database
with the status that way the
2:44:22
user is created uh in that particular day with the 24 hours time period
2:44:27
everything you don't need to do it with the help of ajet it's automatically do it
everything for you. Okay. So I hope
2:44:35
you understand this particular RJ u uh rate limiting integration. If you have
2:44:40
any question any doubt let me know in the comment section. If you really enjoy
about this arjet comment down in the
2:44:46
comment section say ar is best. Okay and uh
2:44:53
uh if you any question you can also reach out to me on discord channel.
Interview Start Screen
2:45:00
Once the user created the interview, we want to redirect user to the uh page
2:45:05
where user can start the interview. Now on this page is quite simple. You just need
to show a button to start this
2:45:11
interview and then we also have an option to send an interview link to that
2:45:16
some other user like friends or anyone right. Uh the most important thing over
2:45:21
here the the route will be now start interview. Okay.
2:45:28
And again after this you need to provide a interview ID. Okay. So this ID is
2:45:35
obviously dynamic one. So it can change it can be something like this. Obviously
2:45:40
this ID we already have. So if I go to our database inside the database you
2:45:45
will find this interview session tables ID. This ID we are going to use uh to pass
to the our route. So we'll get to
2:45:54
know which record need to fetch, which interview question need to fetch and from
there it will start the interview
2:45:59
process. So let's go back to our application. Inside this routes, I'm
2:46:05
going to create a new route called start interview.
2:46:10
After this, we'll create a dynamic route and it will be a interview ID. And
2:46:16
inside the interview ID, we'll create a page tx file. Now we'll add a default
2:46:21
template. Here we'll say start interview and then save it. I will just rename
2:46:28
this uh maybe we can say interview page only. Okay, just interview only
2:46:35
and here as well I will say interview. Okay, so it will be easy because we again
have one more page on which
2:46:42
actually interview uh session will start. Now if I go to this local 3000 /
2:46:48
start or not start but interview
2:46:56
and some ID right maybe the spelling
2:47:01
and if I go to that particular route if you see it's navigate to the start
interview page it means our route is
2:47:06
working fine now inside the create interview dialogue as soon as we get the
2:47:13
uh record ID we want to navigate it. Obviously, in order to programmatically
navigate, you need to define a router.
2:47:20
So at the top, I will define a constant router is equal to use router. Make sure
2:47:26
you are importing this use router from the next /navigation. Then over here I will
simply say
2:47:35
router dot push and then we'll navigate to the / ai slash
2:47:42
interview slash and then interview uh the record ID which is nothing but we'll
2:47:48
get it from the response. So here we'll say maybe we can rename this to interview
ID.
2:47:54
So something meaningful something like this. Oh, this next do not need to be an API
just interview/in ID and then save
2:48:01
it and let's test this out. So, what I will do, I will create a new interview. So,
I will go to our uh dashboard
2:48:07
screen. Here we will say create interview. I will add a job description
2:48:14
full stack react developer 2 years of experience and then click
2:48:22
submit. Once you submit it, it will generate it and then it should navigate.
2:48:28
I don't know why it did not navigate it, but if I go to the console. Okay, so it
giving me warning that the free credits
2:48:35
issue. So let me fix that. Go to the ARJet and instead of 5,000 seconds, I
2:48:41
will just add let's say 5 seconds. So I just want to wait 5 seconds. Okay.
2:48:48
And now it's working. So once u it generate the record. Okay. So, it's
2:48:54
saying object is missing something. It's not correct. Okay. It's looking for the
resume URL. That's weird. Uh
2:49:02
basically, it did not generate uh the questions. Let me try. Sometimes uh
2:49:07
maybe server is down. Not sure. Now, if you see uh this case is navigate to this
2:49:12
particular route. And over here, if you see, we have this interview ID. Okay. Which
is the unique ID from the convex.
2:49:19
So that's how you need to navigate as soon as uh it generate the interview
questions for you. Now next thing
2:49:28
u I think I forgot to when the limit is exceed we can add some notifications. So
maybe we can add alert message or some
2:49:36
dialogue. Okay so let me add it quickly because I don't want to keep left like
2:49:42
that with an empty value. So I will just go to the shad CN sorry the shad CN and
2:49:50
inside the from the shad CN you can add a toast. So let's go to the toast or we can
call
2:49:58
it get it from the sonar as well. So this is how it works. See, so in order
2:50:03
to install just copy this npx command inside the terminal, paste this one and
2:50:11
then you need to add this uh toaster component inside the layout. So just
2:50:16
copy that and then I will go to the root layout
2:50:22
file over here. We'll add this
2:50:28
toaster component from the component UI sonar and whenever you want to use here we
can say toaster
2:50:37
sorry uh toast dot warning and then we'll say
2:50:45
uh we can just write this message okay because we already returning from the API
and then save it as simple as that
2:50:52
and once we navigate it obviously we are good to go. Now on this page, we need to
add an UI. So we'll go to the page.tsx
2:50:59
where we have this start interview screen. Now I already have one image added in my
2:51:06
public folder. So if I go to this public the interview jpg file I'm going to use
2:51:12
to display that. So we'll say source/ interview.jpg
2:51:18
in all tag I will say interview. The width let's say 600, height 400.
2:51:27
Okay, if I save this one, this is how it look like. Let me decrease this size 200
2:51:33
maybe and 400 for now. Uh I want everything in
2:51:40
the center of the screen. So we'll make it flex item to be in the center. Justify
content in the center.
2:51:46
We give margin top to let's say
2:51:52
24. Okay. And then below that I will write S2 tag but I will wrap inside the
2:51:59
div. And here we'll say uh ready to start
2:52:08
interview. Over here we'll add a class name. We'll say font bold text 3 Excel.
2:52:16
Make sure you'll provide a flex column because we want everything one after other.
Uh for this div I'm going to add
2:52:24
a padding let's say six.
2:52:29
And to this image we'll add a class name.
2:52:34
Uh we'll say width full. Okay. And height to let's say 200 pixel.
2:52:44
And here we say object cover. Maybe we can add more. Now for this div I'm going
2:52:51
to add but it's stretching out. So what we can do we can wrap this inside the div.
2:52:58
Okay. So I'll add simply div tag.
2:53:04
And to this do tag I'm going to add maximum width. So we say maximum width to let's
say 3 XL. Okay. But make sure
2:53:10
you provide a width to be four. Something like this. And for this image I will say
object cover.
2:53:17
Perfect. Now you can give some more uh size. Let's say 300.
2:53:23
Perfect. I think that's pretty good. Um here we can add just 14. Not too much.
2:53:30
And then we want to keep this in the center of the screen. So we'll say text to be
in the center. Perfect. And then
2:53:36
we'll simply add a button. And here we'll say start interview. I
2:53:44
will add arrow right something like this. And uh here we'll
2:53:51
say flex column item to be in the center. Perfect. Also you can add space
2:53:59
y to five some gap. Okay. You can add some description over here. So I will
2:54:06
add description. So I just pasted this interview will last 30 minutes and blah blah
blah.
2:54:11
Let's save it. Okay, perfect. Something like this. Okay, one more thing you can
just make this great 500. And then we
2:54:19
have the start button. After this, uh I'm going to add an horizontal line.
2:54:28
Okay. So over here we'll say HR line
2:54:34
or maybe we can add a separator. And below that you can simply uh add an
2:54:41
input box. So here we'll say H2 tag. Um
2:54:47
and if I want to see mockup this is how the mockup will look like. I will just
paste it this text over here. I will say
2:54:55
class name font semi bold text to Excel
2:55:01
and save it. Okay. And below this we'll just add
2:55:08
input inside this we'll say placeholder enter
2:55:15
email address and then we want to add a button
2:55:24
called send perfect obviously the input and button
2:55:30
we want in one line so I will add a do I will wrap this in a do and we'll Say class
name flex gap to five
2:55:39
over here uh we'll say wid to be full but maximum width let's say to excel
2:55:49
and here as well I will give full width I think let me excel only okay
2:55:59
maybe you can give maximum width uh to this do. I think that's much better. See?
Okay.
2:56:06
And then you have the send button. I will wrap this in a do tag so that we
2:56:12
can add some styling to this particular section. So over here we'll say class name
padding to let's say three.
2:56:20
Background gray let's say 100. And we'll say rounded to
2:56:26
2XL. Okay. I think we can add more padding.
2:56:34
And here I will just make it 50 only.
2:56:39
Perfect. Okay. So here uh this option for the user if user want to send to someone
else.
2:56:46
Uh just I will give margin top to two some gap. Perfect. Now on the click of
2:56:52
the start interview we actually need to start the interview process where we are
going to add a streaming author. He will
2:56:59
ask you the question and you have to answer it. And at the last we are going to um
give you give the user the all the
2:57:06
complete feedback about the interview.
AI Streaming Avatar Using AKOOL
2:57:12
Once user click on the start interview we are going to redirect user to the new
screen where we are going to connect
2:57:18
user to a live streaming uh author and obviously for that one we are going to
2:57:24
use an Akul. Akul provide you a streaming author functionality along with there are
lot of different products
2:57:30
you will find on Akul in one of my previous video I used this Aul product
2:57:35
and many user requested some new tutorial on this one and that's why I came with
this Aul's streaming author
2:57:42
features where we are easily integrate with the live streaming agent how cool
2:57:48
right and it's very easy to integrate and that's what we are going to look into
this particular project so click
2:57:54
the link in the description. So we'll jump onto this Akul. Now before start
implementing it, I want to walk through
2:58:01
the step-by-step guide how we are going to uh implement this particular feature.
2:58:06
Okay. Now I connect I divided this particular part into two different section. One
is before interview start
2:58:12
and after interview start. Okay. What are the process and what are the step we need
to follow. So very first thing when
2:58:20
uh before interview actually start right before connecting to the streaming author
agent we need to fetch the
2:58:27
interview question from the database then we need to get a knowledge base
2:58:32
from uh for the aul uh streaming authar that I'm going to tell you how to do it
2:58:37
right and obviously we are we have to create this knowledge base for our
2:58:42
interview author agent after this if the knowledge base is not there then we have
2:58:47
to create that knowledge base over here. We'll fetch it if it's already exist. So
you don't need to create a new one. Once
2:58:55
the we have the knowledge base then we need to initialize the streaming uh
2:59:00
Agora streaming or Aar SDK. Now here is thing Akula and Agora are are already
2:59:06
connected together. Okay, we don't need to deal with uh Agora on their particular
platform. Just for your
2:59:13
information that Agora is a video calling platform and it also provide a
2:59:19
lot of different feature but mainly we are going to focus on Akul because Akul
2:59:25
in the behind the scene they are using the Agora SDK okay for the streaming
platform. Now after performing all of
2:59:33
these step before the interview start then we are going to click on the connect to
start the interview. Now once
2:59:39
user click on uh start interview then we are going to create an Aul agura session
2:59:46
credential. Now this credential we are going to create with the akul and that
credential we need to pass to the agora
2:59:52
in order to join a channel and the chat functionality. Okay and once that is
2:59:58
done you are almost there you you just need to enable some setting like mic
3:00:03
audio etc. Once everything is done, you are able to see the streaming author on
3:00:10
the screen. Okay. And all of these we are going to implement step by step. Now
3:00:16
once uh you start the conversation at the end of the conversation we are going to
store all the conversation messages
3:00:24
which we are going to process with the help of AI model in order to get the
feedback. Okay. Now first thing first
3:00:31
let's implement this particular part. Okay. So before interview start now I will go
back to our application and then
3:00:38
inside the interview where we have this interview id inside this I'm going to
create a new route called start where we
3:00:45
going to start the interview inside this we create a page tsx file
3:00:52
then add a default template and here I will rename this to start interview and
3:00:58
then save it. Now inside the start interview we need to get the interview ID.
3:01:05
I will just make sure this uh field name is correct. So over here
3:01:11
we need to write interview ID is equal to use params.
3:01:17
Now once you have the interview ID you need to fetch the um interview questions. So
over here we say constant
3:01:25
get interview questions is equal to an error function.
3:01:33
Now obviously from the convex so we'll go to the convex we need to write a query
inside the interview.ts.
3:01:40
So over here we'll simply say export constant get interview
3:01:47
questions is equal to query because we want to fetch the data. Inside the
3:01:52
query, you need to pass the interview ID. So, in this case, we'll say interview ID
of type string.
3:02:02
Make sure it's uh you need to add it inside the arguments because this is your
arguments.
3:02:09
Then add an handler with an async with ctx
3:02:17
comma arguments and the arrow function. Inside here we say constant result is
3:02:24
equal to await ctx dot db dot select sorry
3:02:35
dot uh query and we need to provide a table name over
3:02:42
here we say so let's me add a dot where clause
3:02:50
sorry dot filter because we want to filter this one and then we need to add a
condition.
3:02:58
So first we need to write Q dot equal to and then inside this we'll say
3:03:07
uh the left expression. So that's depends on the Q dot not Q dot.
3:03:14
So here we'll say Q dot fill then give the fill name. So depends on the
3:03:22
ID we need to fetch the data. So here we'll say then arguments dot so this
3:03:30
need to be an uh interview record id. We'll say interview record id
3:03:37
okay so meaningful I think and then the last we'll say collect because we need to
select all the data simply in the
3:03:43
last we'll say return result. Now once we define this query in order to use this
query only when the interview ID is
3:03:50
available we'll define a convex using this use convex uh hook. Okay. And then
3:03:57
inside here we'll say constant result is equal to await. Then we say convex. Inside
this
3:04:06
we need to add API dot interview dot get interview question
3:04:14
and then we need to provide a parameters. Okay. So in this case I think we just
have
3:04:21
the interview record ID. Okay. And for this one we'll add
3:04:27
interview ID. I think here we need to pass a query.
3:04:34
And here I will make this as a sync. Just one quick update. So here u this ID
3:04:39
need to be of type ID only. So here we'll say v dot id and
3:04:46
then you need to give the table name. This one
3:04:53
here. uh for now I will add ts ignore okay and then save it. Now this get
3:05:00
interview question we need to call inside the use effect whenever this component
get load and make sure
3:05:06
whenever the interview id is available something like this okay once we have
3:05:12
the result I will first console this result and then save this one now we'll
3:05:18
go back to our application we'll test this out now make sure on the click of this
start
3:05:25
interview you'll redirect it to this / start button so I'll go to the page tsx
where we have the start interview over
3:05:32
here. I will go I will add this link tag with the h reference and then
3:05:37
I will make sure to wrap this inside here we need to add slash
3:05:44
interview slash the interview id. So I need to get this ID. If you don't
3:05:50
have make sure to get that is equal to use params because that we
3:05:57
need to pass inside the router and here means this I inside this link. So here
3:06:02
we will say interview id plus plus / start.
3:06:09
I will just refresh the screen. Now if you are using this hook make sure you'll
3:06:14
mark this component on the client side. And then if I click on start interview
3:06:23
it should redirect it to the start screen. So if right now if you see we are on the
start screen. Now we have
3:06:29
this error because we are using a hook and we did not mention it as a use client at
the top. Whenever you are
3:06:35
using any hook you have to make sure uh you have to implement that on the client
3:06:40
side. And right now if you see we are on the start interview screen. Now if I go to
the inspect panel, go to the console,
3:06:47
make sure you are getting the result and then here we have the result. Okay. So
3:06:53
here we have the interview question. Now make sure you are getting only one
element. Obviously we are getting only one element because we are fetching with
3:07:00
the interview ID. Okay. So uh over here we have one option just you can return
3:07:06
the first element and then save it. And now you'll get just that particular
3:07:12
result. See now once we have the interview questions uh we going to save that
3:07:21
uh all the object for now. So over here we'll define constant
3:07:28
interview data comma set interview data is equal
3:07:34
to use state and here you can define a type as well.
3:07:40
So in the type you'll say interview data
3:07:46
and then mention the type depends on this value. So here we say job title, job
description.
3:07:54
Then we have the job description of type string. Then we have the
3:08:00
interview questions. Obviously uh it is a array. Then we have
3:08:08
the status. Uh status is not that much required and user ID that is also not
3:08:14
required right now but you can add it just for in case we need this
3:08:21
we need this ID. So I will add that too. And inside the interview question if you
3:08:26
see we have answer and a question. So over here
3:08:32
we have answer or maybe we can do one thing uh for the
3:08:39
interview question we'll define a type.
3:08:48
So I will say answer of type string and then we have question
3:08:54
of type string and over here now we can simply define
3:09:01
interview questions and the error of that one. Okay and then
3:09:06
you can define a type. This is how simple it is with the typescript. Now
3:09:11
next time when you want to refer this interview data, it automatically give you the
suggestion which field it is
3:09:17
available to use it. Now over here we say set interview data
3:09:23
with the uh result. Okay.
3:09:31
So over here I think we also need to mention it as a underscore oh sorry uh
3:09:37
optional field with a null. Okay. And then save it. Perfect.
3:09:45
Now this is the one part that we implemented. The next part is to get the knowledge
base. Okay. For the interview
3:09:52
data. Now the click the link in the description for the aul documentation. Once you
are on the documentation, I
3:09:58
will go to this API for now and go to this API documentation. Okay. inside
3:10:04
here uh search for the streaming author.
3:10:09
Inside the streaming author, you need to uh you can see all the information over
3:10:15
here. Okay. But for the knowledge base, you will see an another uh option on the
3:10:20
sidebar called streaming author knowledge base over here. Click on this knowledge
base. Okay. On the right hand
3:10:26
side, you will see a different different API endpoint. the list knowledge base,
create knowledge base, get knowledge
3:10:31
base detail and lot of other thing. Now obviously first thing we need to get the
knowledge B it means the list knowledge
3:10:38
base here this is the API endpoint which is the get call which we need to call it
and we need to obtain the bearer token
3:10:46
for the authentication. Okay. Now obviously uh we did not even log into
3:10:51
the uh a cool yet right but before that in order to make an API call to any uh
3:10:57
AOL endpoints a cool API endpoints then we need to uh pass the uh token. Then
3:11:04
obviously we need to generate this token. So click on this get token and once you
click on it we need to make an
3:11:11
post API call. uh to that post API call you need to pass a client ID and client
3:11:16
secret key which you will get it on the occult dashboard and then it will generate
a token that token is valid for
3:11:23
a more than years okay so if you see one only once you have to generate this token
and then you are good to go so
3:11:29
first thing first uh I will copy this get token we are not going to integrate
3:11:34
into our application this particular API endpoint but uh we are going to make uh
3:11:40
with the help of Postman if you are using Postman or you can go to your local uh
API client in order to send the
3:11:47
request. So I'm using this request bin. So go to the request bin.com. You will jump
onto this website. Here I will
3:11:54
paste this API endpoint. Make sure change this to post. Then go back to
3:12:00
your Aul. Now in this case I will log to aul.com. Okay. If you an account make
3:12:05
sure uh uh to login it. If you don't have make sure to create is free to use.
3:12:12
Then we'll go to the get started. Inside here you'll find an option called API or
3:12:17
you can find it on the top as well. Click on that one. Over here you will find a
client ID and the client secret
3:12:24
key which uh is already for my previous application. But if you don't have uh
3:12:30
create a new API credential over here I will say interview sorry mock interview
3:12:36
app. And then we'll click next. Once you click next, you'll get this client ID.
3:12:43
Copy this client ID and for the sake I will put it inside this.local
3:12:50
file. So over here we'll say client ID.
3:12:57
Okay. And I will paste it here. So I will not lose it. And then secret ID. If
3:13:02
you see it's saying it show only once. Okay. So over here we'll say client secret
id is equal to and paste it here.
3:13:11
And then once you copy it just close this one. Now we have to go back to the
3:13:17
documentation and inside this post request we need to pass client ID and client
secret key. So inside the body
3:13:24
parameter. So this oh sorry this is our API request. I will go to the body
parameter. Inside here
3:13:31
we need to create a client. I will just copy this text client ID and client
3:13:36
secret key.
3:13:46
And this is how you need to pass. We already have this client ID and client secret
key. I will just paste it here.
3:13:57
Something like this. Okay. Once you have that, make a request. Once you make a
request, you will find this token. See
3:14:03
how quickly copy this token because we want all of this. So I will copy that.
3:14:10
We'll go back and here we'll paste it inside the env.local file. So here we'll say
api
3:14:17
token and then paste it here. We don't need to add this double quote.
3:14:23
So I will remove that and then save it. And that's how you have to generate the API
token. Okay. Once you have your API
3:14:31
token ready, now I will go back to our previous page where we have this
3:14:36
knowledge base. Now we will get this knowledge base first. So we go to the
3:14:41
knowledge base list knowledge base and here we need to make a request.
3:14:46
So I'll create a new API endpoint inside the API. We'll call it as a cool
3:14:56
knowledge base. Okay.
3:15:03
Inside this we'll create a route.ts file and then we'll say export a sync
3:15:09
function. It is a get request. So we'll say request
3:15:14
next request. Now inside here
3:15:19
we need to pass the um knowledge base id okay from it we'll get to know whether
3:15:25
that knowledge base is already exist or not so we are implement step by step don't
worry we are not going to skip any
3:15:32
uh lines okay now in order to make a call we'll copy this get request okay
3:15:40
and then here we will say constant result is equal to await
3:15:45
exos dot get then paste this endpoint inside here
3:15:52
we'll pass an header inside the header we need to pass an authorization and here
we'll say bearer token and for a
3:16:00
bearer token we already have that token right here I will use this tag and then we
say
3:16:08
process dot environment and then copy this environment variable name which you
3:16:13
want to class. Once you have that
3:16:18
uh obviously you can return the result. So over here we'll return next response
3:16:27
dot JSON result dot data. Okay, only
3:16:33
data which you want to pass. Um right now I think let's test this
3:16:39
out. So I will go to the start uh page where we need to call this
3:16:44
method. So we'll say constant get
3:16:49
knowledge base
3:16:54
knowledge base and error function. Inside here we'll say
3:17:02
constant result is equal to await exos
3:17:07
do.getate/ get slash API slash
3:17:14
a cool dash knowledge
3:17:22
base and then uh that's all we need to do right now. So inside the console
3:17:27
we'll say result here I will make this as a async. Okay, obviously we just need
3:17:33
to add one knowledge base. Okay, now this get knowledge base we need to call inside
the use effect
3:17:40
and then save it. Now let's test this out. So I'll go back. I will refresh this
screen.
3:17:47
And inside the console, we'll see whether we get the knowledge base. And if you see
inside the data on line page 42, we have these two data. Okay, so it
3:17:56
means we have the two knowledge base for this token ID which I already recreated.
Okay. And these are the two knowledge
3:18:04
base we have. Okay. With this prompt and all of this information
3:18:10
but for you if it it's not there don't worry because we are learn now how to create
a new one. But if you want to
3:18:17
delete that knowledge base you can even delete it as well. Okay. So it's up to you.
So right now I will just pause the
3:18:23
video. I will delete it. So we'll start everything from the scratch. Okay. Somehow
it's not get deleting but you
3:18:29
can try this out. Okay. Uh once um you have this knowledge if you don't have
3:18:34
any knowledge base then inside the route we're going to check. So here we say if
3:18:40
result dot data or we can look for the specific knowledge base with the name.
3:18:46
So if I go to the data right inside here you can search with the name as well. So
3:18:52
here we'll say if the result dot data or maybe at the top we can say constant if
3:18:59
exist is is equal to data or sorry result
3:19:05
dot data dot data dot list
3:19:11
dot find here we'll say item of type any.
3:19:20
So we say item dot name dot trim
3:19:27
is equal to equal to and this uh particular name let's say
3:19:33
interview agent pro okay if that ID is not there
3:19:43
I will just compare without trim and we'll check if it exist or not okay
3:19:49
If is not exist then we'll create new knowledge base. Now in order to
3:19:57
create a new knowledge base we'll go back to this uh documentation. Here you have
option called create knowledge
3:20:03
base. Copy this endpoint. Obviously this is a post request. So make sure we add
3:20:08
constant uh response is equal to await aios.post.
3:20:16
Paste this endpoint. inside that we need to pass an header. I will copy this
authorization as it is over here. Okay.
3:20:25
And now to this knowledge base we need to pass few parameters. If you see we
3:20:30
can pass a name. So in this case uh maybe
3:20:37
we'll say name. Oh, so over here only you need to pass.
3:20:47
So just click enter name. So here we will say interview I want to give same
3:20:53
name. Okay. So next time it will not create. Then we need to pass a prologue.
3:20:59
Now prologue is an opening or greeting message. Okay. So that is very important. So
I will add that too. So
3:21:06
here we'll say tell me about yourself as a U first question you can say. Then we
3:21:15
need to pass a prompt. If you see this is the prompt that we need to pass.
3:21:21
Now for the prompt I will go back to this uh documentation. I already have
3:21:27
this prompt. You can use this and then paste it here. Okay. So here we'll add this
tag and then I will paste it. Now
3:21:35
it just saying that you are friendly job interviewer and you have to ask one uh
3:21:41
the following question one by one. Now over here obviously we need to provide the
questions list. Right now make sure
3:21:47
you'll get this question list. So we'll say constant questions. Okay. And then is
equal to
3:21:53
await request dot JSON. Now obviously we need
3:21:59
we cannot pass it to this query parameter. We need to convert this into a post
request so that we can pass it to
3:22:06
the body. So here I will make this post. Okay. And then save it. Obviously inside
the start I will make this as a post
3:22:13
only. Okay. So remember this to update uh get
3:22:18
request to post request. And these questions now I'm going to pass over here.
3:22:25
Something like this. Okay. As simple as that. And that's how our prompt is also
ready. Next parameter is document or
3:22:33
URL. If you have any document uh file or URLs that also you can directly pass uh
3:22:40
as a knowledge base. So you don't need to do any implementation. Uh a obviously
3:22:46
take caring of your knowledge base from the documentation or from the URL. But in
this case is a simple text prompt
3:22:53
that we are providing. Okay. Now we already have a hither and everything. Now once
uh the request is ready you can
3:23:02
just console it. So over here we'll say console not
3:23:09
console but let's console the result. So we'll say response dot data. Okay. And
then inside the
3:23:17
return we'll say next response dot JSON result or response dot data. As simple
3:23:24
as that. And then save it. Now once you save we'll go back and we'll test this
3:23:29
out. But don't forot to pass the questions inside the body. So here we'll
3:23:34
say questions and in order to get these questions you
3:23:40
can say interview data dot interview questions.
3:23:48
I think that's all we needed and then save it. Now let's try this out.
3:23:54
So right now if you see uh as soon as we save we got an error. So in order to
3:24:00
check the log I will go to the console inside the console you will find uh this
3:24:05
particular error right. So it's saying it exist and then it give the error. So
3:24:11
over here you don't need to pass a list. It's just result data data. Okay. And now
if I refresh this let's see. And
3:24:18
boom. If you see in this case we got okay. So we got a message saying authorization
cannot be empty. Okay. So
3:24:25
somewhere we miss we did not pass a correct authorization. Oh, so over here we need
to wrap this
3:24:31
header as a third argument. Okay. Maybe um
3:24:39
we need to wrap like this
3:24:46
and again this one. Okay. So it just mismatch of the curly braces. So make
3:24:52
sure to fix this. Now we'll go back. We'll refresh this screen
3:24:58
and we have the result. It's saying okay. And boom. If you see we have brand
3:25:04
new u name with the prologue and the prompt as well. We have we have complete
3:25:09
prompt. Inside the prompt if you see uh the question is undefined. We'll fix
3:25:14
that issue in a moment. But right now we are able to create the prompt
successfully.
3:25:20
Now one more important thing here you need to consider that our prompt need to be
different every time. Okay. If you
3:25:27
want to use existing prompt you can use but every time the questions are different
and then we need to use a
3:25:33
different prompt every time. So even though if you did not call this method that's
completely fine. Okay. And then
3:25:40
we'll also uh not use this exist method.
3:25:45
But just for your example purpose I added this get request so that if you are using
any agent that need to be used
3:25:52
for the same purpose then you can use this uh same knowledge base and
3:25:58
regarding the questions right it's not working because we are calling interquation
and immediately we are
3:26:03
calling knowledge base without fetching the question list. So I will just move this
get knowledge base after the
3:26:10
interview data is there. Okay. And I think let's pass this interview data as
3:26:16
it is to this result over here. We'll say um or maybe we can use another use
3:26:24
effect and once the interview data is there so here we say interview data is there
then
3:26:32
only call get knowledge base
3:26:38
and then save it. Now if I refresh this screen obviously uh we might not get so if
you
3:26:46
see it's saying already exist right the knowledge base is already exist so
basically what we can do we can add a
3:26:52
time stamp so here we'll say date dot now so what it will do it will create a
3:26:57
new name every time and new knowledge base every time and boom if you see now we
have oops I
3:27:05
think this one now we have the new knowledge base Okay. And obviously we have the
3:27:11
questions which is object object it's written out. That's completely fine because
uh it's actually a JSON, right?
3:27:17
So that's why. But I hope you understand this one. If you want to see the actual uh
questions, you can just change this
3:27:25
to a stringify and then if you refresh the screen,
3:27:31
you will see the result. So over here
3:27:37
and then you will see this interview question see. Okay. So that's how the
3:27:43
next step is we need to initialize the Akul Agora streaming author SDK. Now uh
3:27:49
I'm going to follow little bit in different way that I already put the link in the
description about this HDK.
3:27:56
Okay. Now this streaming SDK is from the AOL only. So don't worry about that.
3:28:01
First we'll copy this. Then we'll go back to our application inside the new
terminal. Just make sure to install
3:28:08
this. So it will install this SDK. Next we need to create an instance of this
3:28:13
SDK. So we'll copy this and inside our page.tsx file
3:28:24
maybe we can just collect this. We'll create another use effect. over
3:28:30
here we'll create an use effect inside this just paste this HDK make
3:28:38
sure to import this and here we'll say HDK only in small
3:28:44
uh I will copy this import statement like this so make sure it is installed
3:28:50
so right now okay so we got an error due to the permission so over here if you are
using MacBook make sure to add sudo
3:28:58
this link Let me clear this at the start for a
3:29:04
windows. I don't think so you will get any error. Okay. Uh if you get any error,
make sure to uh
3:29:12
install this. Then once you define this, if you not if you see we don't have any
3:29:17
error. Next is uh we need to register that different different event handler.
3:29:23
Okay. So I will copy everything as it is and then over here
3:29:31
inside this use effect only I'm going to paste it as we are using HDK short form
3:29:37
I will just replace with this short form SDK and here we have different different
3:29:42
event now inside this on user publish I'm
3:29:48
going to remove this okay so we're going to um use in different way. So for the
3:29:54
video I will say user dot video track dot play. Okay. And then
3:30:02
we need to play in our div tag. Obviously we need to define a container. So I will
call it as a video container
3:30:10
reference dot current. Now if you don't have this container mentioned we'll
3:30:16
define at the top. So over here we say constant define this
3:30:22
container is equal to use reference and initially I'll put it as a null. You
3:30:29
can mark this as a type any after this for the audio
3:30:36
I will say user dot audio track dot play. Okay I'm just
3:30:43
simplifying the all the logic and then save everything. Once you save over here
3:30:49
we need to uh uh we will define one state okay in that one we need to save this uh
HDK uh instance. So over here we
3:30:58
say constant agore we say Agora SDK set Agora SDK
3:31:09
is equal to use state and you can provide a type generic Agora
3:31:16
HDK or null and oh so this need to be a type
3:31:25
something like this. Okay. And at the end of this one, we'll just set this
3:31:30
Agora SDK with the SDK instance. After this, you can even clean up. Okay.
3:31:36
So, inside the return, we'll just say H S H S H S H S H S H S H S H S H S H S HDK
dot live chart.
3:31:44
Then HDK dot live channel. If we are not using anymore right it's always good to
3:31:52
uh clean the clean this all the um uh instance okay and then simply save it
3:32:01
now as you are using use effects okay so make sure you you will execute only once
3:32:06
so don't forget to pass an empty array and then save it and that's all so our
3:32:12
this particular step the Agora SDK initialization is now ready. Now if I go
3:32:19
back to our application, go to the inspect panel and just make sure you
3:32:24
don't have any error. And if you see it's saying your agura instance is
3:32:29
created. Okay, it means it initialize successfully. Perfect.
3:32:36
Now the next part is the start interview where we need to create an Aul agura
3:32:42
session credential. So uh first thing we'll go back to our application and
3:32:47
here we going to define a container as we are already uh want to load the
3:32:55
outar right on inside this div. So for that one we need a container which we the
reference we we already defined. So
3:33:02
over here we'll say div inside this div uh provide the reference. So here we'll
3:33:07
say video container reference. Then we'll provide an id for this container.
3:33:13
So we'll say container
3:33:18
ID. Okay. And we'll define this container ID at the top.
3:33:24
So this need to be an container ID.
3:33:29
So at the top I will say constant. Oh I I think I did not copy that. Let's
3:33:35
copy this and then paste it here. And you can define you can give any name for this
3:33:42
container ID. I will say um let's say akul
3:33:47
authar container. Okay. Along with this one uh
3:33:53
we need an author id. So we'll say constant aar
3:33:58
id which you can get it from the aul from the API. The one of the id is uh
3:34:04
which I'm going to use and I'm going to tell you how to get this all this ID. Okay.
3:34:11
So this particular ID I already have. So I'm using this one as well. Now next
3:34:19
we'll go back and in for this particular div we'll apply some styling. So over
3:34:25
here we say style. Inside the style we'll provide a width.
3:34:31
Uh I think we added extra curly braces. So over here we we'll say width of let's
3:34:36
say 640. Uh let's add some height. Let's say 480. We'll change this one. Okay. Then
the
3:34:43
background. I will add a black background. So we'll say hash 0000.
3:34:50
And then we'll add some margin top. Let's say 20.
3:34:56
Next uh we'll add a two button. Okay. Uh so over here maybe we can add it below
3:35:03
this due. So one button to mute the mic and unmute
3:35:11
the mic. Okay. So over here if mic is on. So I think we need to define
3:35:17
one state. So we say constant mic on, set mic on is equal to use state.
3:35:25
Initially it will be false. And here we say if mic on
3:35:34
then we'll say mute mic. Obviously we want to change this
3:35:41
all the styling and all this but just for the testing I'm going to add some data
and we'll add one more button.
3:35:51
Uh here we'll say leave conversation.
3:35:56
Okay. Um then we also want a button to start the conversation.
3:36:02
So we'll create a button. Here we'll say start conversation.
3:36:11
For this button I'm going to add on click method. And here we're going to create a
start conversation
3:36:18
uh method. Now inside the start conversation we need to create an aul
3:36:24
session. Okay, a cool Agora session that we just uh define in the step. So this
3:36:29
particular step now in order to create this simply we'll go to the uh AOL
3:36:35
documentation inside this AOL documentation we file this streaming author go to the
3:36:41
streaming outer option and here you have option called create session we need to
3:36:47
call this particular API endpoint in order to create a session. So copy this.
3:36:52
Obviously um we need to create a new API endpoint inside the route. We'll keep uh
3:36:57
sorry inside this API. So I will create a new folder called aul
3:37:03
session. Inside this we create a page route.tsx
3:37:09
file. Over here we'll say export a sync
3:37:14
function post. And this is the request. So we'll say next request. Now inside this
we'll
3:37:23
say constant result is equal to await axios dot post and simply paste
3:37:31
this endpoint. Inside this post method we need to pass an author id. Okay. So
3:37:39
if you see this parameter inside the documentation, you need to pass author id
which is the required field and you
3:37:46
can pass the knowledge ID so that that particular author will uh
3:37:52
will will uh answer and will uh train on our uh knowledge right. So for the
3:37:59
author id we we can get this author id from here we we already define. So two
3:38:04
parameter we need to get it to this post API call. one is the author id and another
is knowledge base ID. Okay, the
3:38:12
short form I put it as a n kb ID. Here we'll say await request dot JSON. Now
3:38:19
here I will pass author id as author id and then we need to pass the knowledge
3:38:25
ID as well. For the knowledge ID we'll say KB ID.
3:38:31
Once we have the result, we'll say return next response
3:38:37
dot JSON and inside this we'll say result dot data and then save it.
3:38:46
Over here obviously inside the start conversation we need to call this API.
3:38:51
So we say constant result is equal to await exos dot post/
3:39:00
API/ a cool session and inside the post API uh we need to
3:39:08
pass two parameters. one is the author ID. Copy this field name which we
3:39:15
already have this author ID and then another is the knowledge ID.
3:39:22
Right? Now this knowledge ID when we get the knowledge ID we need to save this in
some uh state. Okay. So we'll define so
3:39:30
we'll say constant KB id comma set KB id is equal to use
3:39:36
state
3:39:43
and I will just over here for now uh in order to get
3:39:49
knowledge base right we'll see what data we are getting inside the result. So if
3:39:54
I refresh this screen, we'll get the knowledge base information, right? So
3:39:59
this is uh not this one. So this one. So inside the data, we again have the data
and then inside this we have underscore
3:40:07
id. So make sure we'll set the KB ID as result dot data dot data ID.
3:40:19
And that's how we'll get the KB ID. this KB ID obviously now we going to pass over
here okay as simple as that as we
3:40:28
are using a let make this as a async and then inside here we'll get result dot
3:40:33
data now here we'll just saying create a cool
3:40:40
session next thing uh we'll check until this point whether we are getting a data or
3:40:46
not right right now if you see we have this blank screen where we have a button
called start conversation Okay, we're
3:40:52
going to update this in a moment, but for now, let's click start conversation.
Okay, let me refresh the screen first.
3:41:00
So now everything we have say start conversation. So right now we get an error. We
have an error. We'll find
3:41:06
inside the console. What's the issue? So let's scroll down and over here if you
3:41:13
see it's saying invalid URL. Okay, so maybe because we use this post text. So
3:41:20
let's delete this post text. That's the reason. And now uh
3:41:28
we got this uh not this one. I don't think so. This is anything. But if I click on
start conversation again, it's
3:41:34
saying authorization cannot be empty. I think we forgot to pass the header. Okay.
So over here, don't forget to pass
3:41:41
a header. Inside the header, we need to pass authorization. I will copy this
3:41:46
authorization. same like previous one,
3:41:52
right? And then save it. Perfect. Now let's click start conversation.
3:42:00
And so it's saying the author uh you are
3:42:05
trying currently is busy. Please try again few minutes. The priority access to
create a custom fine-tune reached out
3:42:10
our sales team and sales. Okay. So currently the author which we are trying to uh
use it right it is currently busy.
3:42:18
Now uh the question is how to get a different author. So it's quite easy. So
3:42:23
if I go to the author inside here you have option called get streaming author
3:42:29
list. Just click on that. Here you will find an author list. Right now I'll execute
inside the
3:42:35
uh rest API where make sure to pass a beer token in order to make a call here.
3:42:41
Make a get request. Simply click send. And then here you'll find a different
different author list. You'll find an
3:42:48
author uh ID. See this one. So you can use any author ID. For example, let's
3:42:55
use this one. Uh I will update this author ID inside
3:43:01
our page.tsx file at the top where we define this.
3:43:07
And let's try this out. So you have to test this out. Um sometimes uh the author
might be busy so you can use the
3:43:15
author which you think that it's ready to use. Okay. Now over here again uh if you
see now we
3:43:22
get the credential. Okay. So inside the credential we have this agora app ID
channel token UID that's what we needed.
3:43:30
Okay. So if you see it is inside the data under the credentials. So make sure
3:43:35
to save that in one constant. So here we'll say constant
3:43:41
credentials okay is equal to await not a sorry uh
3:43:47
respon result dot data dot data and
3:43:53
credentials okay so inside this we have this credentials
3:43:59
perfect now once we have the credential we need to connect to Agora
3:44:07
um channel and start chart. Okay. So over here we'll add a condition. If
3:44:16
the credential is not there then simply we'll throw a new error saying
3:44:24
missing credentials. Then we'll say await agora SDK dot join
3:44:33
channel. And inside this joint channel we need to pass a few parameter that you
3:44:39
will get it on on a GitHub uh page. Okay. So over here if you see these are
3:44:45
the field we need to pass. We we we just join the channel. Then we need to join the
chart. So
3:44:52
let's copy here and paste it. Okay. Then we need to simply use this
3:45:00
join chart method. Okay. So over here we'll say Agora HDK
3:45:08
dot join chart. I don't know why we get this error. So it's saying Agora HDK is
3:45:14
possibly null. So to fix this issue I will say if not Agora HDK then return
3:45:22
sorry uh return empty. Okay. And I think now we don't have any error. Now for the
3:45:29
mode you can select dialog mode and one is for the repeat mode. Repeat mode means
whatever you talk it will repeat
3:45:35
you and for dialog mode it will actually speak. So here we'll say two. Now for
3:45:41
the voice id okay you can get it from the agora. So one of the voice ID I have
3:45:46
is this one vit. So here we have net a. Okay. Uh
3:45:55
obviously I will list out more uh voice ID for you. And the next thing is uh we
3:46:00
need to toggle the mic. Okay. So you can enable the mic as well. So you don't need
to configure uh through the react
3:46:08
it automatically uh enable for you. So here we see agora HDK dot toggle mic.
3:46:14
Then you can set the mic on to true. Okay. And then
3:46:21
um I will define one state whether it's join or not. So we'll say constant join
3:46:27
comma set join is equal to use state and initially it will be false. Once it join
3:46:35
we'll set the join as true. Okay. Now whenever the join is true so here if not
3:46:42
join then only show this button
3:46:48
otherwise show this new conversation button. As simple as that. Okay. Now
3:46:55
once you want to leave the conversation means you want end the call. Okay. So
3:47:01
we're going to simply add a constant leave conversation
3:47:10
inside this here. If you say if Agora SDK is not there return nothing.
3:47:16
And then here we'll say await agora SDK dot leave chat.
3:47:22
Then await agora SDK dot leave channel. Await agora SDK dot close streaming.
3:47:31
Okay. And here we'll say set join to false and set mic on to false. Okay. And
3:47:39
here we'll say a sync. Now everything uh you can refer directly from the u this
3:47:45
GitHub page. Okay. Everything is mentioned over here. Now this leave conversation
we need to attach to this
3:47:51
button. And for a mic as well in order to mute and unmute the mic we'll say toggle
mic.
3:48:00
Here uh we'll say await agora agora SDK dot toggle mic.
3:48:08
And here we'll say set mic on to agora SDK dot is mic enable. Okay. So
3:48:16
this has a function called is mic enable it will automatically return for us.
Obviously here we need to write if a HDK
3:48:22
is not there then return nothing. I will make this as a sync. Now
3:48:30
this toggle mic I will connect um I think we can connect to this button
3:48:40
on click. Perfect. And then save it. Now let's take this out complete scenario of
3:48:47
okay if you face any issue any problem we'll just fix this right now I will say
3:48:52
start conversation right now if you see this conversation
3:48:58
is started uh so there is a one uh line that we miss
3:49:06
so inside the onus user publish if I go to this um documentation
3:49:12
over here Uh if you go to the top you need to add this get client subscriber.
3:49:18
Okay. So maybe over here I will just copy this
3:49:27
and also you can copy same thing inside the audio too.
3:49:34
That is important uh as we are using HDK. So make sure to update this as a
3:49:39
HDK and then save it. Once you save, we'll go back. Let's refresh the screen.
3:49:47
And I'm just opening this console. If we have any error, we can observe this. And
let's start the conversation.
3:49:59
And boom. If you see, we have this beautiful. Say hi to her.
3:50:06
Hi there. How can I assist you today? But that's weird. I just ended the call.
3:50:12
The voice is not matching, right? We have the girl and obviously our voice is not a
female one. So you can simply fix
3:50:19
it by updating the voice ID. But until this point, I hope you understand
3:50:25
everything. The how we step by step implement the feature and our streaming
3:50:30
authar is ready. So how you speak depends on that one. The author will give you the
response as our author is
3:50:37
connected to the knowledge base. So he will ask the question about the uh interview
related uh query and all.
3:50:44
Okay. But right now I hope you have u you did not miss any points. If you have
3:50:50
any question let me know in the comment section. Now obviously we have to um
properly display everything. We have to
3:50:56
fix if there is any bug and then we'll test the final demo as well that how
3:51:01
actually it works. Okay. Along with the uh this particular UI styling everything
that we are going to update now.
Style Interview Screen UI
3:51:11
Now it's time to style our component so that we can uh implement a proper uh
3:51:18
functionality into our application. If you see this on mockup is very rough but on
the left hand side we want to show a
3:51:24
user author along with the controller where you can start the communication and
start the interview and on the right
3:51:29
hand side uh as you start uh giving interview you'll see your uh translation
3:51:36
in a live mode. Okay. So that will be on the right hand side. So obviously we need
to divide the screen into two
3:51:42
parts. So we'll go back to our application and inside the start page.tsx file.
First I will divide the
3:51:49
screen into two uh section. So inside the parent view we'll add a class name.
3:51:55
We'll make it flex and flex column. But when the screen size is large we'll make
3:52:01
flex row. Okay. because you want to show another div into that one. Then we'll also
add a
3:52:09
width full minimum height to screen and you can add a little bit background.
3:52:16
So let's say background gray 50 and then save it. Now for this
3:52:21
particular due where you want to uh show the interview aar and all. So here I
3:52:28
will add a due for that one.
3:52:34
the complete div and another due for the uh charts. Okay. Now the f first do you
3:52:42
can mention a minimum width as well. So over here we'll add a flex flex column
3:52:48
first then I will add a padding to six and whenever the screen size is larger
3:52:54
we'll add a width to 2x3. Okay. So out of the complete screen two by3
3:53:03
uh screen is assigned to this particular div and if you want you can add a border
3:53:08
as well or we can just leave it for now and same thing you have to do but in this
case
3:53:15
for this we say flex then flex flex column padding to six and whenever
3:53:21
screen size is larger we'll just assign one/ird of the screen size and then save
3:53:27
Now if I go back this is how it looks on the right hand side if you see this merge
area is for the chart and now on
3:53:34
the left hand side we have this section. Perfect. Now let's style each section.
3:53:39
First we want to add some styling to this uh container reference. So over
3:53:44
here we'll add H2 tag and we'll say interview session.
3:53:51
Over here we'll add a text to Excel font bold margin bottom to six.
3:54:00
Now I will make sure that all item in the center of the screen. So I will add item
to be in the center. Something like
3:54:05
this. See I can make this 4 XL little bit bigger.
3:54:12
Oh, so this need to be a text for Excel. Okay. Now I'll make this two. Okay. Next
3:54:19
thing uh we have this div right I will keep everything as it is but over here I
3:54:25
will add a class name I will make a rounded corner so we'll say rounded to
3:54:31
let's say 2 excel then we'll say overflow hidden
3:54:37
we'll also add a border to this one and along with that we'll say background to
3:54:43
white flex item to be in the center and justify enter because in this uh div we
3:54:51
want to add a placeholder right so if user is not join
3:54:57
so here we'll add a condition or not condition but here we we're going to add some
placeholder so inside the div I
3:55:04
will add another do and then over here we'll add a user icon
3:55:10
okay from the lucid react over here just mention some size and then inside the
3:55:16
class name we'll make text gray 500.
3:55:21
Okay, something like this. So if you see uh that user icon is showing on the
screen. Now that is only enabled when um
3:55:29
the user is not join. Okay, if you want you can remove this background color.
3:55:34
You can add if I remove this you can if you see now it's a background white color.
Okay, so it's up to you how you
3:55:41
want to show that. Uh next uh we want to add a controller right. So
3:55:48
I will remove this all of this controller and obviously the controller you have to
add little bit logic. So I
3:55:53
already added this controller code inside the uh eraser doc. So if you see
3:55:59
over here I already mentioned this is a UI for controller. So I will just copy that
and then paste it over here and
3:56:06
save it. And once you add this, make sure to uh import this all the uh icons.
3:56:13
Okay, that is very important. So like mic, mic off
3:56:18
and phone off as well. Over here uh on the click we have this start
3:56:24
conversation. So and I don't think so we added the loading state.
3:56:30
So if you don't have the loading state, I will just mention that. So here we say
loading set loading is equal to use
3:56:38
state and initially it will be false. Now you can mention that loading because this
is very important. So when you
3:56:44
start the session so if you scroll down here we can uh here we have this start
session right. So basically you can set
3:56:52
the loading to true and once it is finished at the end you can set the
3:56:57
loading as a false. Okay. Now let's save it and let's take this out. this
3:57:03
completely white and boom. If you see we have this beautiful button now called
connect call and then once you click on
3:57:10
this it will start connecting to the streaming authar for the interview
3:57:16
here uh if you see we have this blank white okay because we added the minimum
height to screen so what we can do just
3:57:22
scroll down a little bit over here I will add height to make sure it's a minimum
height to
3:57:28
screen so that's the reason it was not showing but now it's perfectly fine there
was a spelling mistake now on the
3:57:35
right hand side. Uh for now I I'm going to add a chat messenger box. So we'll
3:57:41
scroll down a little bit. Over here we'll add an H2 tag. Inside this we'll
3:57:47
say conversation. Class name we say text large.
3:57:55
And then font we can give semibold and margin
3:58:01
Y to let's say four. Then
3:58:06
inside this we want to show all the message list. Okay. Right now I will keep as it
is because once we have all
3:58:12
the conversation then we can simply display it. Now let's test this uh
3:58:18
complete scenario. So I will just say connect call. And if you see we have this
beautiful disabled button state.
3:58:24
Okay. Once the call is connected you will see we have the mute and end call button.
Hey what's up?
3:58:33
Hello, I'm here to help you with any questions or information you need. What can I
assist you with today?
3:58:40
You have mute call button as well. And then if you don't want, you can simply end
the call. Okay. And that's how our
3:58:47
simple clean UI for the U video call is ready. You can even show your video at
3:58:54
the bottom of the screen. It's up to you how you want to display. Now for the
conversation first we need
3:59:01
to save the all the conversation in one state. So over here I will define a state.
We'll say constant
3:59:09
messages, set messages is equal to use state and
3:59:16
we'll define a type in a moment. So over here I will define type messages
3:59:25
and inside here I will add a from. So either it is from
3:59:32
the user because if you see inside the inspect panel uh if I go to the console
3:59:38
we have the message from. So over here let me scroll up where we
3:59:45
already we had some discussion.
3:59:55
So over here if you see we have from one value is a board and one value is a
4:00:01
user. Okay. So either board or user.
4:00:08
Oh. So just remove the extra curly braces. And then we have another value
4:00:13
called text. Okay. So text is of type string. Now I'm going to simply add this list
of
4:00:21
messages. Something like this. and then save it. Now inside this use effect uh
4:00:30
so if you scroll down we have this messages. All right. Once you receive this
message you can simply
4:00:38
save it. Right. So here we say set messages dot
4:00:44
here we'll say previous message and then dot dot dot previous message
4:00:51
with new message. So we'll say um message dot P or PL.
4:01:00
Oh, so over here this need to be inside the square braces. And here I will
4:01:05
provide a type any. I think you can provide a type messages as well but not sure
why we are getting error but it's
4:01:12
better you can provide it as a any and then save it. Once you define these
messages,
4:01:18
you can simply go to this conversation section and inside this
4:01:26
you can add a due tag. Inside the do we'll add a messages. So we'll say if
4:01:31
messages dotlength is equal to equal to zero then we can simply
4:01:39
add a div and inside the div p tag saying no messages yet. Okay.
4:01:49
Otherwise we can simply show the list of messages.
4:01:55
So we can say messages dot map message, index arrow function
4:02:03
and then we can add a div. Now inside the div I will add
4:02:12
simply h2 tag to show message dot text.
4:02:17
For a div I will add a key as a index and then save it. Now for this uh
4:02:24
particular div we can add a class name make it flex one then overflow
4:02:31
y at because vertically we have to make sure it will scroll it add some border we
say border gray 200 I will make a
4:02:38
rounded corner as well so I will add rounded excel padding to four and then
4:02:45
space y to three okay between the all all of these messages for this uh h2 tag
4:02:52
as well. You can add a class name. We'll add padding to three.
4:02:59
And then depends on whether it's a it's a user's message or AI message, you can
just add
4:03:05
in a quote something like this. So first we'll add a curly braces then
4:03:11
this quote and then you can add a condition. So over here we'll say if
4:03:17
message. So inside the dollar use dollar write a condition if we say if message
from is
4:03:24
equal to equal to uh AI then we can simply add background let's
4:03:33
say blue 100 then we say text blue
4:03:39
darker 700 and self start okay so it will be at the one end and otherwise
4:03:48
we can add background green 100 and text
4:03:54
green 700. Okay. And then we'll say self in
4:04:00
and I think that's all we needed. And make sure to close this curly braces.
4:04:12
So this need to be uh user and then we have the boat right. So
4:04:20
make sure to add that. I think that's all we need. Let's save this one and let's go
back to our application
4:04:27
also. Um let's add a rounded to let's say large. Okay. And then we'll say
4:04:34
maximum width to 80%. Because we want don't want a complete weight to uh
4:04:39
capture. And then save it. Now let's test this out. So right now if I click
4:04:45
on connect call
4:04:50
hey how are you? I'm just a computer program so I don't
4:04:56
have feelings but I'm here and ready to help you. How can I assist you today?
4:05:02
Perfect. It sounds good right?
4:05:08
Yes it sounds good. I'm here to help. And if you see our message is getting
4:05:14
rendered but there are some empty uh value is getting uh render as well. And
4:05:20
also we need everything in one line. So that also you can add it. So let's fix
4:05:25
this issue. Now whenever the message is blank we just avoid uh adding it. Okay.
4:05:31
So over here we can check if message
4:05:37
dot pl dot u text
4:05:43
dotlength is greater than zero then only add it.
4:05:51
So over here it's saying does not exist. That's completely fine.
4:05:58
I will I will just ignore this. And at the bottom
4:06:05
we're also going to add some uh padding. So over here
4:06:14
we say ma maybe over here we say margin top to one. Okay. And then save it.
4:06:22
Haveings but I'm here and ready to help you. How can I assist you today?
4:06:30
And now if you see we have this beautiful messages list. Okay, that sounds good.
Perfect.
4:06:36
Uh now obviously you can add more styling, more uh modern UI into this
4:06:42
one. It's up to you how you want to display. But main focus is our the
functionality. The functionality is
4:06:47
working as expected. here quick thing uh you have to mention
4:06:53
this screen uh I will just add it to
4:06:58
this particular div okay so that's one thing and one more thing that we want to
4:07:06
zoom that author uh so that it will look like a profile image okay so what we can
4:07:12
do um obviously it will speak something you're asking about a profile image but
4:07:17
I need more context to provide the specific answer looking for information on how
to create a profile image, the
4:07:23
importance of profile images on social media or something else, please provide more
details.
4:07:28
So, so just click on this particular video and if you see this video tag right to
this video tag, I will show you
4:07:34
how it looks. So, first we'll implement a transform to this one then we can scale
it and along with scale we can
4:07:42
just translate to Y. Okay. Now we want to translate to Y but here we can say
4:07:49
let's say 15%. Okay something like this. See and then
4:07:55
this transform actually we need to add to our um you can add it to the global CSS
as
4:08:03
well. So let's do this. So I will copy that. We'll go back to a global CSS file
4:08:08
and at the top we'll add dot video and simply implement
4:08:15
that. But don't forget to add this import button. Okay. So next time it will show
you uh it will show the screen
4:08:22
uh with the only face of that particular author. So that's all for this particular
4:08:29
chapter. If you have any question any doubt let me know in the comment section.
Quick Update
4:08:37
Now there is a one quick update that I wanted to inform. Sometimes uh the knowledge
base from the might not work
4:08:44
when you create a session and that's why author will not understand what to ask
4:08:50
and where from where it start right now to fix this issue is very quick and easy.
Now if you implement that one you
4:08:57
don't even need to implement a knowledge base. Okay. So uh over here you need to
4:09:04
write a prompt. So whatever the prompt we have I will just copy that and I will
paste it here. So here we say
4:09:11
prompt and then simply paste it. Okay. Uh over here this need to be an
4:09:17
interview data dot interview questions and then we map it. Okay. So this is our
4:09:23
prompt. Now this prompt you just need to send it. So here we'll say await agora
4:09:29
SDK dot send message. Okay. And then simply send this prompt. Now what it
4:09:34
will do uh our aar will understand what action need to take very initially and
4:09:41
then it will start the question asking the question one by one. Uh don't forget to
add this line saying that after the
4:09:48
user respond ask the next question in the list. Do not repeat the previous
question. Right. And same thing uh it
4:09:55
will start with the tell me about yourself and like that. Okay.
4:10:01
Obviously you can customize this message as well. And let me test this out. So once
you refresh the screen let's
4:10:07
connect the call and now we'll discuss it.
4:10:13
Tell me about yourself. Hey I am re react developer and working in the IT industry
from last six years.
4:10:24
Can you explain the role of state in React and how it differs from props? The state
in React is nothing but the
4:10:30
state management used to set and get the value uh which you can store like a
variables. Props basically use it to
4:10:38
send the value from one component to other.
4:10:43
Thank you for your response. That concludes our interview questions. If you have
any questions for me or
4:10:49
anything else you'd like to discuss, feel free to ask. Thank you for your insights.
If you have any further
4:10:54
questions or topics you'd like to discuss, feel free to let me know.
4:11:00
And that's how it will ask the question and the topic. Obviously, currently in that
particular uh record ID, we only
4:11:07
have one to or two questions and that's the reason it wrap up very quickly, but
that's how it works. Okay. Over here on
4:11:14
the right hand side you will see all the uh chart session as well.
Generate Feedback
4:11:21
Now it's time to generate the uh report or interview uh feedback from your
4:11:27
interview. Obviously we already have the list of messages. That list of messages we
need to pass it to the AI model in
4:11:33
order to generate the proper feedback. Okay. And for that one obviously we are
4:11:39
going back to use this in model. it will be uh make our life easy by adding the
4:11:47
complicated integration with the help of this innate model. So you don't need to
addit that integration or implementation
4:11:53
into your application. Also inside the eraser doc I already added this uh
4:11:58
sample message uh in order to test it. So let's go to this nin model. Inside
4:12:05
here we'll create a new workflow and we can name this as a interview
4:12:12
feedback generator. Now very first thing we need to add a web hook. Okay. Now this
web hook we
4:12:20
going to use it in order to make an call. Now for this web hook it will be a
4:12:26
post request and uh let's listen the event so that we
4:12:31
can add that. Okay. So we'll say listen the event. Okay, let's copy this first.
4:12:37
Then we'll listen this event. We'll go back to this uh example.
4:12:44
So, let me paste it over here for the authentication. We don't have any. That's
good. Inside the body,
4:12:52
I'm going to write messages. Okay. And inside this, obviously, we need to send
4:12:57
a list all the messages or conversation that we have, right? So you can copy it
4:13:03
from this documentation and then close it. Now once you have
4:13:09
this message just click send over here inside your n you will get the response.
4:13:17
Right now this is the response that we geted. Okay. Now this is the first step that
we are getting the webbook
4:13:22
response. Now the next step is we need to add an AI model directly.
4:13:29
Okay. So over here we'll add open AI because that's what I'm using but you can use
any free model as well. Over
4:13:34
here we'll say message model. Now inside the first prompt this is the system
prompt. Here I'm going to write
4:13:42
depends on user conversation or interview conversation
4:13:52
messages. Generate a feedback
4:13:57
and slash report in detail.
4:14:03
give all um good or suggest improvement if there is any
4:14:14
if there is any also rate it
4:14:20
um between out of 10 okay and this is the prompt I wrote now
4:14:27
I'm going to add a message inside the message we need to pass this message as a
prompt Okay. And you can keep this
4:14:34
role as a user only. Then you can output the content as a JSON only. Okay. Here
4:14:40
um you can also mention that in the output make sure the field are correct. So here
we'll say um give response in
4:14:49
JSON with field as feedback
4:14:56
suggestion and rating.
4:15:03
Okay, something like this. And that's all we needed. Now once you execute this
4:15:08
step, so right now obviously we have to execute the previous node. So we'll save
this one and I will go back to this node
4:15:16
again. We'll listen this node because we are in the test mode. So it's better you
can just listen it. I will save it. I
4:15:23
don't know what's the issue but let's execute this workflow. Okay. So sometimes if
it's not stable just
4:15:29
refresh it. and then we'll execute this workflow.
4:15:36
So maybe there is an error. Okay. So here we forgot to add a model. So make sure
you will select the model. I'm
4:15:43
going to use this uh gin mini model. And now you can say execute workflow
4:15:51
over here. We'll trigger this workflow. And now if you see it generating the
4:15:56
response okay and boom inside the content we have the feedback we have
4:16:02
suggestion and then we have the rating out of six. How easy it is right? We
4:16:07
don't need to even write a code within with the help of this n at n model
4:16:13
you'll you are getting the expected result as well. Okay. Now this result
4:16:18
obviously you need to return back. So here we'll say web hook response. Okay. And
obviously we need to
4:16:26
pass this content as a response. So over here we'll say response code.
4:16:33
Okay. You don't need to add this response code but you can pass everything as it is
directly
4:16:44
and that's how you'll get the response. Okay. Now everything is done. Save it.
4:16:49
Now here you can enable this so that it will be in the production mode now and I
4:16:55
will copy this production URL. Okay, just for the information, you can see your
production execution inside under
4:17:01
the execution tab. Over here, you will see which one is failed, which mean one is
success and if there's if it's
4:17:08
failed, why it failed. Okay, you can track out each request. Now, once you
4:17:14
copy this URL, we'll go back to our application. Inside this, I'm going to create a
new API endpoint.
4:17:23
And here we'll say interview feedback.
4:17:29
Inside this we'll create a route dot tsx file and then we'll say export a sync
4:17:36
function post as this is a post request. So we'll say request next request. Okay.
Now
4:17:44
inside that obviously we need to get a list of messages. Here we'll say await
4:17:50
request dot JSON.
4:17:55
Then we need to call the API endpoint. So we'll say exio dot post. This is the
4:18:03
endpoint, right? And obviously we need to call u or we need to send a body. So
4:18:09
here we'll say messages add messages. Perfect. You can convert this into a
4:18:14
string as well. Okay, that will be good option. So you can write like this. Once
4:18:19
you have the result, I will just console the result and you can return
4:18:25
next response dot JSON. Now I will just use this one and because we only want to
4:18:32
return the exact response. So that's how you'll get the response, right? So
4:18:40
I will just write result.data dossage.content. Okay? Because inside
4:18:45
the content uh where we have okay over here if you
4:18:50
see inside the content we have this feedback suggestion and the rating. So that's
all we need it and then save it.
4:18:57
Now let's go back to the interview page
4:19:03
inside the start. Right now when you disconnect it that's when we need to call. So
over here first we'll create a
4:19:09
method called constant generate feedback arrow function and inside this
4:19:16
we'll say constant result is equal to await exos dotpost
4:19:23
/ ai/g generate feedback
4:19:29
and inside the post request we need to send a messages as messages
4:19:36
here I will make this as a sync Now this gen uh before that I will just
4:19:42
console the result. So we say result dot data. Now this generate feedback I'm going
to
4:19:49
call it when uh we end the conversation. Right? So
4:19:55
here we have the new conversation and that's when we need to call. So over here
we'll say
4:20:02
await generate feedback something like this. Okay. And once the
4:20:08
feedback is generated, we want to navigate. Okay. We want to save the
4:20:13
feedback and then we want to navigate it. Okay.
4:20:18
But before that we are going to test this out. Now for the testing again you have
to start the conversation do some
4:20:24
conversation and then it will generate it. But ra so doing all of this instead of
this we will just create a single
4:20:31
button which will call this generate feedback method by passing the messages
because you already have the list of
4:20:38
messages right so what we can do uh we'll go over here
4:20:43
I will copy everything as it is okay and
4:20:50
I'm going to create messages dummy messages as a demo so over here we say
4:20:56
constant dummy conversation is equal to and paste it. Okay, now we
4:21:04
have the dummy conversation. That demi conversation I'm going to call it
4:21:10
or we can set it for now
4:21:15
to the send message. Okay, let's leave it like this.
4:21:21
So over here if messages is not there or just pass the demi conversation for the
4:21:26
testing purpose and then we'll add a button somewhere here
4:21:33
and here we say test feedback generate. Okay this method going to call generate
4:21:42
feedback method and then save it. Now it will call this method. It will generate
the response. It will console it for us.
4:21:48
In the meantime, you can show some kind of loading as well. So over here you can
show toast message.
4:21:55
So here we say toast message. Warning with uh generating
4:22:00
feedback please wait. Okay.
4:22:06
And then save it. And once the response is generated to dot here we say to dots
success
4:22:13
feedback is ready. Feedback ready. And then save it. Okay, now we'll go
4:22:19
back over here. If you see we have this button, right? Obviously that is only for
the testing purpose. So we'll go to
4:22:26
the console. Over here we say test feedback. Now we got an error. It's saying 404
error. It means this
4:22:33
particular API is not fine. It's not available. So maybe we have some spelling
mistake. So I will go to the
4:22:39
API. Inside this we have generate interview just interview feedback. So this need
to
4:22:46
be an interview feedback.
4:22:54
and then click generate now. Okay. So we have 500 error. Let's see what is the
4:23:00
issue. So over here if I go to the console and if you see it's uh
4:23:09
it seems request fail. Okay. So inside this N8 model. So if I go to the
4:23:15
execution if you see we have one error response. So we'll check what is the issue.
So it's saying web hook not
4:23:22
correctly configured. So let's go to this editor
4:23:29
and maybe here we need to say when last node finishes. So response
4:23:35
or we can say using response to web hook node. Okay. So maybe that is the correct
way. Same thing we already implemented.
4:23:41
Right now let's test this out. So I will click on this test feedback in the network
4:23:47
tab. We can observe. So if you see now it's working. Now we have the interview
feedback. Now it's return the status
4:23:53
200. I will go to the console and boom. If you see we have the feedback rating and
the suggestion as well. Cool. Right
4:24:00
now once you have this all the information related to the feedback you can simply
save it. Now I will go to the
4:24:07
schema. Inside the schema, make sure for your interview uh you have the feedback
4:24:12
column. If you don't have, simply add this feedback column.
4:24:18
Inside this, I will make this an optional initially. And I will put a type any
because we
4:24:24
want to save a JSON. Let's save this one. Then go to the interview. Inside the
interview, you need to
4:24:32
update your in uh particular record, right? So here we say export constant
4:24:38
update feedback. Now update uh is come under the mutation. So we'll say
4:24:43
mutation. Inside the mutation pass the arguments. Over here you need to pass a
4:24:49
record ID. Okay. So which is of type ID and then the
4:24:56
table name is interview session table. Then here the feedback.
4:25:02
The feedback is of type any. Then you need to pass an handler with
4:25:09
the async. Over here we say ctx, arguments and the error function. Over
4:25:16
here we say constant result is equal to await
4:25:22
ctx dot db dot up uh dot uh patch
4:25:29
because we want to update the record. Then which document you want to update
4:25:34
that document id. So in this case we'll say arguments dotrecord id and then the
4:25:40
field which you want to update. So in this case we want to update the feedback. So
here we can get arguments
4:25:45
dot feedback. As simple as that. Right. And uh that's all we have. Perfect. And
4:25:52
also you can provide a status as complete. Okay. So this interview is
4:25:59
completed because we have this inside the schema you have the status field. So
that's the reason. Now once you have the
4:26:05
result you can return the updated record ID and then save it. Once you have the
4:26:11
uh interview convex function ready in order to use it first you have to define
4:26:17
at the top. So over here we'll say constant update feedback is equal to use
4:26:23
mutation. Define that API. So we'll say API dot interview dot u update feedback.
4:26:31
Then we'll scroll down where you want to update. So over here we'll say constant
result is equal to await.
4:26:38
So here we'll say response because we already used the result. Here we'll say um
update feedback and inside this
4:26:45
update feedback we just need to pass a feedback. Whatever the feedback we get it
that
4:26:51
information we're going to pass. And the last is record ID.
4:26:57
Now record ID is nothing but the interview ID. Okay.
4:27:05
And over here I will just ignore this one. Okay. And save it. I will also
4:27:11
console this response and then save.
4:27:16
Now if you want to test one more time. Let's go ahead and test this feedback
generate. Now right now it's generating
4:27:22
the feedback. Please wait. Anyway, if you user go to the next page, it will
automatically do it for you and it
4:27:30
generated the feedback. Okay, but it returned 213. But let's see in the database.
4:27:36
So over here inside our database, if you see we have the feedback for that
4:27:42
particular record inside in the form of JSON. How cool, right? That's how easily
4:27:47
we implemented this particular feature. Obviously, once you are done with this
4:27:52
one, right? And once we have the information you can simply toast the
4:27:58
message or here we'll say interview completed
4:28:06
and then you can redirect it so that uh you can define a router for that in
4:28:12
order to redirect programmatically. So here we say router
4:28:17
is equal to use router okay from the next /navigation
4:28:22
and then over here we say router dot replace because we don't want user come
4:28:28
back to the same interview here we'll say dashboard
4:28:35
and then save it and now we don't want this button so I
4:28:40
will remove this button and obviously now it will generate the feed feedback as
soon as the conversation is
4:28:47
completed. So that's all for this particular chapter. I hope you understand. If you
have any question,
4:28:52
let me know in the comment section. Now it's time to display the generated
Display Interview List on Dashboard
4:29:00
interview on the dashboard. Now currently on the dashboard we are not
4:29:06
showing anything when interview is created, right? But now as soon as user create
the interview we already saving
4:29:12
that interview information to our database but we also wanted to show on the
dashboard right as this is the empty
4:29:19
state which we already implemented but whenever user have the any interview we
wanted to show that interview
4:29:24
information and as per this mockup we have two kind of interview as you know that
one is the resume interview and
4:29:31
another is a job title description interview and whenever there is a resume
interview these are the content which we
4:29:37
are going to show along with the status uh option to view the resume and option
4:29:42
to start the interview and same thing with the job title description uh for
4:29:48
the different card. Okay, so first thing we need to fetch the all the interview
list. So I will go back to
4:29:55
our dashboard page inside this page.tsx. Uh we already have this interview
4:30:02
listed. Inside this I'm going to create a new method called constant get
4:30:07
interview uh list I will say and then the arrow
4:30:13
function. Now we need to create a convex function for this one. So I will go to
4:30:18
the interview.ts under the convex folder. Inside this we create a new
4:30:24
method called export constant get interview list is equal to query because
4:30:32
we wanted to fetch and then we'll f add the argument. Now inside the argument we
4:30:38
just need a user ID because we want to fetch a record based on user ID and here
4:30:44
we'll say v do ID and the table name is users. I will just verify the table name
4:30:50
from the schema. So it's called user table. So make sure to provide that.
4:30:56
Then provide the handler with a sync ctx,
4:31:02
arguments and the arrow function. Now make sure inside your database uh for
4:31:10
each record we already connected with user ID. So each record we are already
4:31:16
connected. So this way it will be very easy just to fetch uh the all the
4:31:22
records with the help of user ID. Now inside the handler we will say constant
result is equal to a ctx dot db dot
4:31:32
query on table name. So which is the interview session table.
4:31:38
Then we'll say dot filter on. So we say Q dot sorry Q dot uh equal first and
4:31:46
then Q dot fill again we need to give the uh
4:31:54
field name which is the user ID and then we need to match with our arguments user
4:32:01
ID and then at the last we'll say collect obviously it will return the list of uh
records so we'll return all
4:32:10
of them. So we'll say return result and then save it. And that's how we'll get
4:32:16
the interview uh list. Now in order to use it, let's go to the page.tsx. First
4:32:22
we'll define a convex is equal to use convex.
4:32:30
And in order to get a user ID, we can get it from the user detail context or
4:32:38
uh that particular hook. Right? So first I will define this user detail. Here we
have this use user detail context
4:32:50
so that we can use it. Okay. So we have this error. Let's
4:32:56
simply use this use context and here we will say user
4:33:04
detail context. Okay. And once we have user detail information simply we'll say
4:33:10
constant result is equal to await then convex dot query here we need to
4:33:17
define that API. So we'll say API dot interview dot get interview list and then
inside the argument you need to
4:33:24
pass user id that user ID we can get it from the user detail dot ID. After this
4:33:31
we'll make this as a sync. We need to call this method. So we'll use the use effect
4:33:38
and inside the use effect we'll call this get interview list. Okay over here
4:33:44
we'll say uh user detail. Now whenever the user detail is available then only
4:33:50
we need to call this particular method. Right? So that's the reason I added this
condition. Now once we have the result I
4:33:57
will just console it for now to verify that we are getting the result or not. So I
will refresh the screen and on the
4:34:04
right hand side you will see we have the five interview record. Okay. Inside this
4:34:09
you can even order it by uh with the descending order. So here we say
4:34:17
so maybe after this or before this we need to add order and then we'll say
4:34:22
descending. So it automatically order it by the descending order. Now next thing
once you done with this one let's make
4:34:29
sure to save it in a state. So we'll say constant. Oh we already defined the state.
So
4:34:35
we'll just set it there. So set interview list with the interview list
4:34:42
and save it. Now once we have the interview list you will not see this empty state.
Now if I refresh this
4:34:48
screen. Okay. So we are still uh displaying that interview list. So let's
4:34:53
go back and check why. That's because we did not set correctly. This need to be a
result.
4:35:01
Okay. And over here we need to define the interview list type. So I will
4:35:06
define a type called interview.
4:35:12
Inside this we need to provide all of these field like feedback, interview
4:35:17
questions. Okay. So we'll say feed back.
4:35:22
Okay. Right now I will give type any. Then interview question.
4:35:29
Uh again I will give type any for this one. Then we have job title, job
description.
4:35:35
I think we already have this interview uh type created. So I will directly use
4:35:40
this one. If you don't know where it is. So if I go to the start page.tsx file,
4:35:45
go to the top over here. You will see this interview data. Make sure to export this
one. Once you export, you can reuse
4:35:53
it over here. Something like this. Okay, as this is a
4:35:59
list. So, we need interview data. And then we save this result. Now, once we
4:36:05
save it, let's go back refresh the screen. And if you see now the empty
4:36:10
state is gone. Okay. Now obviously here we need to show the list of all the
4:36:17
records. So I'm going to create over here we'll say a div and instead of
4:36:25
this and and I will add a question mark okay and turnary operator and then I'm
4:36:31
going to show the div over here I'm going to iterate this interview list. So we say
interview list dot map we'll say
4:36:38
interview, index and the arrow function
4:36:44
over here uh we're going to create a diff a new component under the dashboard
4:36:49
and I'm going to keep in this uh that particular component inside the component
folder and I'm going to call
4:36:56
it as uh interview
4:37:03
cards. tx I will say interview just card.tsx t
4:37:08
that's fine. Then add a default template and then save it. If you see this empty
4:37:13
state, make sure to move this to underscore component. Okay?
4:37:19
Because by mistake I added inside the dashboard. So make sure to uh move this
4:37:24
and then I will remove this import statement and make sure to import the correct
import statement for this empty
4:37:31
state. Now over here I'm going to add this interview
4:37:36
card component. Okay. And save it. Now let's go to the interview card component.
And here we need that
4:37:43
interviewed information. So I will create a prop type props. So here we say
4:37:49
type props and here we will say interview
4:37:55
uh info of type interview data and then
4:38:02
we can use this interview info. I will keep this I small
4:38:10
and then we'll provide this type props. Then over here as per this design mockup
4:38:20
first uh we'll we'll see whether that interview is from the resume or from the job
title. Right? So let's add an H2 tag
4:38:29
over here. We'll say if interview info dot
4:38:36
uh so in this particular interview data I think we don't have the resume URL. So I
will make sure to add this stream.
4:38:42
Okay. because that is very important inside your tables we have this resume
4:38:48
URL right so that's the reason we need to add so that's why I added this
4:38:53
particular value and over here now we'll say resume URL
4:39:00
if it's there then we'll say resume interview okay otherwise we're going to
4:39:06
show interview info dot from the job title okay and then save
4:39:14
Then we want to show a description. So same condition I'm going to use over here.
Okay. Obviously I'm going to
4:39:21
change this little bit. If there there is a resume URL then I will use this uh
4:39:26
sorry I will use this text called we generated the interview
4:39:35
questions from the uploaded resume. Okay. generated interview will say interview
4:39:42
from the uploaded resume otherwise we're going to simply show a job description
4:39:48
and make sure the we'll only show maximum two lines.
4:39:53
Now for this H2 tag I'm going to make it font semi bold text excel
4:40:01
and for this one I will make text gray 500 and then save it. Now once you save
4:40:08
make sure to go to the dashboard here to this interview data you need to pass the
interview information each interview
4:40:14
information I will keep this key as a index let's save this one
4:40:20
uh we have an error over here
4:40:25
so inside this interview data type make sure you can keep it as a null okay so
that's the reason we have that error and
4:40:32
then save it now if I go back to our application uh refresh this screen. I think we
have
4:40:37
an error. It's saying create interview dialogue. Cannot resolve it under the empty
state.
4:40:44
So I will go to this empty state because we have this incorrect import. Now we
4:40:50
just move this component. Right? So that's the why. And now I think we are good.
See now that particular interview
4:40:57
information is getting listed. That's good. Uh let's go to this interview card.
Obviously we need to style it. So
4:41:02
we'll say class name. We'll add some padding. Let's say padding to four. We'll add
a border. We'll make around it
4:41:09
to Excel and then save it. Now let's go back to the dashboard because currently
this uh
4:41:16
all the cards showing in a list format we need in a grid format. So for this
4:41:22
view I will add a class name. I will make it grid. Make grid column uh two
4:41:27
for the smaller screen. For a medium screen we'll make three and for the larger
screen we'll make grid column
4:41:32
four. If you have extra large you can make grid column five as well but I will
4:41:37
keep it four max then gap to five and then save it
4:41:43
and boom if you see how beautiful it look right um then we'll go back I think
4:41:49
we can just change this to three and let's see how it looks
4:41:55
so inside the dashboard I will make it three only I think three is much
4:42:04
And also for this one I'm going to add some margin top to let's say 10.
4:42:11
Then we want to add more information. So I'll go to this interview data again
4:42:16
over here. We'll add a due tag. For this due tag I'm going to add a badge from
4:42:22
the shad CN. So we'll use a shad CN.
4:42:27
And under the component you will see one component called batch. Okay. So this is
how it look like. So it actually uh we
4:42:34
are going to use it for the status in order to show the status. So first let's
install this batch
4:42:41
component. Then in order to use it I will just use this
4:42:48
batch component. I don't know why it's not importing correctly.
4:43:00
And inside this we'll say interview info
4:43:06
dot status. If you don't have the status field so make sure to add that inside
4:43:11
your interview interview data type. So over here we say
4:43:16
status of type string and optionally it will be null. So that we can simply add
4:43:23
it. Now once you add the status you will see the complete draft something like this
right.
4:43:29
So also I think we don't need to add anything
4:43:35
else over here. You can move this badge to the to an H2 tag. Let's see how it
4:43:41
looks. And then you can make it flex justify
4:43:48
between an item to be in the center. Perfect. Okay. Then we want to add a
4:43:55
button. So we'll add a two button.
4:44:01
Now one button is uh to view the resume. Okay. Now if there is a resume. So here
4:44:07
we'll say interview data info dot if there is a resume URL then we'll show
4:44:12
this button and we'll say view resume.
4:44:17
The button name is view resume.
4:44:22
and another button here we'll say start interview
4:44:30
and we'll say arrow right
4:44:35
something like this see um I think we need to
4:44:42
add a class name margin top five
4:44:48
I think that's all we needed we can mark this as the outline. So class name we'll
4:44:55
say not class name but if you provide ovarant as outline that will be good also
make
4:45:02
it flex justify between item to be in the center
4:45:10
and then let's go back and let's see how it looks. I think that's pretty good. See
and that's how our uh dashboard is
4:45:19
almost ready. Now obviously if I uh reload this one uh you will see this screen and
then it come back to this
4:45:25
particular dashboard right that's because inside our uh dashboard page.tsx
4:45:32
right when there is a loading you can just wait and just show some kind of loading
indicator or skeleton. So over
4:45:39
here we say constant loading comma set loading is equal to use state initially
4:45:46
it will be false. Now when you are getting the interview list you can set the
loading as a true. Once you finish
4:45:52
it we'll set the loading as a false. Now when there is a loading we want to
4:45:59
show the skeleton effect. Okay. So you can either implement over here or you can
implement as a different one. So I
4:46:07
will just add a div and we'll add empty state. Okay something like empty array.
4:46:13
Then we'll add map oop sorry inside the curly braces. Then we have map item
4:46:19
comma index. Wait let me try start you from scratch.
4:46:25
So over here we'll add empty array something like this dot map with item
4:46:32
index and the arrow function. Now inside that we want to use a skeleton. Now you
4:46:37
can use the shadian skeleton component for a loading. So I will go to the shenan
search for the skeleton
4:46:45
copy this import statement paste it here. Once you copy you can simply use
4:46:51
this skeleton uh example. Okay. So if you see this example I think pretty good
right we can directly use this one
4:46:58
and I will import it here. Now what it actually do this particular map so it will
just repeat your uh skeleton six
4:47:06
times. Then of inside this do I will use same structure okay
4:47:13
over here because we want to keep it same color and key as index and then
4:47:21
save it. Now this particular skeleton let me show you how it looks first. So if you
see this skeleton below right
4:47:27
that's how it look like. You can make it width full.
4:47:32
Okay. And I think that's pretty good. But we only want to show skeleton when
4:47:39
there is a loading. So here we'll say if loading is there. Okay. Let's add this
4:47:44
condition then only show it. But also we have to make sure when there is a loading
don't
4:47:49
show this empty state. So here we say if not loading and and and then this
4:47:55
condition. Now if I load still showing this empty state. Okay. So
4:48:00
I think there is a mismatch again. Okay. So, initially uh make sure we can
4:48:07
set the loading true. And now if I refresh this, see perfect, right? So that's how
it works.
4:48:14
And on the click of this start interview, we'll make sure you'll navigate to that
interview screen. So it's very easy. Go to the interview card
4:48:21
because we already have the button. Uh I will wrap this in a link tag with a h
4:48:27
reference. Here we'll say slash interview slash and then the id. So id will be
4:48:34
interview info dot id and make sure to
4:48:39
wrap your start interview button inside the link. Right? Once you wrap if I click
on any of this interview it will
4:48:47
navigate to that particular page. See and where I can start the uh interview.
4:48:52
Cool. Right. So this is the complete flow of our application. Obviously you can
upload the resume uh add the
4:48:59
description and everything else but uh I hope you understand this particular
4:49:05
dashboard UI. Uh just we are showing the whatever the user created interview.
Display Interview Feedback
4:49:18
Now once you uh completed the interview we added this uh button called feedback. I
replace that button and change this to
4:49:25
a feedback. So that on the click of feed we can see the feedback for that
particular interview. Okay. Obviously
4:49:31
you can give the interview repeat again but over here make sure that uh we want
4:49:37
to add the user feedback so that user come and check his feedback. Now on the click
of it we want to open a dialogue
4:49:44
and on that dialogue you can show all the feedback information which we already
storing into our database. So
4:49:50
let's go back and we're going to create a new component under this dashboard
4:49:56
only and we can create a component called uh feedback
4:50:02
dialogue dot tsx. Let's add a default template
4:50:08
and then save it. Now inside this feedback dialogue
4:50:13
obviously we want to add a shadian dialog component. We already installed this one.
So you don't need to install
4:50:19
it again. But make sure to add import statement.
4:50:25
Then we'll use this example dialog example. So that also
4:50:31
copy and I will paste it here. Okay. And then save it. Now inside this trigger I
4:50:37
will use this button. Okay. Instead of
4:50:43
uh importing that dialogue. So maybe inside this interview card we have this button
right. I will cut it from here
4:50:50
and this be this will be our trigger to open the dialogue and make sure to import
this button here. I will mark as
4:50:57
a child this feedback dialogue. Now you can import something like this. Okay.
4:51:03
And then save it. Now if I go back to our application, if I open this feedback, let
me refresh this screen
4:51:09
once and open this feedback. You will see this window. Perfect. Now let's uh
4:51:15
add all the details. So here we'll say interview feedback as a dialogue title
4:51:22
and for the description obviously we need to pass a feedback information to this
feedback dialogue. So I will create
4:51:31
a type props inside this we'll create a feedback
4:51:39
uh info. Okay. And I will define a type over here. So we'll say feedback info
4:51:45
type. Okay. And over here we need to write all
4:51:52
the field which we are adding to this feedback. So if I go to the convex let
4:51:58
me go to the development and if you see inside that we have
4:52:03
feedback rating and suggestion. So feedback of type string, rating of type
4:52:10
number and then uh suggestion
4:52:17
of type string. Okay. Now this period info I'm going to attach and then here
4:52:22
we'll say feedback info of type props.
4:52:30
Here I will use small f only just to avoid confusion. Okay. And then save it.
4:52:36
Now from the interview card, uh over here inside the interview data as well,
4:52:42
if I go to this interview data, right? Now we use this feedback of type any. Now I
will replace this with the
4:52:48
feedback uh info. Okay. So I will make sure I will export this one so that we can
use
4:52:54
it. So here we will say feedback info. Perfect. And save it. So that to this
4:53:02
feedback dialogue we can pass the feedback info from the interview info
4:53:07
dot feedback and then save it. Perfect. Let's go over
4:53:12
here inside the feedback info. Now for the description if I go to this example
right if you see
4:53:19
this we have the feedback and then we have the suggestions. Okay, which is the list
of suggestions. Now first we'll
4:53:25
define a feedback. So over here we'll add a do then s2 tag
4:53:32
inside this we'll say feedback I will add a class name font bold text
4:53:39
larger and then inside the p tag I will add
4:53:45
this feedback. So we'll say feedback info dot feedback. Let's save it and
4:53:52
let's test this out. So I will go back and here if you see we have this feedback as
well. I will increase this
4:53:58
size. Let's say text larger and here I will make text to Excel
4:54:06
and text color as a black. I will just make it Excel. Okay. So this is the
4:54:11
first feedback. Uh for this one I will make font bold
4:54:16
text to Excel. Then we want to show a suggestions.
4:54:24
So for the suggestion I will use do tag. Inside this we have a feedback info dot
4:54:30
suggestions and suggestion is not a string actually is a list of string.
4:54:35
Okay something like this. So that we can simply map it.
4:54:41
So here we'll say item, index and the arrow function
4:54:46
inside the h2 tag we'll say item only.
4:54:51
Over here we'll add a class name and uh I think we forgot to give the
4:54:58
title. So similar like this one I will just paste this title but I will rename this
to suggestion
4:55:06
and then save it. Right now we got an error. Let's see what is the issue. So it's
saying
4:55:14
undefined reading map. Okay, maybe just add an optional operator field. Go to
4:55:19
the feedback. Right now it's not showing the suggestion. So this need to be a
4:55:24
suggestions with a s. Okay. So I think I need to update over here as well.
4:55:31
And now if you see we got the suggestions. Perfect. Now for the suggestion um you
can add a
4:55:39
padding then background gray 50
4:55:44
and then rounded to large. Okay. And I
4:55:50
think we can add more padding and padding y to one. Okay. So some
4:55:57
space as well. So this is just a suggestion that we can say okay these are the
suggestion. Um you can add
4:56:04
some arrow right I will say okay something like
4:56:10
this but we want in one line so we'll make it flex gap to two
4:56:18
and for this one I will say height to four width to four okay smaller then we
4:56:25
want to show a rating so I will copy this H2 tag and then I will Just show
4:56:31
the rating in P tag or maybe we can show over here only
4:56:38
in a span tag and we have this
4:56:45
feedback info dot rating. Perfect. So you can even change this
4:56:53
color. Okay. So I will change this to primary so that you can see this. Okay. Maybe
we
4:57:01
can change it over here only. And that's how you will find this
4:57:06
feedback for your interview. Cool, right? So that's how uh you can display.
4:57:12
Obviously, you can add more style. Okay. Uh it's up to you. But our main focus is
4:57:17
the functionality. So that's the reason I kept it as simple as that. Okay. I think
this arrow right not look good. I
4:57:23
will remove it. But only thing that we want to add, I will make this text
4:57:28
Excel. Okay. Little larger or maybe just
4:57:34
text large. Perfect.
4:57:43
Now it's time to add a subscription pricing table into our application. And for
that one, we are going to use a
4:57:50
clerk billing feature. I will put the link in the description for the documentation
and the uh site so that
4:57:56
you will jump onto the exact uh web page where uh you can add the number of plans
4:58:04
whichever you want with the all the features which you want to provide in that
particular plan and in app only uh
4:58:10
with the help of stripe payment gateway it automatically integrate the payment
gateway inside your application. You
4:58:16
don't need to do anything guys, okay? You don't need to write a complicated logic,
any checkout page logic, anything
4:58:21
within just one line of code, you going to implement this uh pricing table into
your application. And let me walk
4:58:28
through the how. So first thing uh on the click of upgrade button, so we have
4:58:33
this upgrade at the top, we want to create a new screen and on that screen we want
to navigate. So first I will go
Subscription Billing
4:58:40
I will go to this routes. Inside the route, we're going to add upgrade screen
4:58:46
or upgrade page. And here we'll say page.tsx. Add a default template. I will rename
4:58:53
this to upgrade. Now once you are on the upgrade page,
4:58:58
now it's time to add a pricing. So for that one, I will go to the clerk. Okay.
4:59:05
So make sure to log into your dashboard. Inside the dashboard, you will see this
subscription beta. Right. Right now we
4:59:11
did not set up. So you can have option you have option called get started or you
can go to the configure. Under this
4:59:18
configure you will see this uh billing section. Okay. Click on setting. Under
4:59:24
setting you have to first create the plan. Okay. So you can create uh
4:59:29
whichever plan how many plan you want. Currently the default is a free plan. Inside
the free plan uh you can provide
4:59:36
a name. The key. Key is very important. Okay. It automatically generate as you
enter the name. You can provide the
4:59:43
description as well and you can provide a monthly. Right now it's a free so it's
4:59:48
just uh it's not enabled the pricing but you can add a feature. So over here we'll
say uh
4:59:55
generate to daily interview only. Okay. Then we'll create this
5:00:03
feature. Then we can add a new feature here. We can say uh limited feature
5:00:10
access and it's up to you how you want to do
5:00:16
it. Okay. No email support.
5:00:24
So like this you can create. Okay. And then once you are done with this one
5:00:30
save this particular plan. Now I will go back again and in this case I want to
5:00:35
create now new paid plan. So here I will create add user plan. Here we'll say uh
5:00:43
pro plan we can call. Okay. Inside this you can add description if you want. It is
completely optional. Monthly base
5:00:50
price you can see you can set let's say $6.99. Okay. And if you are buying it
5:00:55
annually you can set annual price as well as of 5.99. Oh sorry. So here we'll
5:01:01
say 5.99. Then you can add a feature. So you can add a feature. You can select the
5:01:06
current feature as well. Or if you want you can add new feature. Here we'll say
unlimited
5:01:11
daily interview.
5:01:17
Then all feature access.
5:01:24
And the last will say 24 by 24
5:01:29
by 7 email support. Okay. So these are the feature we added.
5:01:36
Let's create this feature and then simply save it. Once you save, let's go
5:01:41
back and here you will you will see these two option. Now you have option called
enable billing. Now currently we
5:01:48
are in the development mode, right? So clerk is enable the clerk being is
5:01:53
enabled for the development purpose. Okay. So you don't need to directly connect to
the strappy right now. Once
5:02:00
you move to the production then you can just connect the strappy with the clerk
that also you have to just follow the
5:02:06
step-by-step guide. Click next next. It will connect it for you. Now here you will
see the billing is enabled. go to
5:02:13
the read billing guide where you will find a billing uh documentation how to
5:02:19
add that billing. Okay, as I told you in the beginning that within just one line of
code you will add that pricing table
5:02:25
and let me show you how. So if you scroll down a little bit this is the component
called pricing table. Okay,
5:02:31
which is importing from the clerk next. That is the only thing that you need to
add. So I will copy this.
5:02:38
Go back to your application and simply paste it here. Make sure to import this
pricing table from the clerk neckjest.
5:02:45
Save it. Go back to your application and then over here uh
5:02:53
I will just refresh the screen. So boom. If you see now the pricing table is
5:02:58
showing on the screen. I will just add some style. Okay. So over here I will
5:03:03
add flex. Oh, this is a style. So I will add a tailwind CSS. So here we say class
name
5:03:11
flex item to be in the center justify center and then I will add a height to
5:03:18
screen right so it will be uh in the center of the screen I think that's weird but
uh I will just remove this
5:03:26
height to screen for now above this pricing table I will say upgrade
5:03:34
to pro plan for this H2 tag we'll say font whole text to 3XL
5:03:42
and I will make this flex column. Okay. And then we also give margin top
5:03:50
to let's say 24.
5:03:56
I don't know why the margin is not get applied. So let's me give margin top to
5:04:01
24 and margin bottom to let's say 10. Okay.
5:04:07
And that's how our upgrade plan pricing table is ready. Okay. Over here if you
5:04:13
click on subscribe here inside your application you have option to enter the card
details and all of this
5:04:20
information. Currently we are in the development mode. So that's the reason you can
even test it by uh with the help
5:04:25
of this test card. Okay. But for now I hope you understand this. Now let's
subscribe to this one. So once I click
5:04:33
subscribe, pay with the test card and then it will make a payment. See and then say
continue.
5:04:40
Currently now you subscribe to this particular plan. You can see all the analytics
under this subscription over
5:04:46
here. Immediately you will see that user is subscribed right and you will see that
uh record as well with this
5:04:53
username the status when is the next payment everything all of this information all
the analytics you will
5:04:59
see under the clerk dashboard how cool it is. Now the next part is how to
5:05:06
enable this feature so that user can create unlimited interview.
5:05:12
If you remember that we use the arjet to limit the user uh interview creation
5:05:18
process right and if I go to this API where we have an option called generate
5:05:23
interview that's where I think we created this decision maker see okay now
5:05:29
inside this we're going to first check if this user is already uh subscribe to
5:05:35
the pro plan or not okay so from the documentation so if I go to this clerk
5:05:40
documentation If you scroll down here is a has method which is inputting from the
5:05:46
authentication use o I think. Okay. So this is how you can get it and then you can
check if that particular plan is
5:05:53
subscribed or not. So simply what we can do um you can go back and inside this
5:06:02
can say constant or uh
5:06:07
I think it's has is equal to await o. Okay. Now if you
5:06:14
see this o is importing from the um nextjs server. Okay. And once you has
5:06:20
this has so over here we're going to check constant
5:06:26
is subscribed user. Okay. And over here
5:06:31
we'll say if has and simply we're going to add the plan name something like
5:06:36
this. Okay. You can even test it with the feature. And then we have a h plan and
then we need to provide a plan ID.
5:06:43
Now that plan ID you will find under the config subscription plans and the pro over
5:06:50
here. This is the key that we need to use. So I will copy this pro and then simply
paste it. If this is subscribed
5:06:56
user is true. So then you don't need to check this condition. Okay. So over here
we'll add and and not subscribe user. If
5:07:05
it is not subscribe user then only it will go into this if condition. Okay
otherwise it will not and that's all
5:07:12
that's all uh you need to do it. That's how easy it is how easily we added the
5:07:18
pricing billing section how easily we connected to our existing u logic and
5:07:24
done. Okay. So I hope you understand this club billing. If you have any question,
any doubt, let me know in the
5:07:29
comment section because there are lot of things uh you want to learn on this
5:07:35
channel. Before moving to the next chapter, I want to introduce a brand new
5:07:40
uh product which I developed called Kraix Studio. Kraix Studio is one of the
5:07:46
first AI model which will generate the complete uh story or short film for you.
5:07:54
Okay, where you can generate AI short film uh episode base which contain the
5:08:01
consistent character. It will generate the outline for you. You can even edit each
scene one by one or you can
5:08:07
generate all the scenes together. Most important there are consistent character
throughout the video. You don't need to
5:08:14
do anything. This graphic studio AI will take care of it. Not only that but you
5:08:19
can generate the multiple type of video like you want to create a 3D pixar you can
create an anim style cinematic uh
5:08:27
gibli style there are lot of different style it available okay and most important
it will generate the short
5:08:33
film within just 2 minute and you can export it uh immediately as well it's
5:08:39
free to start you can just go ahead uh if you use the link in the description
you'll get uh free credits as well I
5:08:46
will put the link in the description Go ahead and try this out.
Deploy App
5:08:53
Now it's time to deploy our application in the production so that you can share
this app with your friends and family.
5:09:00
Now in order to deploy this application uh on a cloud first you need to push all
5:09:06
of your code to the GitHub and then we're going to connect GitHub uh repo to
5:09:11
the versel. versus the free uh cloud deployment hosting service where you can
5:09:16
deploy it for free. Okay, obviously whenever you make some changes into your
application, you just need to push your
5:09:23
changes and automatically it will trigger the deployment event for you. Okay, so
you don't need to deploy it
5:09:29
every time manually through the versel. Only very first time you have to set up. So
uh before deploying or pushing any of
5:09:38
our code, first we build our application. If you find any runtime error, we will
can fix it immediately.
5:09:44
So just type a command npm run build, click enter and then it will start
5:09:50
building your application. If you find any error just fix it and then again try
5:09:56
this command so that uh it will remove complete error if there are there is
5:10:02
any. So right now if you see there is one error saying build worker exited with a
one signal null. Okay. So over
5:10:08
here the image kit is not valid route export field. So we use this image kit
5:10:14
somewhere. So obviously so if I search this image kit where we exported at some
5:10:20
uh location. So that's where we exported right. So we cannot actually export from
this uh page. So we'll just remove this
5:10:28
export. This is not good way that you can export from the route. And now I
5:10:33
will run this npm run build command again. And now this case in this uh case
5:10:39
it's working perfectly fine. The build is successful. Now the next step is I will
go to the GitHub create a new repo.
5:10:47
Over here we'll say uh mock AI mock interview AI mock interview 2.0.
5:10:56
Then you can select the repo uh visibility. Click create repo. Once you
5:11:01
create this repo first you need to set the remote origin. So I will copy this
command.
5:11:08
Okay. Make sure it's initialize as well. Then we need to stage all of this file.
5:11:13
Okay. So you have a plus option. It will stage
5:11:18
it or you can use a command line to stage it. Then we have to provide a get
5:11:24
commit message. So here we say initial uh commit as a message. You can give any
5:11:32
message and simply push it. If you are using pushing first time, make sure to push
with this command. Okay, you have
5:11:39
to push it to the origin main. But later on, you can push it by using get push
command as well. Now, if I go to this
5:11:46
GitHub, refresh the screen, you will see just now we pushed all of our code to this
repo. Now, the next step is go to
5:11:53
the versel. If you see there are many project running on the versel. Here you have
option called add new project. Uh
5:12:01
make sure to connect your GitHub repo and once you connect it you will see your
project name. Click import over
5:12:07
here. It automatically detect your framework right as we are using a convex you
need to update this build tool
5:12:13
settings little bit. So go to the convex deployment deploy. Okay. So you will
5:12:20
find this documentation. Now obviously this is official documentation obviously I
will put the link in the description.
5:12:26
Just click on that on this one. uh you need to update this
5:12:31
build command to npx convex deploy and this copy this complete command. I will
5:12:37
go to this versel enable it paste it here. Okay. Then
5:12:44
you need to uh add this convex deployment key for the production. So
5:12:51
that is the key that we need to add. We can add it later on in a moment. But right
now make sure to update this build
5:12:57
setting. Now go to the enrollment file. Obviously I will add this deployment key.
Now this deployment key you will
5:13:02
find on the convex dashboard. So go to the convex over here. Uh make sure to
5:13:09
select the production from this option. Once you're in the production go to the
5:13:14
settings and here you will find the URL deployment key. Right now we don't uh have
any deployment key. So we'll create
5:13:21
a new one. Here we'll say prod. Save it and then copy this deployment key. Once
5:13:27
you copy it, paste it here. Okay. Now we have more environment variables. Okay.
5:13:32
So that environment variables I will get it from the env.local file. See all of
5:13:38
these. Copy everything as it is and simply paste it here. Once you paste it
5:13:44
then the last step is deploy and then your application will deploy in a
5:13:49
minute. It start building the locks. then it will install the dependencies
5:13:55
uh all the packages and then it will assign a domain for a final uh
5:14:00
production. Okay. So we'll wait to finish this deployment process and boom
5:14:05
if you see our application is deployed. If I click on this one you will see
5:14:10
application is running on this particular domain. I will put the link of the
application demo so you can try
5:14:17
this out. Okay. But in meantime if you can test our application as well. Okay.
5:14:24
So that's all for this particular uh project guys. Uh I hope you really enjoy. If
you have any question, any
5:14:30
doubt let me know in the comment section.