TRANSCRIPTEnglish

Full Stack React Project ( AI Career Coach ) - Next JS, Tailwind, Gemini AI, Prisma, Shadcn UI 🔥

5h 1m 51s58,220 words7,689 segmentsEnglish

FULL TRANSCRIPT

0:00

this is that AI powered project that

0:02

will take your resume to the next level

0:04

by building this full stack AI career

0:06

coach called Sensei with features like

0:08

user onboarding to generate interactive

0:10

dashboard displaying in demand skills

0:12

and salary Trends in your industry which

0:14

is updated weekly an AI Resume Builder

0:17

that generates ATS optimized content

0:20

based on your industry and skills and it

0:22

is fully customizable as well this

0:24

awesome mock interview feature with role

0:26

specific questions to prepare for your

0:28

upcoming interviews which also displays

0:30

your performance over time and gives AI

0:32

generated Improvement tips as well an

0:34

intelligent cover letter generator that

0:36

analyzes job descriptions and creates

0:38

tailored content accordingly along with

0:41

this fully responsive and beautiful user

0:43

interface that we will be building using

0:44

nextjs and Shad CN UI so right of the

0:47

bad we have this professional and modern

0:49

looking landing page with this beautiful

0:50

scroll animation which I'll teach you

0:52

how you can Implement as well if you

0:54

further scroll down we have the list of

0:56

features that our app contains like

0:58

interview preparation industry insights

1:00

AI powered career guidance smart resume

1:02

creation and much more we have all of

1:04

the statistics related to our app how

1:07

our app works and also some testimonials

1:09

from our users along with some

1:11

frequently asked questions right here so

1:13

we have included all of the important

1:15

elements that a modern SAS website

1:18

contains and a call to action button at

1:20

the bottom and as I always say a modern

1:22

landing page like this can play a huge

1:25

huge role on if you'll be getting a call

1:27

back from that HR or that company or not

1:29

so so let's click on get started and we

1:32

are on the login page now we can go on

1:34

and login with Google or email address

1:36

and password so let me just quickly go

1:37

on and login with Google and there we go

1:39

we have successfully logged in and it

1:40

has presented us with this user

1:42

onboarding page where we can select our

1:44

industry so let me select technology and

1:46

I'm a software developer years of

1:48

experience let's say four let's select

1:50

our skills for example if I select

1:51

JavaScript react postgress nodejs we can

1:54

enter some professional bio and click on

1:55

complete profile and here we go we are

1:58

on industry insights now this is our

2:00

dashboard page and over here you can see

2:03

on the top left we have a user drop-

2:05

down with options like manage account or

2:07

sign out if I click on manage account we

2:09

can see more details about our user we

2:11

can update our profile over here like

2:13

first name last name or email addresses

2:14

Etc if you go to security you can see

2:16

different different places where the

2:17

user is logged in right so we have all

2:19

of these production great features

2:21

implemented inside of our app let's

2:23

close this and over here you can see

2:25

there's another drop down which will

2:26

display all of our AI tools we will come

2:27

back to this very soon but here in the

2:30

industry insights you can see it shows

2:31

us The Market Outlook based on what we

2:34

have selected on the user onboarding

2:35

screen how fast our industry is growing

2:38

how much is the demand or you know jobs

2:40

inside of our industry what are the top

2:42

skills over here and it shows different

2:44

different job roles with minimum median

2:47

and Max salary for each and every one of

2:49

them right these are all the top job

2:51

roles in the industry and if you further

2:53

scroll down it will tell you the key

2:55

trends that are going on right now in

2:57

the industry and the recommended skills

2:58

that you can learn learn and all of this

3:01

data is updated constantly right every

3:03

single week you can change it if you

3:05

want as well and it will be updated in

3:07

next six days and to implement this

3:09

feature we will be setting up a

3:10

background job a crown job which will be

3:13

running every single week and not a lot

3:15

of tutorial teach you this kind of

3:17

features and that is what makes this

3:19

project different now let's go to this

3:22

growth tools dropdown and let's select

3:24

Resume Builder and we are on this form

3:27

right here right we can select our email

3:29

addresses let me just select Anish over

3:31

here some random mobile number we can

3:33

enter our LinkedIn URL our Twitter

3:35

profile we can enter professional

3:37

summary along with the skills as well

3:39

now when it comes to work experience

3:42

let's say you're entering something in

3:43

the description right let's say worked

3:46

on an Ecommerce website and now you're

3:50

St what am I supposed to write further

3:52

in this right let's say an e-commerce

3:53

websites selling clothes so you can

3:56

click on this improve with AI button and

3:59

notice

4:00

it will generate a complete description

4:03

ATS friendly description with all of the

4:04

analytics and everything as well right

4:06

using Gemini Ai and I will show you

4:09

exactly how you're going to go on and

4:10

Implement a feature like this you know

4:12

so you can build any type of AI

4:14

application we can also enter over here

4:16

our title our company from which date we

4:20

started and if it's a current experience

4:22

you can click on this else you can

4:23

select the end it over here as well and

4:25

you can click on ADD entry button over

4:27

here and this will be successfully added

4:29

and similarly you can add more

4:30

experience if you want to add education

4:32

if you want to add projects it supports

4:34

links and everything as well right and

4:36

after you have built this rume

4:38

successfully you can go to this markdown

4:40

tab over here and your complete rume

4:42

will be rendered right over here so let

4:44

me just fill this form completely and

4:46

let me come back and there we go I have

4:48

created my complete resume right over

4:51

here now obviously you want to download

4:54

this resume as well right so click on

4:56

this download PDF button and this will

4:58

allow you to download this rume as a PDF

5:00

let me click on Save and there we go our

5:02

resume is successfully downloaded

5:05

awesome if you want to save this

5:06

markdown rume in your uh you know

5:09

database you can click on this save

5:10

button over here and if you want to

5:12

directly edit this resume you know how

5:13

to edit markdown right so you can click

5:15

on edit resume and you can change

5:17

anything directly over here and then you

5:19

can click on Show preview and it will be

5:21

updated over here and you can click on

5:22

save button and to manage all of the

5:24

forms inside of our app we will be using

5:26

react hook form along with the Zod

5:29

validation Library so that you are

5:31

following all of the latest industry

5:32

standard practices as well all right now

5:35

let's go on to the interview prep page

5:38

and over here you can see we have the

5:40

data related to the users's performance

5:42

over the time what is their average

5:44

score how many questions that they have

5:46

practiced what is the latest score and

5:48

if you scroll down you can see all of

5:50

the latest quizzes that user has

5:52

attempted if you click on it you will

5:53

see the result for that particular quiz

5:55

as well along with the Improvement tip

5:57

as well so let me just go on and start

5:59

start a new quiz there we go it tells us

6:01

that this will have 10 questions let's

6:03

click on start quiz and it's loading our

6:05

quiz it has generated 10 questions using

6:08

Gemini API so let me just go on and

6:10

randomly answer these questions for now

6:13

and you can see we have this show

6:15

explanation button like if you're not

6:16

able to think for any of this question

6:18

if you on show explanation it will show

6:20

you and give you the idea of the right

6:22

answer so let me just click on next

6:23

question and randomly select all of

6:25

these and we are on the last question

6:27

let's finish the quiz and we will see

6:29

the result right over here so you can

6:31

see I have scored 20% and it's given me

6:34

this Improvement tip that I need to

6:35

focus on solidifying my understanding of

6:37

core JavaScript concept asynchronous

6:39

programming blah blah blah for every

6:41

single question it will give you the

6:43

summary of your answer and the correct

6:45

answer and along with the explanation of

6:47

the correct answer so these are the

6:50

Enterprise grade features that you see

6:52

in the big applications right and if you

6:54

go back to the interview preparation see

6:56

it showed me my latest performance which

6:58

was 20% so the chart died and we will be

7:01

using recharts for rendering all of

7:03

these charts inside of our application

7:05

and you can see inside of our

7:06

postgressql database we have all of

7:09

these data stored like related to our

7:11

assignment our resume you can see the

7:14

complete resume stored in the content in

7:16

the markdown format the industry

7:17

insights for every single user right so

7:19

that all of this data is persistent now

7:22

let's check out the AI cover letter

7:23

Builder so you can see I have already

7:25

created two cover letters over here if

7:27

you click on create new it will ask you

7:30

the name of the company enter job title

7:33

for the job description obviously you

7:34

can copy it from the job portal and

7:36

stuff like that but let's say for now

7:38

I'm going to say nodejs and mongod DB

7:43

required right let's click on generate

7:45

cover letter and this should generate a

7:48

proper cover letter that we can provide

7:49

to that particular company to you know

7:51

apply for that job so you can see it has

7:54

given us this empty columns to fill our

7:57

name address phone number email and the

8:00

complete cover letter over here as well

8:03

right it has mentioned the back end

8:04

develop at roadside coder and stuff like

8:06

that amazing let's go back to the all

8:08

cover letters and also I would like to

8:09

mention this is not a spoon feeding

8:11

course I will also give you some

8:14

assignments to do as well along with

8:15

this course right because on this

8:17

channel We Believe taking action and

8:19

building projects yourself is what makes

8:21

you a better developer so before

8:23

starting up let me know in the comments

8:25

down below from where you watching this

8:27

video and what is the best feature that

8:29

you like about this app let's get

8:30

started all right so open vs code over

8:32

here and let's quickly open our terminal

8:34

and initialize a new nextjs app so I'm

8:37

going to say npx create next app at

8:43

latest and I'm going to press enter it's

8:44

going to ask us to proceed yes what is

8:47

your project name now if you name our

8:48

project anything it will create a new

8:50

folder over here but we are already

8:52

inside of this Sensei folder I'm going

8:54

to press Dot and press enter would you

8:56

like to use typescript no would you like

8:58

to use es lint yes yes Tailwind CS says

9:01

yes of course would you like your code

9:02

to be inside of SRC no we're going to be

9:04

using App router right so yep that's

9:06

exactly the next question yes we're

9:08

going to be using App router turbo pack

9:10

yes comes from nextjs 15 would you like

9:12

to customize import allias no and there

9:15

we go it is going to be initializing a

9:17

brand new nextjs app inside this folder

9:19

right here there we go let's go on and

9:21

run this so I'm going to say npm run Dev

9:24

and it

9:25

has started a brand new server let's

9:28

click on over here there we go our

9:30

nextjs app is running now where can we

9:32

find this code so if I go back and if I

9:35

go inside this app folder right here we

9:37

have two files one is layout. JS which

9:41

basically contains the code that wraps

9:43

all of our app so if you see over here

9:45

we have HTML body and then the children

9:47

and this children is this page.js file

9:50

inside of this you can find the complete

9:52

code that we just saw so let's remove

9:54

everything inside this return right here

9:57

and I'm going to have a Dev over here

9:59

which will say subscribe to Road Site

10:01

coder which you should if you haven't

10:02

yet so yep you can see this is what is

10:05

being rendered over here all right now

10:06

next what I'll do I'll go on and install

10:09

shat CN UI so just quickly go to Google

10:11

and search Shad cnii there we go and

10:15

shat CN UI is not a component Library

10:18

this is basically a beautifully designed

10:20

components that you can copy and paste

10:21

inside of your app so this is basically

10:23

pre-built components that are built on

10:26

top of Tailwind CSS that we can fully

10:28

customize right right the ones that you

10:30

can see right here so let's see how we

10:31

can install it if I click on docs over

10:33

here and click on installation and by

10:35

the way this library is super popular

10:37

noways click on nextjs and let's go and

10:40

use npm so I'm going to copy it up and

10:42

I'm going to go back to my terminal

10:43

let's open a new terminal over here and

10:45

paste it right here so npx Shad C in at

10:48

latest in it and it's going to ask us

10:50

few question base color Yes keep it

10:52

neutral CSS variables yes and it's going

10:55

to ask us this question how would you

10:56

like to proceed it's because we are

10:58

using react 19 right and some libraries

11:02

are not yet fully compatible with react

11:04

19 so we have to choose this use Legacy

11:06

pair depths option so that it works fine

11:09

with our application all right now next

11:12

let's go and install some component over

11:14

here so over here you can see they've

11:16

given the example of button so if you go

11:19

to a button right here yep you can see

11:22

we have different different types of

11:23

components over here right so for this

11:25

button to install it we simply have to

11:27

run npx shat CN at latest add button so

11:30

let's just copy and paste it right here

11:32

and I'll show you how Shad scen UI helps

11:35

us so basically it will create a

11:37

components folder inside of our app but

11:40

before that we have to choose Legacy

11:41

Pier depths again so you can see it has

11:43

created this components folder over here

11:45

and it has created this UI folder which

11:47

is reserved for the Shaden UI components

11:49

and it has created this button component

11:51

over here and you can see This is highly

11:52

scalable component with uh you know

11:55

multiple different variants and sizes of

11:57

the but so we can better see it over

11:59

here so if you scroll down this you can

12:01

see this is a primary button secondary

12:04

color destructive color outline variant

12:06

Etc right similarly we have ghost and

12:09

multiple different sizes for this button

12:11

over here as well and if you want you

12:12

can customize this here and you'll be

12:15

good to go so you see how easy it makes

12:17

our job so if I you know let's just add

12:20

a br tag to add a line break and I'm

12:23

going to add a button from Shad CN UI

12:26

make sure to import it from this/ UI

12:28

folder only and I'm going to say hello

12:30

and let's save it and let's go back and

12:32

check yep you can see we can see this

12:34

Hello message right here now as you can

12:37

already see inside of our app we are

12:39

using this button in multiple places we

12:40

are using this card component this is

12:42

also from Shard CN UI we are using um

12:45

let's say this accordion component which

12:47

is also from shat CNU right so we're

12:48

going to be using bunch of different

12:50

things inside of our app bunch of

12:51

different components from shat CN so

12:53

what I'll do let's just go on and

12:55

install them one by one so you can see

12:57

accordion right here we just simply have

12:59

to copy this lineup and go back to our

13:02

terminal and paste it right here the

13:04

other things that we will be needing is

13:06

a badge component button we have already

13:08

installed we're going to be needing a

13:10

alert dialogue for you know asking user

13:13

confirmation or cancelling some action

13:16

right we have to use the card component

13:18

a dialogue component for displaying

13:20

models like in our case we were

13:22

displaying result after the quiz is

13:24

finished right a drop down menu input

13:28

comp component from chat CN UI label for

13:32

those inputs or you know some other

13:33

places as well progress for showing our

13:37

progress in the dashboard we would be

13:39

needing a radio group component a select

13:43

component a sonor component for all of

13:45

the toasts that you saw on the bottom

13:48

left side of the screen the tabs

13:51

component and at last text area right so

13:55

press enter and this will successfully

13:58

install all of these components right

14:00

here inside this UI folder oops

14:01

something went wrong I believe I

14:03

misspelled something oh I think it was

14:05

the radio group so it has to be g r o u

14:10

and we will also be fixing this text

14:12

area right here and yeah I think uh that

14:15

should do it let's press enter would you

14:17

like to proceed use Legacy paer deps all

14:19

right so you can see it's installing all

14:21

of these dependencies right inside this

14:23

UI folder and it's asking us the button

14:25

already exists let's let's override it

14:28

and and yep there we go we can see all

14:31

of our components right here and we

14:32

don't need to touch this unless we need

14:34

to customize it and we don't need to

14:35

customize it right now right cool then

14:37

now out of the box shaten also provides

14:40

us with the light and dark mode and as

14:42

you can see our app is in complete dark

14:45

mode right so let's implement the dark

14:47

mode as well so you can click on over

14:49

here in this dark mode and click on

14:50

nextjs and it's pretty simple you don't

14:52

need to understand what's going on over

14:54

here so just install this next themes

14:57

over here so I'll just copy it up and

14:59

paste it right here and it's going to

15:01

provide us this code which will be used

15:04

for you know handling our themes so just

15:06

copy it up and inside of components we

15:08

have to create a component called theme

15:10

provider. TSX so I'll say

15:13

theme-

15:15

provider. TSX and in our case since

15:18

we're using jsx we have to say jsx right

15:22

so paste it right here and let's get rid

15:26

of these types we won't be needing them

15:29

Yep this looks good and after this we

15:31

just have to wrap whole of our app using

15:33

this theme provider object right here or

15:35

sorry theme provider component right

15:37

here right so I'll just copy it up and

15:40

go to our layout. JS file as I already

15:43

told you this layout. JS file is

15:45

responsible for wrapping h of our app so

15:47

instead of this children I'm going to

15:48

put this theme provider right here and

15:50

let's import the theme Provider from

15:52

this/ component / theme provider and

15:55

I'll put the default theme as dark and

15:57

yeah that that is all we need to do to

15:59

set up shat CN UI great let's work more

16:01

on this layout page over here so inside

16:04

of this let's plan what all the things

16:06

that will be inside of our app so we

16:08

will have a header component okay then

16:12

we will have a main component which will

16:14

contain all of the children components

16:16

so I'll put children inside of it then

16:19

below it I'm going to have a footer

16:21

component right let's just create this

16:24

footer right away and for this main tag

16:26

I'm going to give the class name of

16:28

minimum IM um height to be screen and

16:32

this footer let's just have a footer

16:33

component over here inside this I'm

16:35

going to have a d inside that I'm going

16:38

to have a paragraph tag which will say

16:41

made with love by roadside coder let's

16:43

go back and see yep we can see it right

16:46

here and you can see our app is now in

16:48

the dark mode as well great let's give

16:51

it some styling so if you have not work

16:53

with Tailwind CSS is pretty similar to

16:54

bootstrap you just have to say class

16:56

name over here and you can start giving

16:58

the class name which are inbuilt in

17:00

typescript and you can refer to

17:01

typescripts documentation and I will

17:03

also show you how you can use it right

17:04

here so like for example if we have to

17:06

add a background color of muted and by

17:09

the way these colors are predefined in

17:11

shat cnii so if you go to this global.

17:14

CSS you can see we have different

17:16

different types of colors that are

17:17

defined over here for muted it's this

17:20

muted foreground you can you know check

17:21

more about these in the shats and UI

17:24

documentation about what these colors

17:26

are exactly so I'll say background muted

17:28

and SL I'll provide the 50 opacity I'll

17:31

say padding vertical so py and if you

17:34

hover on these Styles you're going to

17:35

see we have padding top and padding

17:38

bottom to be 48 pixels you can see the

17:40

exact values right similarly for our da

17:43

as well I'm going to provide the class

17:44

name of container now what is a

17:46

container class so basically container

17:48

provides us with some break points like

17:50

for example in the smaller screens we

17:53

have Max width of 640 pixels in the you

17:56

know medium screens or screens less than

17:58

768 pixels we have Max withd this and

18:00

different different things right so this

18:02

helps make our websites more responsive

18:06

so I'll say MX Auto so that we can

18:08

display it at the very middle some

18:10

padding horizontal of four text is going

18:13

to be in the center and text Gray is

18:18

going to be 200 let's see Yep this is

18:21

exactly what we wanted amazing for our

18:24

header right here let's just quickly

18:26

create a header component as well so I'm

18:27

going to create a new file

18:29

called header. jsx R A fce and I'll say

18:35

header over here let's import our header

18:40

over here make sure to import it from

18:41

slash

18:43

components let's see yep we can see the

18:45

header over here as well now before

18:47

moving forward before doing anything

18:49

else let's start working on our user

18:52

authentication so click the link in the

18:53

description down below and you will land

18:55

on Clerk and this is the most

18:57

comprehensive user manager platform as

18:59

you have already seen in my previous

19:01

videos I love to use cler because it

19:03

provides us user authentication and user

19:05

management right out of the box so let's

19:08

click on start building for free and

19:10

let's go on and log in with Google and

19:12

you will see a similar interface now

19:13

here we can add the name of our

19:15

application so let's say Sensei we can

19:18

choose what are all the authentication

19:20

types that we are going to be adding

19:22

inside of our app like for example we

19:23

can add email password we can add Google

19:26

login as well or like username phone

19:28

number bunch of different things right

19:29

and I'll show you how easy it is to

19:31

implement inside of our application so

19:33

let's just choose both email and Google

19:35

and click on create application and we

19:37

are in amazing and you can see it tells

19:40

us exactly how we can go on and add

19:42

clerk inside of our application so I've

19:44

chosen nextjs over here so all we need

19:46

to do npm install at clerk / nextjs okay

19:49

I'll copy it up and go back to my

19:52

terminal and paste it right here now

19:54

what's next we are supposed to set up

19:57

our environment variable so that

19:59

app can connect to clerk so okay let's

20:01

copy it up and instead of our app I'm

20:03

going to be creating a new EnV file this

20:06

will contain all of our secret

20:07

environment variables and which we are

20:09

not supposed to share with the world

20:11

right and obviously if you try to use my

20:13

environment variable they won't work

20:14

because I would have deleted them after

20:16

the video okay after that we have to

20:18

create this middleware DJs file now what

20:21

is this file all about so this file runs

20:24

before our application is run right so

20:26

before our application starts we need to

20:28

figure out some things like for example

20:30

in this case user authentication so you

20:32

can see it is going to initialize the

20:34

clerk before our application is accessed

20:37

so I'll copy it up and I'm going to

20:39

create a new file

20:41

middleware do JS and paste it right here

20:45

just like this then next we are supposed

20:47

to wrap our app inside this clerk

20:49

provider function okay let's see so if

20:52

we go to our layout. JS this whole thing

20:56

this whole app is supposed to be wrapped

20:57

in clerk Prov provider so let me just

20:59

move it to the very bottom and let's

21:03

import clerk Provider from at clerk SL

21:06

nextjs like this and also by the way we

21:09

don't need both of these fonts right

21:11

here so I'm going to remove them and we

21:13

would be needing the font

21:15

enter and let's just add this font right

21:17

here so simply you have to do const

21:19

enter equals we have to import enter

21:21

from next SL font / Google subsets Latin

21:25

so this is basically just for changing

21:28

the font of our application if you don't

21:29

want to keep it that's fine you can use

21:31

some other font so over here in the body

21:35

I'm going to remove this let's remove

21:37

this class name and over here simply I'm

21:40

going to say enter do class name this is

21:42

just a onetime configuration don't worry

21:44

about it we're just adding the fonts

21:46

inside of our app and let's just change

21:48

the title to AI career coach or you can

21:53

also say Sensei AI career coach and you

21:57

can add your description according to

21:58

you right all right now let me show you

22:01

how easy it is to set up the user

22:03

authentication using cler so what I'll

22:05

do over here you can see we have this

22:06

example over here so I'm just going to

22:09

quickly copy it up and I'll go to my

22:12

header. jsx and inside of it I'm going

22:14

to paste it and import all of these

22:17

things from clerk so clerk / nextjs

22:19

signed in component user button

22:22

component all of them right now you're

22:24

going to notice if I go back to my app

22:26

we are getting this warning right here

22:28

hydration warning oh so this is actually

22:31

H this happens because like when we add

22:34

this theme provider inside of our

22:36

application to so you can check the shat

22:38

scen U documentation as well they have

22:40

recommended that you can simply add

22:43

inside of the HTML this thing suppress

22:45

hydration warning and you won't see this

22:47

error so what's going on over here so

22:49

basically we're saying that if the user

22:51

is signed out then show the signin

22:53

button and if the user is signed in show

22:56

the user button let's see you can see we

22:59

have this signin button over here or

23:01

sign in text if I click on it what's

23:03

going to happen it takes me to a

23:04

completely separate login page amazing

23:07

and we didn't even do anything right we

23:08

just took that code from Clerk and

23:11

obviously this is highly customizable as

23:12

well so if I click on continue with

23:13

Google it's going to allow me to sign in

23:16

and let's see we are in you can see we

23:18

have this user drop- down button right

23:20

out of the box coming from cler right

23:22

click on manage profile you can see we

23:24

can update our profile over here as well

23:26

update our profile picture like for

23:27

example if I go back inside this

23:29

configure tab in clerk you can add some

23:32

options over here like for example I

23:34

want users to be able to change their

23:36

name as well right so I'll enable this

23:38

and now if I go back I'm going to click

23:40

on update profile and now I'll be able

23:42

to change my name right here amazing and

23:46

you can also go to this security tab to

23:48

see where you are logged in and you can

23:50

delete your account as well right so

23:51

yeah all of these things comes right of

23:53

the box from clerk let's go on and

23:54

properly design our header for our

23:57

application so you can see see inside of

23:59

our deployed app we have this logo right

24:01

here right Sensei AI so you can get this

24:04

logo from my GitHub repository so just

24:07

click the link in description down below

24:08

and you will land on this GitHub

24:09

repository right here and if you go to

24:12

public folder over here you can find

24:14

different different things like for

24:15

example this logo that I've kept apart

24:18

from that I have three different types

24:20

of banner so that all of you know all of

24:22

you building this app don't have same

24:24

types of banner images inside of your

24:26

app right so I'm going to go on and

24:29

download both of these there we go I've

24:31

downloaded them and kept it right here

24:33

in my public folder let's get rid of

24:35

these SVG files we won't be needing them

24:38

so delete all right so right here in the

24:41

header component let's above it I'm

24:44

going to change it to header inside this

24:47

I'm going to have a nav tag over here

24:49

which will contain all of the navigation

24:51

items of our app like for example first

24:54

of all I'm going to add a link tag so

24:56

link tag in nextjs basically helps us to

24:59

navigate between different different

25:00

pages so this link tag takes a h riff

25:04

just like our anchor tag in HTML right

25:07

so this will be let's say slash for our

25:09

homepage and to add any image inside of

25:12

nextjs we use this image tag which comes

25:15

from next SL image and the reason for

25:17

this is this optimizes our images in the

25:21

server right and sends it to our client

25:23

so let's say SRC equals SL

25:26

logo.png let's save this this and see we

25:29

cannot see anything over here in fact we

25:31

have an error over here that missing

25:33

required width property so yep this

25:35

takes a width and height property over

25:37

here as well and we will also give this

25:39

the alt tag that is the description of

25:41

the image so let's just say Sensi logo

25:43

and width and height let's just give

25:46

this some class name of height to be 12

25:51

so this is basically the resolution of

25:53

the image right and here I'm going to

25:55

provide the Styles like padding vertical

25:57

to be one

25:59

width is going to be Auto and object to

26:01

be contained so that it doesn't get

26:03

deformed let's see now yep that is

26:06

exactly what we wanted below this link

26:08

let's add some action buttons right like

26:10

for example to be able to navigate to

26:12

our dashboard or industry insights or

26:14

the d drop down menu uh displaying all

26:17

of our AI tools and you can see so

26:19

inside of this div we will display all

26:21

of those things only if our user is

26:24

signed in right so I'll say signed in

26:28

and insert this I'm going to first

26:29

display the link tag to our industry

26:32

insights right so I'll have a link tag

26:36

which will have a button which will

26:38

obviously be coming from Shad Cen UI so

26:40

make sure to import it from / ui/ button

26:42

inside this we can add an icon over here

26:45

as well along with the text so you don't

26:48

need to worry about the icons because

26:49

Shad CN UI contains Lucid react package

26:53

which you know contains all of the icons

26:55

so just say layout

26:58

dashboard and you can see we're able to

27:00

import it from Lucid Das react and let's

27:03

give this some class name of height to

27:06

be four width to be four and below this

27:09

I'm going to say industry insights let's

27:13

see how this looks oh of course we need

27:15

to give the link tag a HF let's just

27:20

call it dashboard if you want to call it

27:22

something else again that is up to you

27:25

yep that looks good we need to obviously

27:28

this a little bit more so what I'll do

27:30

I'll go to this header right here I'm

27:31

going to say class name and our header

27:34

will be fixed on the top right I'll say

27:36

top to be zero and width is going to be

27:40

full let's give it some border bottom

27:43

and some background color to the

27:46

background from shat Cen right as

27:48

already told you these things are

27:49

already defined in the global. CSS file

27:52

you can go and check it out and I'll

27:53

keep the opacity to be 80 I'll say back

27:57

drop blur to be medium so that if

28:01

anything comes behind our header it is

28:04

you know it has the blurry effect I'll

28:05

say Z index to be 50 so that this

28:08

remains on the top and I'm going to say

28:09

it supports backdrop filter right and

28:13

then I'll give it the background of

28:16

sorry BG to be background color with the

28:20

60 opacity let's see how this looks like

28:22

this looks pretty good and you can see I

28:24

think whatever behind this I think there

28:26

was a button right it went behind this

28:29

header now and we'll come back to this

28:31

to fix it right now for this nav button

28:34

right here I'm going to give this some

28:35

class name to be container I've already

28:38

told you what container does mx Auto

28:40

said everything is in the middle padding

28:42

horizontal to be four height to be 16

28:46

and I'm going to give this some display

28:47

Flex so that everything is in one single

28:48

line and items to be Center so that we

28:51

vertically align it and horizontally I

28:53

want justify between so that they are on

28:56

Far ends of each other let's see yep

28:58

that is what we wanted now one thing

29:00

that I want to do over here is make this

29:02

website responsive out of the box right

29:04

so when this becomes smaller we don't

29:08

want to show this whole button right

29:09

here so what I'll do let's just put it

29:12

into a span tag right here and over here

29:15

I'm going to give this class name of

29:17

hidden by default and when it's more

29:19

than the medium screens I'll say display

29:22

to be block so now you will see if it's

29:25

less than medium screens yep that is

29:28

exactly what we want to do great now

29:31

after this we're going to be showing a

29:33

drop- down button which will display all

29:35

of our growth tools right so after this

29:38

let's go back to shat ceni documentation

29:41

and over here we have to find the drop

29:44

down menu component and we already

29:45

installed it so if I click on it you can

29:47

see this is how it will look like okay

29:49

so let's take this code right here I'm

29:52

going to copy it up and paste it right

29:55

here so let's import them one by one and

29:57

make sure to import it from from /ui

29:58

folder and not the radx UI right so

30:01

sometimes we make this mistake and then

30:03

it won't work so let's import all of the

30:07

separator and yeah I think they would

30:09

have been imported now oh I think I did

30:11

not import this drop down menu item now

30:15

it would be important yep if I click on

30:17

open yes we can see the drop down all

30:20

right let's uh configure it according to

30:22

us we would need the three items over

30:24

here and we won't be needing the

30:26

separator and the label okay for the

30:29

trigger here I'm going to Simply add a

30:31

button just like we have done right here

30:33

so I'll just take this button and paste

30:36

it over here instead of this layout icon

30:38

I'm going to add the Stars icon over

30:40

here and instead of this industry

30:42

insights let's just say growth tools and

30:44

below this let's add an icon for you

30:47

know indicating the Chevron down key you

30:50

know indicating a drop down over here so

30:52

let's see um yeah that is exactly what

30:55

we wanted let's create some gap between

30:57

both of these so over here in the div we

30:59

would need to give some class names so

31:01

I'm going to say display flex and items

31:03

to be centered so that they are

31:04

vertically in between and some space X

31:06

tob2 so that they have some space

31:08

between them and when the screen size is

31:10

bigger we will add Space X to be 4 yep

31:13

that is what we wanted all right so now

31:15

over here for each and every one of

31:17

these I'm going to add a link tag which

31:20

will take us to that particular you know

31:21

growth tool like for example Resume

31:23

Builder cover letter Builder or you know

31:25

interview preparation page again inside

31:28

the link tag I'm going to have two

31:29

things one uh icon and the name of the

31:32

growth tool so over here we just going

31:34

to get rid of this class name inste of

31:37

this Stars icon I'm going to say file

31:38

text icon so import it from Lucid react

31:41

and I'll say build resume let's see if I

31:44

click on it oh yeah of course this again

31:47

needs the HF tag which will be slash

31:50

resume and I'll give this the class name

31:52

of display Flex items to be Center and

31:54

some gap of two between them so now we

31:57

should see this if I click on it yep

31:59

build resume similarly I'm going to do

32:00

for both of these as well so let's just

32:03

copy it up and paste it right over here

32:06

and then we will change it for the cover

32:08

letter I'm going to add a pen box icon

32:11

and for the interview prep page we're

32:13

going to add a graduation cap icon so

32:15

let's just import both of these and now

32:18

let's see yep that is exactly what we

32:20

want let's change the link so for this

32:23

one I'll say AI cover letter and for

32:27

this I'll just simply send it to the

32:29

interview page okay now after this we

32:33

need to display our you know login

32:35

button and user button so let's move

32:38

this back inside of over here inside

32:40

this div and when the user is signed out

32:43

we don't want to show this sign in

32:44

button instead this will have some

32:47

children inside of it where we will

32:49

render the button from Shad cnii so I'll

32:52

say sign in also by the way we want to

32:56

differentiate between both of these

32:57

variant right so for my dashboard or the

33:00

this uh industry insights let's just say

33:03

variant to be outline and let's go back

33:06

and Y that looks much better and for

33:08

this thing right here okay sign in

33:10

button I want this to have the variant

33:13

of outline as well so if I go now and

33:16

try to log out let's click on sign out

33:19

over here you can see just the sign in

33:21

over here and growth tool wise it's

33:23

showing up over here I think we need to

33:25

move it inside of this signed in so just

33:28

take this signed in from over here and

33:30

put it right here now it should not show

33:33

up just the signin button okay now for

33:35

our user button over here if we quickly

33:38

go on and sign in again there we go you

33:40

can see it is very small right the

33:42

circle is very small so we can customize

33:43

it actually over here in the user button

33:46

we have a appearance prop inside of this

33:49

let's just say elements we can choose

33:51

the element and we need to choose the

33:54

Avatar box which will be width to be 10

33:57

and and height to be 10 user button pop

34:00

card is going to be Shadow Xcel and user

34:02

preview main identifier is going to be

34:04

font semi bold so you will see this will

34:06

have some Shadow and some font to be

34:08

semi bold okay and we can also Define

34:11

when we click on sign out where this

34:13

page goes right so for now I'm going to

34:15

keep it slash only if you want to keep

34:17

it something else I've kept it right

34:19

here looks like this is deprecated but

34:21

don't worry it will still continue to

34:23

work all right now let's try to uh click

34:26

on this industry insight we're going to

34:28

click on it and this will take us to

34:29

the/ dashboard page and again this page

34:31

does not exist but still we are logged

34:34

in right now right if we log out you're

34:36

going to see it took us to the slash

34:38

page right that's fine but now if I try

34:40

to go to slash dashboard page it should

34:43

not allow me to land over here because

34:44

we are not logged in right now right

34:47

even though this page does not exist it

34:49

should us it should route us to our home

34:51

page right or maybe our signin page

34:53

where we can sign in so let's add this

34:55

protection to our app so I'll go to the

34:57

middle .js file and over here on the top

35:00

I'm going to say cons is protected route

35:04

and we can add the different routes that

35:05

we want to add over here so we'll import

35:08

create route matcher inside this we will

35:12

give an array and we can Define all of

35:14

our routes right over here so our routes

35:17

will be dashboard resume interview AI

35:20

cover letter on boarding right all of

35:22

these and I've added dot asteris over

35:25

here that means anything that comes

35:27

after it

35:28

will also be a private route okay now

35:30

after it inside this export default

35:32

clerk middleware we're going to be

35:34

adding a call back and this will be an

35:37

asynchronous call back which will take

35:39

the Au and the request object and we

35:43

will work with these to you know add the

35:45

production to our app first of all I'm

35:47

going to say await o and this will give

35:51

us our logged in user's ID so const user

35:54

ID then after it right that is user is

35:56

not logged in right now and is protected

36:01

route that is this thing right here

36:04

we're going to pass the current route so

36:05

I'll pass this request object if request

36:08

object does not contain any of these

36:10

then we will route them back to the Lo

36:12

login page right so I'll say await or

36:15

and this will give us something which

36:17

will be redirect to sign in and we can

36:20

simply take this and in the next line

36:22

I'm going to say return redirect to sign

36:25

n that's it we're going to call this

36:27

function and this this will continue to

36:28

work this will reroute us back to the

36:30

signin page and then in the end I'm

36:32

going to say return next response. next

36:34

that is whatever comes next we can

36:36

continue our app after this and make

36:38

sure to import it from next SLS server

36:40

okay now let's try to do this again if I

36:43

try to go to/ dashboard you can see it

36:46

sent us back to this signin page but

36:49

wait you might be thinking what is this

36:50

URL over here this is a weird sign-in

36:53

page right I want the sign-in page to be

36:55

inside of my application and and not go

36:57

to some third party URL right and that

36:59

is exactly what we will be implementing

37:01

next But first you can see our app is in

37:03

dark mode right and this is light mode I

37:05

want this to be in dark mode as well so

37:07

what I'll do I'll go to my layout. Js

37:11

and in the clerk provider I'm going to

37:13

say appearance and inide of this it

37:16

takes a base theme and this will

37:19

basically be dark so I think we need to

37:24

import it or probably install it from uh

37:26

some package let me me just check inside

37:29

of the clerk Yep this is what we want

37:30

npm install at clerk SL themes you can

37:33

find it in the docs right so I'm going

37:35

to paste it right here and P install at

37:37

cl/ themes and this will install it and

37:40

from here we can you know get a lot of

37:42

themes like for example you can see we

37:43

have different different types of themes

37:44

right here and this is what I need all

37:46

right so this has finished installing

37:48

let's try to import it yep from at clerk

37:50

/ themes and now if I go back to my app

37:53

looks like it won't work on this page

37:55

but it will work on the component when

37:57

we go on to add this signin component

37:59

inside of our app right so okay let's

38:01

try to do that and how are we going to

38:02

do that we have to define the custom uh

38:05

you know signin page for our application

38:07

and to do that we have to go to the EnV

38:10

file and we have to add four environment

38:12

variables over here actually two

38:13

environment variables other two are

38:15

going to be for something else so first

38:16

one will be next public clerk signin URL

38:19

this will Define the signin URL for our

38:21

app and the second one will be sign up

38:24

URL sign up right now what will happen

38:28

when the user signs in or signs up so

38:31

I'll say next public clerk after

38:33

signning URL to be SL onboarding and

38:36

after signup URL to be/ onboarding as

38:38

well all right now you're going to

38:40

notice if I go back to my local host

38:42

3000 I'm not dashboard I mean just the

38:45

Local Host 3,000 if I click on sign

38:48

button this will take me to/ signin but

38:50

this page does not exist so what should

38:51

we do inside of our app now we going to

38:54

be creating a brand new route right and

38:56

don't worry I'll show you very soon the

39:00

in-depth ways to create you know routes

39:03

inside of our next CH but for now just

39:04

try to understand what I'm trying to do

39:06

over here if I want to create a new

39:08

route I have to create a new folder

39:10

that's all if I let's say sign Dash in

39:13

this is now a new route inside of our

39:16

application like if I say new file page.

39:19

jsx and this very important you have to

39:20

create a file called page. jsx for it to

39:22

be recognized as a route so I'll say

39:25

page and um let's say sign in right

39:30

let's see if I refresh this now I think

39:33

this is in like behind our header right

39:36

now if I just remove my header from over

39:39

here let's get rid of this header y you

39:41

can see the sign in is behind this

39:42

header let's take care of this as well

39:44

we don't want things to be uh you know

39:46

overlapping our header so what I'll do

39:48

over here I'll create a sign up folder

39:51

over here as well sign Dash up and I

39:55

want to provide some common styles to

39:57

both both of these so what will I do I

39:59

want to grip them somehow right and to

40:01

grip them I'm going to create a new

40:02

folder called o but this won't work

40:05

right this will create a new uh route

40:06

and I don't want to Nest another route

40:09

like / signin so what I'll do I'll wrap

40:11

it inside of parenthesis and this will

40:14

essentially ignore this folder as a

40:16

route right so if I move both of them

40:18

inside of it move now this won't be

40:21

considered as a route right here and I

40:23

can provide it a

40:25

layout. Js file and whatever we write

40:29

inside of this file will directly affect

40:30

both of these right so I'll say R A fce

40:33

let's say o layout and I'll take the

40:37

children over here and I'll render them

40:41

right here so this sign in and sign up

40:44

will render right over here and I can

40:46

Pro now provide some common Styles like

40:48

for example I'll say class name display

40:50

Flex justify to be Center and padding

40:52

top to be 40 let's check it out if I go

40:55

back and ref refes this yep you can see

40:59

sign in right over here now instead of

41:00

this sign in I'm going to display the

41:03

clerk's signin component right so if you

41:06

go to the clerk's documentation you will

41:08

find that there's a convention on

41:10

creating these signin pages right what

41:12

you have to do you have to create this

41:14

signin route first then inside of this

41:15

you have to create a new folder which

41:18

will contain a catch all route and we

41:20

will discuss what this catch all route

41:22

is basically you have to write two

41:24

square brackets inside of it dot dot dot

41:27

sign Dash in and this is basically an

41:30

optional route if you have anything over

41:32

here it will catch it like for example

41:34

if you go back you can see we have all

41:36

of these options over here right so

41:37

these are for clerk to be managed so

41:40

that's why you have to create this scat

41:42

all route over here and let's move this

41:44

page. jsx inside of it move now inside

41:47

this page. jsx simply all we have to do

41:50

is to import a sign in component from

41:54

clerk that is all let's get of this

41:56

import Port react and now let's see yep

42:00

you can see such a beautiful sign in

42:03

form right here and this is right inside

42:05

of our application if I go back and try

42:08

to click on sign in yep you can see we

42:12

are landing on the signin page great

42:14

let's do the same with our sign up page

42:16

as well so inside of the sign up page

42:17

I'm going to get a new folder and I'll

42:20

add a catch all route for sign Dash up

42:23

inside of this I'm going to add this

42:26

page. j6 file so I'll create a new file

42:30

page. jsx paste it instead of sign in

42:34

I'm going to say sign up right let's

42:37

remove this sign in over here and let's

42:40

see if I click on sign up it should take

42:42

me to sign up page all right we can you

42:45

know fill up this form and create a new

42:48

user all right great so we have

42:49

successfully set up our user

42:51

authentication and now let's go on and

42:53

connect our back end or you know set up

42:56

our database basically so click the link

42:58

in description down below and you will

42:59

land on neon and this is a postgress SQL

43:03

database and you already know how

43:05

important it is to be knowledgeable

43:07

working with a post SQL database right

43:09

so I'll tell you everything about how

43:11

you can get your database set up and

43:13

also use it alongside with Prisma orm

43:16

which again is a super trending

43:18

technology nowadays right so click on

43:20

get started and let's log in with Google

43:23

and we are in now we're going to create

43:25

our project so let's name our projects

43:28

and say database name we can just keep

43:30

it empty and click on create project

43:32

there we go we are in let's go on and

43:34

set up our database so all we need to do

43:37

we need to go to this overview tab over

43:39

here and this roles and databases and

43:42

click on ADD roll let's add rule of

43:44

roadside coder that I'll be the one

43:46

managing this database create and then

43:49

below it we need to add our database

43:51

right if you want you can copy this

43:53

password over here as well let's click

43:54

on ADD database and let's name the

43:56

database

43:58

Sensei and the owner will be roadside

44:00

coder let's click on Create and yeah

44:02

with that we have created our database

44:04

successfully let's go to our dashboard

44:06

over here let's choose the database and

44:10

the owner and we can simply copy this

44:13

connection string from over here right

44:15

and then go back to your app and inside

44:17

of EnV file I'm going to create a datab

44:22

basore URL equals and I'll assign it

44:26

right over here so basically this

44:28

connection string will enable us to

44:30

connect our project and to communicate

44:32

with neon DB using something called as

44:34

Prisma omm which I'll show you in just a

44:36

moment but let's set go on and set up

44:39

the service which we will be using for

44:41

managing our background jobs like you

44:43

know fetching the industry insights

44:45

every single week so click the link in

44:46

description down below and you will land

44:48

on inest and click on sign in over here

44:51

quickly I'm going to sign it with Google

44:53

and there we go we are in let's click on

44:55

take me to onboarding and you can see

44:57

over here they've given us this command

44:59

so just copy it up and go back to your

45:02

terminal just run npm install injust

45:06

first so that it installs the injust

45:08

inside of our application and then we

45:10

can run npx in/ CLI at latest Dev

45:14

proceed yes there we go it has

45:17

successfully ran inest on our local

45:20

machine and click on this Local Host

45:22

link right here and there we go our

45:24

inest server is running in our Local

45:26

Host okay so let me just open the injust

45:28

docs over here real quick so we have

45:30

already ran this Command right here and

45:32

we can see our injust running now we

45:35

have to create an inist client and to do

45:38

that we have to do new inist and provide

45:40

the ID of our app okay so what I'll do

45:42

I'll go back and insert this lib folder

45:46

over here I'm going to be creating a new

45:48

file and actually new folder for

45:52

inist and I'm going to be creating a new

45:55

file called client do JS andert this I'm

45:58

going to Simply paste this code so I'll

46:00

just copy it and paste it right here

46:03

right let's name our app Sensei and this

46:07

will also take the name so I'll just say

46:10

Sensei just like that and this will take

46:13

more things like for example later on we

46:15

will go on and configure our credentials

46:17

for the Gemini API key right so yeah we

46:20

will come back to this later let's go to

46:22

the docs and see what else so now we

46:24

have to set up this/ API SL inest route

46:27

inside of our application now how does

46:29

inest actually works so in nextjs we

46:33

have something called as this API folder

46:36

right and inide this we can as the name

46:38

suggest build our apis right it can be

46:40

public API can be private API so we have

46:43

to build a public API for inest to

46:46

connect to our application right so you

46:48

can see we just have to say/ API SL

46:51

inest so I'm going to say new folder

46:53

inist and so that this AP works we have

46:58

to create a route inside of it route

47:00

file so I create new file route. JS

47:04

inside this route. JS file we have to

47:07

add this code right here so just copy it

47:10

and paste it right over here and also

47:13

we're going to remove this because our

47:15

inest client will be coming from at lib

47:18

slin client so what is going on over

47:20

here so we have created this API with

47:24

get post and put requests and this serf

47:26

function which also comes from inest /

47:29

nextt and now over here we can Define

47:31

our functions which will be running in

47:33

the background let me show you how you

47:34

can quickly go on and create the

47:36

function so over here they've given this

47:38

example in the code of a simple hello

47:40

world function right let me just copy it

47:42

and explain you how this works so um

47:45

let's say I'll go insert this inest

47:47

folder and create a new uh like file

47:49

called functions do JS and paste it

47:53

right here now this function takes an ID

47:56

of hello world and the event of test/

48:00

hello. world now this event right here

48:02

is something which will trigger this

48:04

particular function over here right so

48:06

this is very important over here this

48:08

first object takes more things like for

48:10

example if you want to add the retries

48:13

that is how many times this function

48:15

will retry before it fails in the

48:16

background it also takes things like

48:19

rate limiting throttling ability to bash

48:22

the events debouncing and much much more

48:25

right so you can find all of these

48:26

things in the official NES documentation

48:29

and learn more about it okay so now what

48:31

we are doing inside of it we're simply

48:33

saying that make this function wait for

48:37

1 second and then we will return a

48:40

message called event. data. email which

48:42

will be provided by us right so this

48:45

takes the event and the step so injust

48:47

functions are executed in different

48:49

different steps over here right and over

48:51

here we just have added a step of sleep

48:54

so now if I just take this and where did

48:58

it go I'll go back to my route. ts and I

49:00

can import this right here right so

49:03

import hello world from in just SL

49:05

functions and now if I go back to over

49:07

here in in my development server inside

49:10

the app you can see it has all autod

49:11

detected it inside of the functions we

49:13

can see this hello world function and we

49:15

can manually invoke it from over here

49:18

right obviously inside of our app we

49:19

won't be manually invoking it and you

49:21

can see it's asking us for some data if

49:23

we want to provide let's say email and

49:26

and let's say example at

49:30

gmail.com click on invoke function it

49:32

will wait for 1 second and yeah you can

49:35

see it has already completed the

49:37

function and provided us this message

49:39

hello whatever the email was and you can

49:42

see we have this wait a minute step run

49:45

over here right we can see the data that

49:47

we have sent to inest yep right here

49:49

email so this is a very basic example of

49:51

an injust function again we will be

49:53

coming back to this and build our

49:56

industry insights function which will be

49:58

fetched every single week right so let

50:00

me just um get rid of this for now and

50:04

we will come back to this very soon and

50:06

if you're someone who's preparing for

50:07

frontend interviews you can definitely

50:09

go and check out my front-end interview

50:10

preparation course this is the only

50:13

thing that you will ever need to prepare

50:14

for your fronted interviews and not only

50:16

this I've covered every single topic of

50:18

reactjs like react router D Redux all of

50:21

the hooks class based component function

50:23

based component react even the

50:25

performance optimization

50:27

which is asked from senior developers a

50:28

lot tons of machine coding questions as

50:31

well and obviously in-depth interview

50:33

preparation course on JavaScript as well

50:35

and not just this along with this course

50:38

you get an active Discord Community

50:40

where you can ask your doubts whenever

50:42

you get stuck and we will be there to

50:44

help you so click the link in

50:45

description down below because right now

50:47

we're having the biggest sale of the

50:49

year for a very limited time so don't

50:51

forget to check it out or you can also

50:53

scan this QR code on your screen to go

50:55

directly to the the course page and now

50:58

let's go on and build our beautiful

51:01

landing page right here as I've already

51:03

told you having a beautiful landing page

51:05

like this plays a huge role on if you'll

51:08

be getting that call back from your

51:09

recruiter or not right and you can see

51:11

this looks super professional with all

51:14

of this you know grid background and

51:15

everything with all of the FAQs provided

51:17

over here as well so cool then let's get

51:21

started we have already imported this

51:23

banner. jpeg from my GitHub repository

51:26

which we will be needing while building

51:28

our app right all right so I've opened

51:29

my page.js file over here let's remove

51:32

everything inside of it and let's see

51:35

what are all the things that we will be

51:36

adding inside of it so first of all

51:38

obviously we have a hero section this

51:40

hero section right here then we will

51:41

have the feature section the statistics

51:44

how it works what our users say and

51:47

obviously frequently asked questions

51:49

okay so let's first add this background

51:52

that you can see over here right this

51:53

grid background to our app so I'll go to

51:56

my Global start CSS file and right on

51:59

the bottom I'm going to create a class

52:01

name called grid Das background inside

52:04

this I'm going to add a position fixed

52:06

top to be zero left to be zero width and

52:09

height to be 100% for our page right

52:11

because this is going to be fixed and

52:13

we'll be inside whole of our app okay so

52:15

to create those lines I'm going to be

52:17

adding this background property over

52:19

here of linear gradient so basically

52:21

what we will be doing we will be

52:22

creating a line of one pixel with the

52:26

opacity of of 10% or

52:28

0.1% right and it will go from left to

52:30

right similarly we will create another

52:32

line or linear gradient which will go

52:33

from top to bottom right and we will do

52:37

it with the gap of 50 pixels right so

52:40

I'll say background size to be 50 pixel

52:44

and 50 pixels I'll say pointer events To

52:47

None because we don't want to select it

52:48

and Z index to be minus one so let's

52:50

take this grid background and go back to

52:52

this page. jsx I'll add a div over here

52:55

let's actually rename this file to page.

52:58

jsx and give this the class name of grid

53:00

background and let's see yep that is

53:02

exactly what we wanted let's add a

53:04

radial gradient over here right if you

53:06

notice this is fading on the sides but

53:09

it's visible in the middle so I'll go

53:11

back to global. CSS and below this I'm

53:14

going to say dot grid background and

53:17

I'll add before sudo element and inside

53:21

of it let me just quickly get the Styles

53:23

and I'll explain you so content is

53:25

nothing we don't want to display

53:26

anything the position is going to be

53:28

absolute for this gradient top zero left

53:30

Z width 100 and height 100% right that's

53:33

like covering the whole page but we're

53:37

saying add a radial gradient property of

53:40

circle and transparent and it will be 9%

53:43

opacity right so now you will see yep

53:46

just like this this is exactly what we

53:48

wanted and you know don't stress much

53:50

about this in real world you will most

53:52

probably be searching in chat jpt or

53:55

Google to find a property like this

53:57

right you won't be having to create this

53:59

from scratch anytime soon all right so

54:02

coming back to this page. jsx we will

54:04

first be having the hero section so

54:06

right below it I'll have a hero section

54:09

component now one thing that you need to

54:12

understand in nextjs is there are two

54:14

types of components a server component

54:17

and a client component like for example

54:18

this page this does not have any flag on

54:21

the top so this is a server component if

54:23

I were to make this a client component I

54:25

would have to add use client now what is

54:27

the difference between both of these so

54:29

client component can have logic like

54:31

hooks right and which which cannot work

54:33

on our server right which cannot work on

54:35

our back end so that's why we have to

54:37

make them work in our front end right

54:39

that's why they are client component and

54:40

the server component are basically those

54:42

component which generally are rendered

54:43

on a server and contains the information

54:46

which is crucial for probably the SEO

54:49

let's create this hero section component

54:51

um over here so I'll get a new file

54:53

called hero. jsx or

54:57

afce hero section okay let's import it

55:01

right here just like this now uh over

55:04

here let's just wrap it in a section tag

55:08

and start this I'm going to have a Dev

55:11

which will contain another Dev which

55:13

will have our H1 and we will simply say

55:16

your AI career coach for professional

55:18

success and this section right here will

55:20

have class name of width full some

55:22

padding top of 36 right we can see this

55:25

and in Media medium screens like screens

55:27

more than medium screens we're going to

55:29

have padding top 48 and padding bottom

55:31

to be 10 let's see Yep this is what you

55:34

wanted below this H1 we are also going

55:36

to be having a paragraph tag which will

55:38

say Advance your career with

55:39

personalized guidance interview prep and

55:41

AI power tools for job success now below

55:44

this div over here we will display the

55:46

two buttons for getting started and

55:48

watching the demo of this so I'll have a

55:51

d which will contain a link tag which

55:54

will contain a but Buton from shat cnii

55:58

which will say get and the link will

56:00

have the hrf of/ dashboard when we click

56:05

on get started okay for this button

56:07

let's just provide the size of large and

56:09

class name of padding horizontal to be8

56:12

Let's duplicate this link just like this

56:15

and if you have any demo video you can

56:17

add the link to it over here I'm going

56:18

to Simply add the link to my YouTube

56:19

channel is that because that's is the

56:21

place where this tutorial exists and

56:24

this button will have the variant of

56:26

outline that's all let's see link is not

56:29

defined okay let's import link from next

56:31

SL link and there we go we can see it

56:33

now below it we will add that Banner

56:36

image that we copied from GitHub right

56:38

so below this div right here I'm going

56:40

to have another div which will contain

56:43

another div which will contain the image

56:45

and the reason why I'm creating two divs

56:47

over here is because we will be adding

56:49

the logic to this uh image right here so

56:52

if you notice when we scroll down see it

56:54

tilts forward right so so this is the

56:56

logic that we would be needing to add

56:58

and I'll show you how you can add that

56:59

as well right so but first of all inside

57:01

this image I'll say SRC let me see if I

57:05

have imported image from next / image

57:07

yep so SRC will be/ banner. jpeg I'll

57:12

provide it the resolution of 1280 to 720

57:15

and the all tag of dashboard preview oh

57:18

you know instead of that let's just say

57:19

Banner Sensei below it I'm going to have

57:22

the class name of rounded large Shadow

57:25

tob2 XL and some border with margin

57:28

horizontal to be Auto and let's just add

57:32

the priority tag so that it loads first

57:35

right yeah like this all right now that

57:37

we have created the basic structure of

57:39

our app let's just add some stylings

57:41

over here first of all this div which

57:43

contains both of these things we will

57:45

add some gap between them so I'll say

57:47

space y to be six and text to be Center

57:51

and for this particular div I'm going to

57:53

say space y to be six and margin

57:55

horizontal to be Auto let's see yep that

57:58

is what we want now for this particular

57:59

title we will be adding some uh

58:01

gradients and all if you notice just

58:03

like this and we will be using this

58:04

gradient throughout our application so

58:06

we want to create a custom Tailwind

58:08

style for this so what I'll do I'll go

58:10

to global. CSS I'll say add layer

58:14

utilities and inside this let's first

58:16

create a gradient class so I'll say

58:18

gradient inside this I'm going to say

58:20

add apply and I'm going to apply a

58:22

background gradient so I say BG gradient

58:25

which goes from from top to bottom right

58:27

so I'll say gradient to bottom and we

58:30

can assign either two colors or three

58:31

colors so I'm going to say from Gray 400

58:34

via gray 200 to gray 600 if you want you

58:37

can remove this from the middle over

58:39

here as well but I want three different

58:41

colors over here right now similarly we

58:43

can reuse this class over here so I'll

58:46

create a gradient title class over here

58:48

or style over here and I'll use the

58:50

whatevers that we have added over here

58:51

gradient font extra bolt tracking

58:53

tighter text transparent background clip

58:57

to we text you know so that we can show

59:00

this background and clip it inside of

59:01

our text just for our text some padding

59:04

bottom and some padding right right so

59:06

we're just going to take this gradient

59:07

title and provide it to this H1 so I'll

59:10

say class name to be gradient title and

59:13

now you will notice which I don't think

59:15

you can notice because we need to

59:16

provide some uh size over here as well

59:19

so let me just add it so over here

59:21

alongside it I'm going to add text 5xl

59:24

font to be bold in the bigger screen

59:26

text is going to be 6 XL in smaller

59:28

screen it's 5 XL and in the larger

59:31

screens it's going to be 7 XL and in the

59:33

extra large screen it will be 8 XEL so

59:35

right we will we can customize every

59:37

single aspect of our app using Tailwind

59:40

CSS breakpoints right and of course

59:42

gradient title so now if I go back Yep

59:45

this looks good for our paragraph tag

59:47

right here let's come to over here and

59:49

I'm going to say margin horizontal to

59:51

Auto and Max width is going to be 600

59:54

pixels so that we can break it down into

59:55

two lines

59:56

text muted to foreground so that it's a

59:58

little bit lighter and in the larger

60:00

screens I'll say text Excel okay that

60:02

looks much better all right now for both

60:04

of these buttons right here let's

60:06

provide some gap between them so I'll

60:07

say for this D I'll say display Flex

60:09

justify Center and Space X to be four

60:12

like that now for our image over here we

60:15

need to add that logic off so that you

60:17

know this image is tilted and when we

60:18

scroll down it's going to come forward

60:21

and tilt to the normal size so for this

60:24

div I'm going to be providing a custom

60:25

class called hero image wrapper some

60:28

margin top of five in the smaller

60:30

screens and in the medium screens it

60:32

will be margin top of zero yeah we will

60:35

be getting a reference to this div right

60:37

here so that we can provide that logic

60:39

so for that we will be using a use ref

60:43

hook so I'll say use ref and import it

60:46

from react and I'll show you what use

60:48

ref exactly does and we will take image

60:51

ref over here and now you will notice

60:53

this will give us error because we are

60:56

using hooks over here right so it will

60:58

tell us to use this use client directive

61:01

so yep let's just add it on the top I'll

61:03

add use CL and this will continue to

61:05

work just like this okay so now what

61:08

will we do with this image refi we will

61:10

take this and say ref equals image refi

61:13

now through this image refi variable

61:15

right here we will get the access to

61:17

this div's HTML right we can manipulate

61:20

and we can do whatever we want and by

61:21

the way by default we can keep it as

61:24

null over here and also let's give this

61:27

the class name of hero image now what

61:29

will we do we will first of all take the

61:31

use effect hook over here right simple

61:35

use effect hook which will run when our

61:37

component is loaded we need two things

61:39

over here first of all the scroll

61:43

position where we are currently in our

61:45

uh you know window and the scroll

61:47

threshold that is after this has been

61:49

cross we want to tilt it back right tilt

61:52

the image back so first of all to tilt

61:54

the image back we first have to tilt it

61:56

right so we have already added these two

61:58

classes hero image rapper and hero image

62:00

so let's go to our global. CSS and add

62:04

this so over here I'm going to add hero-

62:08

image- wrapper and here I'm going to add

62:12

a perspective class with 1,000 pixels so

62:16

now you will see nothing will happen

62:17

because we have added just perspective

62:20

property over here but we have to rotate

62:21

it now so now I'll say do hero- image

62:26

transform rotate X by 15° and scale is

62:30

going to be 1 now let's see yeah you can

62:33

see now it has been rotated but if we

62:35

were not to add this perspective style

62:38

notice what will happen see it wouldn't

62:40

work right so we have to add this

62:42

perspectives for this transform to work

62:44

and when we transform when we perform

62:46

the transform I want the transition of

62:47

0.5 seconds right so that it eases out

62:51

with the transform and we also need to

62:53

tell Will Change to be transform

62:56

right so this provides a rendering hint

62:57

to the user agent stating what kind of

62:59

changes the author expect to be

63:01

performed on an element right so we just

63:03

adding transform animation that's why we

63:05

have added it over here now when we want

63:07

to put it back to normal we are going to

63:10

trigger another class light over here so

63:13

I'm going to say dot scrolled scrolled

63:16

right so this will simply have this

63:19

transform actually so I'll just

63:21

duplicate it and I'll put it right here

63:24

but instead of 15° it will be 0° scale

63:28

to be 1 and

63:30

Translate Y to be 40 pixels I want to

63:33

shift it a little bit right that's all

63:35

we need to do we just have to add this

63:37

scrolled class now programmatically so

63:40

now in the use effect hook I'm going to

63:42

say this I'll say if scroll position is

63:45

more than the threshold position right

63:47

we have crossed this 100 pixels of

63:49

threshold then first of all I'll get

63:51

reference to this image ref over here so

63:53

I'll say on the top over here

63:56

image element equals image ref do

64:02

current now we have the access to it so

64:04

I'll take this image element I'll say

64:07

image element do class list and I'll add

64:12

the class of scrolled and um yeah we

64:16

need to wrap all of this code inside of

64:18

a function so I'll say handle scroll so

64:20

that we can you know check the scroll

64:23

position so I'll add a app Arrow

64:26

function over here wrap this whole thing

64:27

inside of it and then after this I'll

64:30

say window. add event listener and I'll

64:34

add the scroll event inside of it which

64:36

will trigger the handle scroll so now if

64:40

I check if I scroll down yep you can see

64:42

it comes back to normal amazing and also

64:47

we need to remove the event right when

64:49

the component is unmounted so I'll say

64:52

return window. remove event listener

64:54

scroll handle scroll and even though it

64:56

is working but let's just add the else

64:58

condition over here as well else I'm

64:59

going to say remove the scroll if the

65:01

threshold is not less than that right so

65:04

let's see yep amazing this is working

65:07

flawlessly great so now that we have

65:09

created our hero section let's move

65:11

forward to this feature section over

65:14

here so I'll go back to my page. jsx and

65:17

below this hero section I'm going to

65:19

have another section right here for the

65:22

features so I'll add a d and a h two tag

65:26

which will say powerful features for

65:28

your career growth okay now to render

65:31

all of these features right here we

65:33

would need all of this data right and

65:35

all of this data over here as well so if

65:38

you want you can create your own data or

65:40

what you can do I have added this data

65:42

inside of my GitHub repo so inside of

65:44

this data folder over here you can find

65:46

these four files FAQ features Industries

65:48

and testimonials make sure to download

65:51

all these four files right so let me

65:53

just do that real quick all right I have

65:55

downloaded Ed them and put them inside

65:57

of this data folder right here right

66:01

don't worry about it right now we're

66:02

going to be using one by one so first of

66:04

all we would be needing this features

66:06

and simply what we're doing over here is

66:08

we have the icon title and description

66:10

these three are what we will be

66:12

rendering over here right and we will be

66:13

mapping through this features array so

66:16

I'll go to page. jsx and after this H2

66:19

I'm going to have another div which will

66:22

render my features so features. map and

66:26

we will take each and every feature and

66:29

the index and inside of this we will

66:31

render all of these features inside of a

66:33

shat CN UI card so how do we create a

66:36

card in shat CN UI let's see I'm back in

66:38

this documentation and over here in the

66:41

card Yep this is what we want so let's

66:44

just copy this code right here and I'm

66:47

going to say return and paste it over

66:49

here okay we won't be needing this card

66:52

header so let me just get rid of it and

66:55

import this card card content and card

66:59

footer as well I don't think we will be

67:00

needing it this is all we need first of

67:02

all insert this card content I'm going

67:05

to have a Dev right here which will

67:07

render the feature do icon and I'm also

67:10

going to be having a H3 tag which will

67:14

render the feature do title and then a

67:18

paragraph tag which will render the

67:21

feature. description let's save this and

67:24

see if we can see anything over here

67:27

features is not defined okay we need to

67:29

import it just like this from data

67:32

folder and if you scroll down yep that

67:34

is what we want let's just go on and

67:36

style it first of all for this parent uh

67:39

section right here I'm going to say

67:40

class name to be width full padding

67:42

vertical to be 12 in the bigger screens

67:44

padding vertical is going to be 24 and

67:46

in the larger screens it's going to be

67:48

32 and background is going to be this BG

67:51

background color from shat C and UI

67:53

right so let's see yep we have some gap

67:56

between them and yeah it gives us this

67:58

error each child in a list should have a

68:00

unique key prop so that is what we have

68:02

to add over here in the card I'll say

68:04

key to be index okay now for this div

68:07

right here I'm going to say class name

68:08

to be container margin horizontal to be

68:11

Auto some padding horizontal to be four

68:13

and in the bigger screens it will be PX

68:16

to be six for this H2 I'm going to say

68:18

text to be 3 Exel font is going to be

68:21

bold and tracking tighter so that the

68:23

you know words a little bit closer to

68:24

each other text is going to be Center

68:26

and margin bottom to be 12 so yep that

68:29

is what we can see over here and now for

68:31

this D we will be giving a display grid

68:34

right here right so I'll say class name

68:36

to be display grid in the smaller screen

68:39

The Columns will be one medium screen

68:40

columns will be two and larger screens

68:42

columns will be four we can see all of

68:45

them right so Gap is going to be six

68:46

between them and Max width is going to

68:48

be six XEL and they will be in the

68:51

middle so I'll add margin horizontal to

68:53

be Auto just like this let's just add

68:55

some styling to each and every card so

68:57

for this card right here I'm going to

68:59

say border to be2 when we hover on it

69:02

border is going to be primary color that

69:04

is we can see the you know border around

69:06

them transition color so that when we

69:09

hover on it we can see the colors

69:10

transition and 300 millisecond is going

69:12

to be the duration so if I H on it yep

69:15

just like this now for each and every

69:17

card content over here I'm going to be

69:19

saying padding top to be six some text

69:23

Center display flex and flex to be colum

69:25

so that they are on top to bottom over

69:27

here and items to be Center horizontally

69:30

for this internal div I'm going to be

69:32

saying display Flex Flex to be column

69:34

items to be Center and justify to be

69:36

Center so that you can see everything is

69:38

in the very middle now for each and

69:40

every one of them first of all for the

69:42

H3 tag I'm going to be saying the class

69:45

name is going to be text Excel and font

69:47

bold and margin bottom to two so there's

69:50

some gap between these and I'll make

69:52

this paragraph a little bit muted color

69:54

so I'll say text muted foreground so

69:56

like this now we can clearly see them

69:59

right here all right now after it we

70:01

want this feature right here this

70:04

Statistics feature right so let's build

70:07

that section so over here below this

70:10

section you know what let me just copy

70:12

this section up from over here and paste

70:15

it right here and let me remove these

70:18

features from here let's also get rid of

70:21

this H2 right here instead of back BG

70:24

background I'm going to say PG muted

70:27

oops

70:28

muted to be 50 opacity padding vertical

70:32

to be 32 let's just remove this in the

70:34

larger screens I think this should be

70:36

enough and over here inside this D we

70:38

can add four different stats now when I

70:40

was building this app I had written the

70:42

HTML for it and I forgot to create the

70:44

separate data for it so let me just

70:46

bring this in it would look something

70:47

like this so for each and every D we're

70:49

going to have the stat and the subtitle

70:53

for it right like 50 plus Industries

70:55

covered we're adding display flex and

70:57

flex column so that these are on top to

70:59

bottom item Center and justify Center so

71:01

that they are on the middle and space y

71:03

to be two so that we have some gap

71:05

between them right and simply for 50

71:07

plus we will have text 4XL and font bold

71:09

and this one will be muted and similarly

71:11

we will have three more stats over here

71:14

which again if you want you can create

71:15

your own or you can copy just like I

71:17

have written like 1,000 plus interview

71:19

questions 95% success rate 24/7 AI

71:22

support right so let's see if we scroll

71:25

down yep that is what we want right so

71:27

after this section uh you know what one

71:30

thing but while creating a landing page

71:32

I would say the development is the

71:34

easier part the main thing is to

71:37

understand how you can create the design

71:39

right and what are all the elements that

71:41

you can separate separate elements that

71:43

you can create to build an app like this

71:45

so you can use there there are variety

71:47

of websites available like behance and

71:49

dribble which we can go and take the

71:52

inspiration of design from right just

71:54

don't copy it take take some inspiration

71:56

and add something on your own as well so

71:58

below this section let's just again so

72:00

this is going to be pretty similar to

72:02

this feature section right so I'm going

72:03

to take this section and uh copy it

72:06

right here and on the top instead of

72:09

this we can write how it works and we

72:12

can also add a paragraph tag over here

72:15

which will say four simple steps to

72:17

accelerate your career growth and you

72:19

know what let's just wrap this whole

72:20

thing inside of a d so that this is

72:23

separate from the below section

72:25

and let's remove all of this and I'm

72:27

going to say margin bottom to be four

72:29

and for this div over here I'm going to

72:32

say text to be Center Max width to be

72:34

3XL and some margin horizontal to be

72:37

Auto and margin bottom to be 12 so let's

72:40

see if I go down yep we can see this we

72:43

just need to change this thing right

72:44

here and let's remove everything inside

72:47

of over here in this features. map

72:49

instead of this I'll take the how it

72:52

works and make sure to import it that we

72:54

copied inside this data folder over here

72:56

right how it works. JS I'll take each

72:58

and every item and the index so I'll

73:00

take each div over here and actually

73:03

since there are I think how many items

73:06

are there so there are four I think we

73:08

don't need to change this grid over here

73:10

so inside this div I'm going to Simply

73:12

render my item do icon and let's see how

73:16

it looks if we scroll down okay we need

73:19

to add a key prop as well so key to be

73:22

index and for this div let's just add

73:25

add a class name of width 16 height 16

73:27

rounded to be full background color is

73:29

going to be primary with 10% opacity

73:31

flex and items to be Center justify

73:34

Center and now if you see yep we can see

73:36

it right here but we cannot see the icon

73:38

over here so what did I do wrong it

73:41

should be icon with the capital I no I

73:44

think it should be small I over here

73:46

that's better now if I see yep we can

73:49

see the icons let's get this Dev some

73:52

class name of display Flex Flex to be

73:54

columns items to be Center text to be

73:56

Center and space y to be four so that

73:58

these are in the middle yeah that looks

74:00

good now below this D I'm going to have

74:02

the H3 and the paragraph tag as well

74:04

which will contain item. title and item

74:06

do description which will be a sem font

74:08

semibold and text to be Excel and again

74:10

paragraph is going to be muted just like

74:12

what we've been doing up until this

74:13

point right just like this great after

74:16

this what do we have we have what our

74:18

users say right again this will be very

74:20

similar to what we how we have been

74:23

creating this featured section right so

74:25

I'll just copy this feature section over

74:28

here again and go down after this

74:31

section and I'll paste it right here

74:33

right first of all over here I'm going

74:36

to Simply say what are users say and

74:38

instead of this features I'm going to be

74:40

mapping my testimonial right so I'll say

74:44

testimonial I'll take one single

74:47

testimonial over here for this card

74:49

simply I'll say background is going to

74:52

be this background color that we have

74:54

defined like that shat scene UI has

74:56

defined now inste of this card content

74:58

let me just remove everything and write

74:59

it from scratch but first of all let's

75:01

see if we can see anything over here yep

75:04

what our user say with three cards of

75:06

our testimonial let's just first give

75:08

this card content just the class name of

75:11

padding top to be6 now inside of this

75:13

card component over here I'm going to

75:15

have a d and let's plan how we're going

75:17

to be building this so if you see over

75:20

here we have this Dev first and then we

75:22

have this Dev for containing this uh

75:25

block code right so inside this div I'm

75:28

going to have first div for that one and

75:30

then we will have a block code for our

75:34

code right and then inside this div

75:36

we're going to have two things first the

75:38

image and then the information about the

75:40

user right so I'll have a div for the

75:42

image and then another div for the info

75:45

about the user so first of all for the

75:47

image so I'll add a image tag over here

75:51

import it from next SL image and inside

75:53

of this I'm going to have the SRC of

75:55

testimonial. image width and height of

75:57

40 and all tag of testimonial. author

76:01

let's see if I go back to our app um

76:04

okay so we're using this random user. me

76:07

over here right if you go to the data

76:09

we're using this image with random user.

76:12

me API so we need to add this to next.

76:16

config.js we need to tell nextjs that we

76:19

are using this so insert this I'm going

76:21

to say images and remote pattern I'll

76:24

say protocol https and host name to be

76:26

random user. me so let's see now if I

76:29

refresh this let's scroll down okay we

76:31

cannot see the image yet y now we can

76:34

see great let's add the class name of

76:37

rounded full object cover border tob2

76:40

and like border color to be primary and

76:42

20 opacity so let's see yep like that

76:45

now after this inside of this T over

76:47

here we're going to have three paragraph

76:49

tags first one we'll have testimonial

76:51

author testimonial role and testimonial.

76:54

Company right this will be semi- bold

76:57

this will be text small both of them and

76:59

this will muted and this will be text

77:01

primary color so let's see yep that is

77:03

what we want and for both of these for

77:06

this parent da over here I'm going to

77:08

give the class name of display Flex

77:11

items to be Center and Space X to be

77:15

four let's see now sorry I had to give

77:17

this class name over here not there and

77:21

now let's see yeah that's better for

77:23

this image Dev I'm going to give the

77:25

class name of relative height and width

77:29

to be 12 and flex shrink to be zero so

77:34

yeah it will take the space available to

77:36

it for this parent div right here I'm

77:38

going to give the class name of display

77:39

Flex Flex column because the block quat

77:41

will be in the bottom of it right in

77:44

like below it and space y to be four

77:47

like this okay now you can't see much

77:49

over here right now but for this parent

77:52

Dev of this testimonial do map let's see

77:54

okay okay I've have given grd columns 2

77:57

and over here I think it should be grd

78:00

columns 3 because we just have three

78:02

items over here right so let me just

78:04

remove it and let's add gap of eight

78:06

between them and yeah now we should see

78:08

them in the middle yep something like

78:10

that okay so now let's work on this

78:12

block code so here simply let me just

78:14

bring in the code real quick we will

78:15

just have a paragraph tag which will say

78:18

text muted foreground and it will be

78:20

italic since this is a quote right and

78:23

position relative and insert this we

78:25

will first add this quote Right double

78:28

inverted commas so to write that you can

78:30

write something like this and we will

78:32

just style them text 3 XEL text primary

78:35

and Position will be absolute minus top

78:38

four and minus left to be2 similarly for

78:41

this one as well minus bottom to be four

78:45

and then we'll simply insert our

78:46

testimonial quote between them like

78:49

which looks something like this right so

78:51

yeah let's see yeah that's exactly what

78:54

we wanted in the it as well and let's

78:56

just add some background to this so what

78:59

I'll say background muted to be 50 over

79:03

here okay yeah that looks much better

79:06

now I think the only thing remaining is

79:08

frequently asked questions and this CTA

79:11

at the bottom let's just build it real

79:13

quick this will be very easy just like

79:15

what we've been doing up until now let

79:17

me just copy this section above it this

79:21

how it works section and let me just

79:24

paste it right after it let me just get

79:27

rid of everything inside this map

79:30

because we will be mapping through the

79:32

fa cu's over here this won't be a grid

79:36

so let me just remove everything over

79:38

here in like apart from these two things

79:41

on the top instead of how it works I'm

79:43

going to say frequently asked questions

79:45

and instead of this paragraph I'm going

79:47

to say find answers to most common

79:49

questions about our platform let's see

79:52

okay yeah let's just render the FAQ real

79:55

quick so we have created this fuuse data

79:57

of question and answer over here so

79:59

inside this I'm going to say return and

80:01

I'm going to return a accordion actually

80:05

over here not

80:06

accordion accordion item we will wrap

80:09

this with the accordion so let me show

80:10

you so if I go back to shat CN UI we

80:14

have this accordian component right here

80:17

just like this and to use it this is the

80:19

code I'm going to take it and paste it

80:22

right below it and we will take the

80:25

accordion item and first of all let me

80:27

just wrap this with the accordion and

80:29

over here is what we will be returning

80:31

the accordion item right let's go back

80:34

and see accordion is not defined

80:36

obviously we have not imported it so

80:38

let's import accordion from /ui folder

80:40

accordion trigger accordion content all

80:43

of this has been Tri like imported I

80:46

guess let's see yep but obviously we

80:48

have to provide the key as well right

80:50

and also it takes this value right here

80:52

so I'll say key to be index and value to

80:54

be item and whatever the index of that

80:56

item is right so now we can access every

80:59

single

81:01

separately and instead of this we will

81:03

add the dynamic value that is FAQ do

81:06

question and over here as well FAQ dot

81:10

answer let's make it full width so I'll

81:13

say class name to be width full so page

81:16

crashed let me just reload it FAQ is not

81:19

defined oh sorry FAQ over here not the

81:22

item yep just like this this is exact

81:24

what we wanted the most asked questions

81:26

about our app and then in the end we

81:28

want to have a this beautiful seat here

81:31

right which most of the SAS companies

81:33

nowadays have to make the conversion

81:36

even better so again let me just um

81:39

duplicate this section I'm going to copy

81:41

it and paste it right here you won't be

81:45

needing this accordion now let's get rid

81:47

of this div all together for this H2 I'm

81:50

going to say ready to accelerate your

81:52

career and for this paragraph I'm going

81:54

to say join thousands of professionals

81:57

who are advancing their career with AI

81:59

powered guidance now obviously we will

82:01

be changing these Styles a little bit so

82:03

instead of this section over here I'm

82:04

going to say width to be full instead of

82:07

this div I'm going to be saying margin

82:10

horizontal to be Auto padding vertical

82:12

to be 24 some gradient so if you

82:14

remember we created the gradient

82:15

Tailwind CSS class right so we will be

82:17

using over here for our background color

82:20

and rounded to be large so let's see yep

82:24

something like this we have to enhance a

82:26

little bit more for this div over here

82:29

I'm going to be saying display Flex Flex

82:32

column so that we are aligning them from

82:34

top to bottom items to be Center justify

82:36

Center so that they are in the middle

82:38

space y to be four between them text to

82:40

be Center and maximum width is going to

82:42

be 3 XEL which is around 768 pixel right

82:46

and obviously we want them in the center

82:48

so margin horizontal to be Auto for this

82:51

h2 tag I'm going to be saying in the

82:53

smaller screens three XL some font bold

82:55

and tracking tighter so that texts are

82:57

closer to each other text color to be

83:00

primary foreground in the smaller

83:01

screens it will be text 4 XEL size and

83:04

medium screen 5 XEL so let's see yep

83:07

that is what we wanted let's do the same

83:09

for the paragraph tag as well so margin

83:11

horizontal to be Auto and Max width is

83:14

going to be 600 pixels text primary

83:16

foreground but with 80% opacity and in

83:19

the medium screens text Excel like this

83:22

now in the bottom below this P tag I'm

83:25

going to be Simply Having a link tag

83:27

which will take us to the slash

83:28

dashboard page a button with size large

83:31

variant secondary and class name to be

83:33

height 11 margin top to be five and it

83:35

will bounce right this is a native

83:38

Tailwind class of animate bounce and I'm

83:41

going to Simply say start your journey

83:43

today and I'm going to add a arrow right

83:45

icon which will come from Lucid react so

83:48

link is not defined let's import link

83:50

from next SL link let's see yep there we

83:53

go this is exact ex L what we wanted

83:56

amazing so we have successfully

83:57

completed our landing page Pat your back

84:01

now let's go on and dive into juicy

84:03

stuff that is designing our database

84:05

right designing the tables inside of our

84:07

database using Prisma so first of all

84:09

let's just first go on and install

84:11

Prisma inside of your app and then what

84:14

we will do we will go on and design our

84:16

database so I'll say npm install

84:19

dashd Prisma so let me show you what

84:22

Prisma is all about so if you just

84:24

Google Prisma right here just open it up

84:27

and in the documentation let's see this

84:30

example right here of create right like

84:32

if you were to create something using a

84:34

SQL query it will be super long right

84:37

like insert into this table blah blah

84:39

blah blah it will be a headache but

84:41

Prisma makes it super easy like you can

84:43

see Prisma and let's say if you want to

84:45

insert into user table do user do create

84:48

and simply providing our data right here

84:50

super easy so the Prisma has been

84:52

installed I'm going to say and PX Prisma

84:56

in it and it will initialize our project

85:00

with Prisma over here so you're going to

85:02

notice it has created this Prisma folder

85:04

with schema. Prisma and this is the

85:06

place where we will be creating our

85:07

tables and you can see it has picked up

85:09

this database URL that we have added

85:11

inside of the EnV file and it will use

85:14

it to connect to our post G SQL database

85:17

so this is how our database will look

85:19

like so first of all we have a user

85:21

table where we will be storing all of

85:23

the information of the user now you

85:24

might be thinking we are already using

85:26

clerk for storing uh the user info right

85:28

but we will also be storing a copy of

85:31

that information inside of our database

85:33

along with few more uh things like

85:35

industry bio experience skills Etc right

85:38

so that we can access all of these

85:39

details fast and we can query the other

85:41

tables along with the user table faster

85:44

all right so as you can see we'll be

85:47

storing the ID like obviously this ID

85:49

will be generated but we will be storing

85:51

the clerk user ID over here and the

85:53

email the name the image URL and the

85:57

industry so this industry will be a

85:59

foreign key to this industry table right

86:02

here we'll come back to this apart from

86:04

that we will obviously have a created ad

86:05

and updated ad that we generally do in a

86:07

database table then we will have the bio

86:10

of the user so bio experience and skills

86:12

these are the three questions that we

86:13

will be asking the user when user is on

86:16

the onboarding screen right so we will

86:19

also be asking their um you know

86:20

industry so we will have to uh you know

86:24

categories for this one like the first

86:26

category will be for selecting the uh

86:28

industry like for example Tech Finance

86:30

etc etc and then the sub industry like

86:32

for example in Tech are you in data

86:34

science uh front end development backend

86:36

development Etc right so that is what we

86:39

will be storing over here in this

86:40

industry table and we will be generating

86:44

the industry insights and storing them

86:46

right here and as I already showed you

86:48

in the intro that we will be updating

86:50

this uh particular information every

86:52

single week right so for for example if

86:54

there are two users who are uh you know

86:56

in Tech and they are front end

86:58

developers this information will be

87:00

updated for both of them right along

87:01

with the salary ranges the growth rate

87:03

demand level what are all the top skills

87:06

that they can learn how does the market

87:09

look like in the future right key trends

87:11

what are the recommended skills that

87:12

they should be learning right so this is

87:13

the whole package that is being provided

87:16

to the user in terms of the insights

87:18

when it comes to their industry okay so

87:21

that's that apart from that the user

87:23

table is connected to these three things

87:25

these two like these three AI tools that

87:28

we have inside of our app right first

87:30

one um let's start with the resume right

87:32

so we can build our rum we will store

87:36

the markdown of the rume over here in

87:39

the content if we want we can generate

87:41

an ATS score over here I've just kept

87:43

this uh field over here even though this

87:45

is not the part of our application so

87:47

that if later on we decide to add this

87:49

feature we can add this feature right

87:50

here right but right now it's not our

87:52

priority because we are just generating

87:53

the

87:54

and alongside it we can also provide

87:56

user the feedback on this right so if

87:58

you want you can ignore these two Fields

88:00

over here as well right the major field

88:01

over here is this user ID that this

88:03

belongs to and the content that is what

88:05

is the markdown content inside this

88:07

resume and again the updated at and

88:09

created at now we will also uh like user

88:12

will also be taking the mock interview

88:15

inside of our application so we'll be

88:17

taking like we can configure it we can

88:20

ask them five questions 10 questions Etc

88:22

right so we'll be storing information

88:24

about every single assessment like what

88:26

are all the questions that were involved

88:28

in that particular assignment along with

88:30

the answers what category does it

88:32

belongs to the score of that particular

88:34

quiz if user gave any wrong answers we

88:36

can ask like we can provide them an AI

88:38

generated Improvement tip over here as

88:40

well and of course the user ID as well

88:43

right apart from that when it comes to

88:45

generating a cover letter we will have

88:47

the user ID the content of that cover

88:49

letter that is generated right the job

88:51

description from which this was

88:53

generated

88:54

the name of the company the job so

88:56

basically these three things are the

88:57

ones that we will be using to generate

89:00

our cover letter right so yeah this is

89:02

the basic structure of our database now

89:06

let's go on back to our code and let's

89:09

design all of these database models

89:11

inside of our schema. Prisma file right

89:14

here so to create a model we have to say

89:16

model and the name of that model like

89:18

for example in this case user right so

89:20

what were the things that we discussed

89:22

first of all it was the ID which will be

89:24

generated uh automatically so let's say

89:26

string and if we want we can provide it

89:29

some default value as well which we will

89:31

do it over here so I'll say this is an

89:33

ID you can read the description about it

89:36

right defines a single field ID on the

89:38

model and then I'm going to say add

89:40

default and we can provide the type of

89:42

ID this will be so I'll say uu ID so it

89:45

generates a global unique identifier

89:47

based on The UU ID spec apart from that

89:49

we will also have the clerk user ID as I

89:52

already showed you which will be unique

89:54

we will have the email name the image

89:56

URL of the user and name and image URL

89:59

I'm keeping optional over here then I'm

90:01

going to have the industry which will be

90:03

a string and as I already showed you

90:05

let's see user belong in the tech

90:08

software engine like software

90:09

development industry right so we will

90:12

combine both of them that usable from

90:14

Tech and inside of this we will have the

90:15

software development then after this we

90:18

want to connect this industry to the

90:20

industry table right so we will be

90:22

creating a industry table over over here

90:24

as well so I'll say industry insights

90:28

and obviously we'll come back to this

90:30

later but over here I'm going to say

90:32

industry insights is going to be the

90:35

type of Industry insights

90:38

table and then we will Define the

90:40

relation between this user table and

90:42

Industry table so inside the industry

90:44

table we have a field called industry if

90:46

you remember this thing right here and

90:48

we will be connecting this to the

90:49

industry field inside of the user table

90:52

that is this field right here then after

90:54

that we will obviously have the created

90:55

at and updated at Fields as well okay

90:58

then on the onboarding screen we will

91:00

ask users some questions right so I'm

91:02

going to say profile fields and I'll add

91:04

bio which will be type of string

91:06

experience which will be of type integer

91:08

and the skills which be which will be

91:10

array of skills right or string then

91:13

after that we will also store the users

91:15

resume and the assignments that they

91:17

have uh attempted first of all the

91:20

assessments the resume and the coverlet

91:22

and obviously these three will be uh

91:24

related to the separate table that we

91:26

will be creating so let me just um

91:28

create it real quick over here I'll say

91:31

model assessment let me duplicate it

91:34

twice I'll say model resume and model

91:38

cover letter so each user can have more

91:40

than one cover letter and more than one

91:41

assignment but a user can only have one

91:43

single resume all right so let's check

91:46

this assignments or the assignment table

91:49

right so let me just bring it real quick

91:50

and then I'll explain you what's going

91:52

on over here so obviously in the

91:54

assignments table we will have the ID

91:55

the user ID that this belongs to and

91:57

then we will Define the relation between

91:59

both of the table so since this is a

92:01

foreign key I'm going to say inside of

92:03

this table we have user ID Fields user

92:06

ID which references the ID of this user

92:10

table that is this particular ID of the

92:12

user table which we are storing right

92:13

here then we will obviously store the

92:16

quiz score that we got after attempting

92:18

the quiz the question so this basically

92:20

be a Json so it it will contain the

92:22

question answer the users's answer and

92:25

what is the correct answer right so all

92:26

of these information that we'll be

92:27

storing over here we will have the

92:29

category of that quiz that is if it's a

92:30

technical quiz behavioral quiz Etc what

92:33

is the you know a generated Improvement

92:35

for that particular quiz if any so this

92:37

is optional and obviously created at an

92:39

updated ad and then we are saying that

92:42

Index this table with the user ID so

92:44

that this remains unique then comes

92:46

resume again very similar to what we

92:49

have already seen ID the user ID and we

92:52

are referencing the user table over here

92:55

the content which will contain the

92:56

markdown of the resume we can if you

92:58

want you can skip both of these right as

93:00

I already mentioned I've just kept it so

93:02

that later on if I want to update

93:04

something inside this project I can add

93:05

the atss scoree feature over here as

93:07

well right so you can remove that and

93:09

then we have created it and updated it

93:11

over here as well right when it comes to

93:13

cover letter we will have the ID the

93:16

user ID again referencing that user

93:18

table the content of the markdown

93:20

content of that cover letter the job

93:23

description from which this was created

93:24

company name job title and obviously

93:27

created at and updated at and again we

93:29

are indexing this with the user ID now

93:31

let's see the industry insights this is

93:33

uh you know quite complex first of all

93:35

obviously we will have two things over

93:37

here right the ID of that particular

93:39

table and the industry that the unique

93:42

industry like I already gave you the

93:44

example tech software development right

93:46

then we will have the list of all of the

93:48

users in the industry so we will write

93:51

them just like this then after this we

93:53

will have more things like salary ranges

93:57

which we will get in this particular

93:58

format we will get the role that this

94:01

industry has like for example data

94:02

scientist or backend developer then what

94:04

is the minimum and the maximum salary

94:06

and what is the average salary so let me

94:08

show you something like this so over

94:10

here you can see we have multiple

94:11

different uh information about that

94:13

particular industry right mobile app

94:15

developer devops engineer backend

94:16

developer Etc then we have the growth

94:18

rate demand level and the top skills

94:21

right so again you can see the growth

94:23

rate the demand level and the top skills

94:26

over here right this will be an array so

94:27

I've added string array growth level

94:29

will be in the float format then next we

94:32

will have the current market condition

94:35

right and what are the key trends right

94:37

now so this can be positive neutral or

94:39

negative key trends can be array of

94:42

current industry Trends then we have the

94:44

array of recommended skills and last

94:46

updated and the next update that will be

94:48

happening for this right so which will

94:51

be next weekend so also you can see we

94:54

have a lot of these enums over here

94:57

right that this should only have these

94:58

many values this should only contain

95:01

these many values right I mean either of

95:03

these values so let's create the enim

95:05

for this so for demand level and Market

95:08

Outlook I'm going to say enum demand

95:11

level and I'll say high medium low and

95:14

Market Outlook can be positive neutral

95:16

or negative right so I can just take

95:17

this and provide it right here and same

95:21

for Market Outlook as well over here

95:24

right this is much more better and much

95:25

more robust and yeah I think uh that

95:27

should be it let's just open our

95:29

terminal and I think there's some error

95:31

over here so industry Insight I think

95:34

that should be it not insights and now

95:37

we have to say npx Prisma migrate Dev

95:41

and we have to provide the commit

95:44

message which let's say create models

95:47

and press enter so what this will do it

95:49

will push all of these schemas to our

95:51

database that is our neon database and

95:54

we can see it right there so let's just

95:56

open the neon database there we go this

95:58

is pushed and now if we go back to this

96:00

tables tab inside of our database let's

96:02

just select Sensei and uh let's see yeah

96:06

you can see all of these tables have

96:09

been created successfully amazing so now

96:11

what I want to do first thing first

96:13

let's just store our user inside of our

96:15

database right so to query Prisma inside

96:18

of our app I'll be creating a file over

96:22

here in this lib folder there I'll say

96:24

new file and I'll name it Prisma do JS

96:29

and inside of it I'm going to say

96:32

export const DB equals new prisas Prisma

96:38

client and let's import it from at

96:42

Prisma / client now if we were to use

96:46

this uh new Prisma client to query our

96:48

database every time the nextjs uses hot

96:51

reloading that is it refreshes our app

96:53

it will create a brand new Prisma client

96:55

over here as well so we don't want that

96:57

right so what we want to do we want to

96:59

store it inside of our Global variable

97:01

so I'm going to say if

97:03

process.

97:05

env. nodecore EnV is not equals to

97:09

production right so I'm going to say if

97:12

we are not on production that is we are

97:13

on the development I'm going to say

97:15

Global this. Prisma equals DB and every

97:17

time we export this I'm going to say

97:19

Global this. Prisma if this exists then

97:22

take it else we will take the new Prisma

97:24

client all right let me just add an

97:27

small explanation over here for you guys

97:29

so you can refer it later on cool then

97:31

so now to store our user inside of our

97:33

database I want to run that function

97:35

every single time my app runs right we

97:38

have to check if the user is added

97:40

inside of our database or not so what

97:42

I'll do I'll create a new file over here

97:44

called check user.js I'm going to say

97:48

export const check user equals if sync

97:54

and this will be an arrow function and

97:56

ins start of this now we will first

97:58

check if the user is logged in or not so

98:00

we will take this current user from at

98:03

clerk / nextjs SLS server make sure to

98:05

import it from this only right so we

98:08

will take this and then we will check if

98:09

user is there or not so I'm going to say

98:11

if user is not there then return null

98:14

now we will try to query our database so

98:16

I'll have a try catch block over here

98:18

inste this I'm going to say await DB and

98:22

import that DB that we just now created

98:24

do user so we're going inside the user

98:27

table and then I'm going to say find

98:29

unique we want to find one single

98:31

database which like we want to find one

98:33

single entry which is unique to you know

98:35

particular users ID so we have already

98:38

like we will be storing uh clerk user ID

98:41

right I've already showed you that so

98:42

I'm going to say where the clerk user ID

98:47

is equals to user do ID the user ID that

98:50

we got from this object user object over

98:52

here right and and then we will store it

98:54

inside of the logged in user so

98:58

basically we are checking if the user is

98:59

already stored inside of our database or

99:01

not so if it is if the user is stored

99:04

here inside of our database then we will

99:05

simply return the logged in user and we

99:07

don't have to do anything right but if

99:09

user is not stored inside of our

99:10

database then we do need to store it so

99:12

I'm going to say const name equals user.

99:15

first name space user. last name and

99:18

then to create this inside of our

99:19

database let me just copy this whole

99:21

thing up and paste it right here instead

99:24

of logged in user I'm going to say new

99:26

user and I'll say db. user. create

99:30

instead of this where I'm going to

99:32

provide the data that I'm supposed to

99:33

store so data will be clerk user ID

99:37

which will be user. ID the name of the

99:40

user that we just now created the image

99:43

URL which will be user. image URL and

99:46

the email right so user. email addresses

99:48

user can have more than one email in

99:50

clerk but we will just take the first

99:51

email address and we will store that

99:53

inside of our database and then we will

99:55

simply take this new user and return it

99:57

so return new user over here that's all

100:00

and in the console like in the catch

100:02

block I'm going to say console log and

100:06

log the error do message over here that

100:09

is all we need to do right now we will

100:11

just take this check user we will go to

100:14

our header component and making sure

100:17

this is a server component and let me

100:19

just get rid of this yeah and this

100:21

should be an asynchronous function since

100:23

this is a server component and I'll say

100:25

await check user right here every single

100:29

time we land on our app we will check if

100:32

the user is like part of our database or

100:35

not so import this check user and if

100:37

they are it will simply return it from

100:39

over here else it will create it let's

100:41

go on and check it out so now let's go

100:42

on and sign in continue with Google and

100:45

we are in this should have posted the

100:48

user inside of our database let's see if

100:50

I refresh this uh user table over here

100:52

there we go we we have the user

100:54

information inside of our database along

100:55

with the email name image URL and all of

100:58

these things obviously the industry is

100:59

empty right now and we can also see all

101:02

the tables that our user table is

101:04

connected to over here but we cannot see

101:06

anything since we don't have any data on

101:08

them right now cool then let's go on and

101:12

um you know create our onboarding page

101:13

but before that I want to explain to you

101:16

guys how routing Works in nextjs so as I

101:20

already told you guys for every single

101:22

uh route that we create like for example

101:24

over here in the O we have this layout.

101:26

JS file right so we can have a layout.

101:28

JS file and we can also have a page.js

101:31

file and page. jsx is what makes a route

101:35

possible right so for example for the

101:38

internal routes of our app we will have

101:41

the main folder right so I'm going to

101:43

group them in the main folder and

101:44

obviously this is optional you can do it

101:46

without this main folder as well but

101:48

since we want a consistent layout for

101:51

our application we will be creating a

101:52

layout

101:53

.js file over here which will wrap all

101:56

of the routes inside of our main file

101:59

like or sorry main folder like for

102:00

example I'm going to be creating a new

102:02

folder for on boarding over here and

102:05

inside this we will have a page. jsx

102:09

file let's say r fce on boarding page

102:14

right simple as that and in the layout.

102:16

JS I'll say R fce if I want this on

102:19

boarding to fall under this layout I

102:21

want to create it inside of this Main

102:23

folder right so I'm going to say main

102:26

layout and then I'm going to take the

102:29

children over here that we will be

102:31

rendering so I'll be rendering these

102:34

children right here and then if I want I

102:37

can provide them some Global Styles just

102:39

for this uh routes that fall under this

102:41

main folder right so I'll say class name

102:44

to be a container MX Auto so they are in

102:46

the very middle some margin top to be 24

102:49

so that our header does not overlaps

102:51

them and some margin bottom to be 20 and

102:54

also since all of these are protected

102:56

routes right I'm going to be adding the

102:58

logic over here so that when the user is

103:01

already onboarded we will check if like

103:03

we will land on the onboarding page and

103:04

then we will check if the onboarding

103:06

process already completed then we don't

103:07

need to do it again right so we will

103:10

redirect user after on boarding right we

103:14

will come back to this later on but

103:17

first so what are the different types of

103:19

routes in nextjs let's actually go to

103:21

next js's documentation so I'm going to

103:24

say next js. RG let's go to docs and

103:29

over here we have this project structure

103:31

page over here right okay so let's see

103:33

so since we using App router we are

103:35

inside this app folder right and there's

103:37

something called as Pages router as well

103:39

which is old next Chase right so we

103:41

don't need to worry about that so if we

103:43

come down you can see it is explaining

103:46

all of the different different files

103:47

that we have inside of our folder and

103:49

yeah this is the main thing so we have a

103:51

layout file and the page file we can

103:54

also have files like loading not found

103:57

page right the error page for each and

104:00

every single route we can also have the

104:02

nested routes right like for example if

104:04

you have created a onboarding page like

104:06

if I show you inside of our deployed app

104:08

we have the interview prep right so it

104:11

will be slash interview so this can be a

104:14

page in itself but if you click on start

104:16

new quiz you can notice it goes to/

104:19

interiew SL mock right so this will be a

104:21

nested page so let me just create it I'm

104:23

going to say new folder interview and it

104:27

can also have a new folder mock right so

104:31

this will be a uh page now so I'm going

104:33

to create a new file page. jsx R A fce

104:37

I'm going to say mock interview page and

104:41

they should open that and we can also

104:43

create a page file inside of this

104:45

interview folder so I'll say page do jsx

104:48

and let me just copy this whole thing up

104:50

over here and simply instead of mock

104:53

interview I'll just say interview page

104:55

notice this is a route on its own right

104:57

with the page. jsx and this mock is also

105:00

a separate route right okay apart from

105:03

this we can have Dynamic route segments

105:05

over here as well right so what is a

105:07

dynamic route if I go back to the app

105:09

and let's go to the cover letter so you

105:11

can see we have different different

105:13

cover letters over here right like we

105:15

can have the list of cover letters so we

105:16

I've created this one cover letter so

105:17

this is ai- cover- letter if I click on

105:21

this job like over here in this I button

105:24

it will take me to one single cover

105:25

letter so you can see this is an ID over

105:28

here right so this is going to be

105:30

dynamic every single time so we have to

105:31

create a dynamic route over here as well

105:33

so how do we create a dynamic route

105:35

let's create a route called AI cover

105:39

letter and then inside of it if I want

105:41

to create a dynamic route I have to wrap

105:43

them inside the square brackets and

105:44

let's say ID right so this will be a

105:46

dynamic route I can create a new file

105:48

called page. jsx over here let me just

105:52

add this same name code and I'm just

105:54

going to Simply say cover letter and now

105:57

inside of it we can access that

105:59

particular ID by saying params and let's

106:03

just console log perams do ID over here

106:08

or you know what I'll just display them

106:10

right here I think we need to do a wait

106:12

params do ID and const ID equals this

106:17

and this should be an asynchronous

106:18

component if you want to do this let's

106:20

take the ID and I'll say cover letter

106:22

colon ID right here right so this can be

106:24

a page on its own we can also create

106:26

this AI cover letter page so I'll say

106:28

page. jsx over here r a f c AI cover

106:34

letters page right so this can be a

106:36

separate page on its own let's try it

106:38

out so if I go back and I'll say AI

106:42

cover letter you're going to notice see

106:44

we are on this AI cover letters page and

106:46

if I try to go to some gibberish over

106:48

here and press enter you will see we

106:51

will go to that part cover letter page

106:54

so cover letter and the ID that has been

106:56

entered on this URL right here apart

106:58

from that we have this catch all route

107:01

right which like for example if you were

107:03

to enter like let me show you if I click

107:04

on it see we have SL shop SL A/B SL C

107:08

right we can have multiple different

107:10

routes after it but we don't know how

107:11

many routes are going to be there right

107:13

so that is where we create this catch

107:15

all route so it can catch all of the

107:16

routes after this particular thing like

107:19

after whatever this written before this

107:21

catch all route right so we not going to

107:22

be needing that you've already seen the

107:25

optional catch all route so this thing

107:27

right here that we used in clerk right

107:29

so over here so this is actually

107:31

optional we don't need to provide

107:32

anything over here and it will still

107:35

work fine then we will have these

107:37

grouping conventions that I already

107:39

showed you we created the O folder the

107:41

main folder right for grouping the

107:43

routes but in this case next just

107:45

ignores this and goes inside of it but

107:47

if we create a folder with let's say

107:48

underscore folder right next just we

107:50

completely ignore this folder and

107:52

everything inside of it so the best way

107:55

to use this is by creating a components

107:57

folder right like for example if I let's

107:59

we are going to be working on the

108:02

industry insights right so let's say if

108:05

I create a new folder called

108:06

dashboard we will have a page. jsx file

108:10

over here like RFC I'm going to say

108:13

industry insights page and then if you

108:17

want to use any components over here I'm

108:18

going to create a new folder called

108:20

underscore components and everything

108:22

inside fit along with this folder will

108:24

be ignored and will not be considered as

108:25

a route and then we have more types of

108:28

routes like parallel and intercepted

108:29

routes metap file conventions right so

108:31

we don't need to worry about all of

108:32

these things this is the major things

108:35

that we need to worry about for this

108:37

particular project right let me show you

108:39

how you can create a not found page so

108:41

currently we have a default not found

108:44

page right like if I go to some

108:45

gibberish over here it will show us not

108:48

found yep you can see 404 page cannot be

108:50

found but if you were to create a our

108:52

own not found page so over here inside

108:55

this app folder you can create a new

108:57

file called not- found and it has to be

109:00

exactly called this not found. jsx and

109:04

let like you can create anything over

109:06

here let me just give you a quick

109:07

example this does not really matter so

109:09

I've created this not found page over

109:11

here with simple H1 of 404 H2 of page

109:15

not found and then I've written a

109:16

message over here oops the page you were

109:18

looking for does not exist or has been

109:20

moved and then I have a return home

109:22

button Buton over here which will take

109:23

me to the homepage right simple and I've

109:26

given this gradient title if you

109:28

remember we created this some time ago

109:31

our custom title so if I go back now you

109:33

can see this looks much more beautiful

109:35

right so it's a custom 404 page if you

109:38

don't want to create it that's fine

109:39

nextjs is anyways handling it by our

109:42

default 404 page all right then let's go

109:45

on and start working on our onboarding

109:47

page so if I go to/ onboarding we will

109:50

just see this onboarding page message

109:52

over here so now if I go back over here

109:55

inside of the main folder we have this

109:56

onboarding page. jsx and over here first

110:00

of all we will check if the user is

110:02

already onboarded if they are we will

110:04

redirect them to the dashboard page and

110:06

I showed you we have added this

110:08

condition over here in the layout. JS

110:10

right so over here basically we will say

110:13

redirect to onboarding if user is not

110:15

onboarded then we will redirect them to

110:17

onboarding but if they are already

110:19

onboarded then the onboarding page will

110:20

send them back so we will come back to

110:22

the logic but over here instead of this

110:24

div I'm going to have a main tag and

110:26

inside of this I will be rendering my

110:29

onboarding form so I'll say on boarding

110:31

form so the reason why I've created a

110:34

separate component over here is because

110:36

this is going to be a client component

110:38

and client components need to use that

110:40

use client directive right we cannot use

110:43

hooks inside of This Server component

110:45

and the reason why I'm not creating this

110:48

as a client component is because we will

110:50

be making a API call over here on our

110:53

server which will check if user is

110:55

already onboarded or not and that will

110:57

be much more faster when compared to

110:59

client component right so to this

111:01

onboarding form I will send the data of

111:04

the industries so we have created this

111:06

Industries data right inside this data

111:08

folder yep there we go Industries and

111:11

now you can see this data so basically

111:13

for this data we have the iD Tech name

111:16

technology and the sub Industries inside

111:18

of this and similarly for each and every

111:19

Industries like Finance Healthcare

111:22

manufacturing etc etc we have created

111:25

the industries and sub Industries over

111:28

here as well so that all types of users

111:30

can use our app okay so let's import

111:33

this I'm going to send this as

111:35

industry or you know what industries

111:38

equals Industries and make sure to

111:41

import it from at data/ Industries and

111:44

obviously this onboarding form does not

111:45

exist yet so let's just create this

111:48

component just like I showed you we will

111:50

be creating a new folder UND score

111:53

components and I'll name this file as

111:57

onboarding Das form. jsx R A fce I'll

112:02

say onboarding form over here for this

112:04

particular component and this will take

112:07

the prop of the industries that we are

112:10

sending from right here okay now before

112:14

uh building the UI of our onboarding

112:16

form let's first create the apis for the

112:19

onboarding form right so the back end

112:21

part of these things so where do where

112:24

will we uh you know be writing our apis

112:27

the older way of writing it is in the

112:29

API folder over here but the new nexj I

112:32

think it was from nextjs 13 something

112:35

version that nextjs has introduced

112:37

server actions so we have to create a

112:39

folder over here called actions and

112:41

inside this we will be creating the

112:43

server action this will be like simple

112:46

functions which will be running on our

112:48

server so let me show you so if I create

112:50

a new file over here let's say user doj

112:52

yes since onboarding has more to do with

112:55

user right and I'm going to create a

112:57

function over here export async function

113:00

update

113:02

user right this will be our server

113:05

action and this will take some data

113:07

let's say onboarding data if will come

113:08

from the UI right and also very

113:12

important you have to write use server

113:14

on top of this so that this runs on our

113:17

server and our server components as well

113:19

right so before updating our user we

113:21

need to check if user is logged in or

113:23

not right so I'm going to say await o

113:26

and this Au will be coming from at clerk

113:29

nextjs SL server right if we get the

113:32

user ID then we will check if user ID

113:35

does not exist then obviously the user

113:36

is not logged in and we will throw

113:38

unauthorized then we will check if user

113:40

exists inside of our database or not so

113:42

I'll say const user equals a wait DB

113:46

just like we have done earlier db. user.

113:49

find unique and I'll say where we will

113:52

will'll find them using the clerk user

113:54

ID right so clerk user ID is equals to

113:58

user. ID pretty straightforward just

114:00

like we have done over here sorry not

114:01

user ID this user ID over here not user.

114:04

ID and again if user does not exist

114:07

inside of our database we will throw the

114:09

error over here cool then now that we

114:11

have that out of the way we can make the

114:14

uh you know connection with our database

114:16

over here inside the T TR catch block so

114:19

we have the data right here right what

114:21

will this data contain let see inside of

114:23

our Prisma schema right here so we will

114:26

be sending like let's see our user table

114:29

Yeah we will be sending the bio the

114:31

experience the skill set and obviously

114:34

the details about our industry okay so

114:36

now after this we will be performing two

114:38

operations over here first of all we

114:40

will find if the industry exists right

114:46

if the industry exists then we won't do

114:48

anything but if the industry does not

114:50

exist we will create it with the default

114:52

values for now but later on we will add

114:54

the you know AI logic to generate the

114:56

industry insights right away right and

114:58

the third step will be to update the

115:01

user right so we are performing three

115:02

API calls over here so this can be a

115:04

time-taking process so instead of using

115:06

just normal API calls over here we will

115:09

be using something called as transaction

115:11

that comes from Prisma right so I'll say

115:13

const result equals await DB Dot and

115:19

I'll say dollar sign transaction action

115:23

right so now what is the uh you know use

115:25

of transaction so transaction basically

115:27

makes sure that all of these three

115:30

completes if any of these fails the

115:32

transaction will fail as well and this

115:33

will give us the error right so first of

115:36

all we will take a call back over here

115:39

the asynchronous call back and the

115:41

second thing that we can provide it is

115:43

the timeout value now this is optional

115:45

by default it is 5 seconds but we are

115:48

providing 10 seconds over here because

115:49

later on we will be adding this AI logic

115:52

right so let me just take this first of

115:53

all and add it inside of this call back

115:56

so yeah this is the call back we are

115:58

providing it 10 seconds to Pro you know

116:00

complete this operation to generate all

116:02

of the AI insights regarding that

116:05

industry and then in the end we will

116:07

return the result. user that's all in

116:10

the catch block I'm going to say

116:12

console. error error updating user and

116:14

Industry and we'll provide the error.

116:16

message and we'll throw a new error that

116:18

failed to update profile that's all

116:20

let's dive into this now so to perform a

116:22

transaction we will take a TX over here

116:24

for one single transaction and we will

116:26

have three transactions over here right

116:28

so first for this step I'm going to say

116:30

cons industry insights or let's just say

116:34

let over here because we'll be

116:36

overlapping this value so industry

116:38

insights equals await TX do industry

116:43

insight. find unique we will try to find

116:47

if that particular industry already

116:49

exists right like for example front end

116:50

developer and I'll say where here data.

116:53

industry so we'll be getting this

116:54

industry from this data object that

116:56

we'll be getting over here right so I'll

116:58

check if this already exists and now if

117:01

the industry does not exist we will

117:02

create it with the default value so let

117:04

me show you I'm going to say if the

117:07

industry does not exist the industry

117:09

insights oops sorry I think it should be

117:11

industry Insight does not exist we will

117:14

simply say await tx. industry insight.

117:18

create and we will create all the

117:20

default value that we are supposed to

117:21

have in inside of our database right so

117:23

you've already seen this schema. Prisma

117:25

file over here this industry inside

117:27

right so we are providing all of these

117:29

values as default so you can see the

117:32

industry the salary range the you know

117:34

empty array growth rate zero demand

117:37

level medium top skills Market Outlook

117:39

blah blah blah and this is a temporary

117:41

thing for now right again when we later

117:43

on understand the AI stuff we will be

117:46

adding the AI generated industry

117:49

insights right here cool then after this

117:52

we will update the user so I'll say

117:55

const

117:57

updated user equals await

118:00

tx. user. update we will update the user

118:05

object that is already inside of our

118:06

database right so first of all we will

118:08

try to find that user using the user. ID

118:12

and then we'll provide the values that

118:13

we are getting that is industry

118:15

experience bio and the skills right all

118:18

these four values right here then in the

118:19

end let's return this updated user and

118:22

and this industry insights notice I have

118:24

overlapped this industry insights

118:25

variable over here so after this I'm

118:28

going to say return the updated user and

118:30

the industry Insight that's all that is

118:33

all we needed to do to create this

118:35

update user server action over here okay

118:38

and then after this let's just create

118:40

another server action for fetching the

118:44

onboarding status right so I'll just

118:45

copy it and paste it right here and

118:48

rename it to be get user onboarding

118:50

status we won't be needing any data we

118:53

are just going to be first checking if

118:55

the user is logged in or not so I'll

118:57

just take all of these things that we've

118:59

already written and I'll just paste it

119:01

over here first and then I'll say try

119:04

catch block oops try catch and this will

119:07

be fairly simple right first of all I'll

119:09

fetch the user so I'll say cons user

119:11

equals a wait DB do user do find unique

119:17

and set this I'm going to say where

119:19

clerk user ID is this ID or you can you

119:21

know also um search using this ID equals

119:25

user. ID as well from this our database

119:28

but this will also work and then I'm

119:30

going to say select the industry as well

119:32

because when we get the user object the

119:33

industry object might not be populated

119:35

we just get the ID so we want to

119:38

populate the industry as well and then

119:40

in the end we will simply return is

119:42

onboarded flag and I'll check if the

119:44

user industry exists then obviously this

119:46

will be true else this will be false and

119:48

in the catch block we will simply say

119:51

console. error error checking onboarding

119:53

status and provide the error do message

119:57

and throw new error fail to check

119:58

onboarding status that is all cool then

120:01

this these are the two API that we will

120:04

be using right here right so let's go

120:08

back to our onboarding form and let's

120:10

start building this but you know what

120:11

since we have already created uh this

120:13

get user onboarding status API why not

120:16

we just go on and add it to our page.

120:18

jsx over here right we have this

120:20

condition so I'm going to say cons

120:22

and actually I will say first await get

120:25

user onboarding status let's take it

120:27

from over here at action SL user and

120:31

over here I'm going to say const this

120:33

will provid us is onboarded you can see

120:35

it is suggesting this is onboarded and

120:37

this will be an asynchronous function

120:39

since this is a server component and if

120:41

the user is already onboarded we will

120:43

route them to the dashboard page right

120:46

that's all let me just copy it and go to

120:48

our dashboard page. jsx and I'll add it

120:51

right here as well and let's make it an

120:54

asynchronous component and I'm going to

120:56

say if user is not onboarded then we

121:00

will push it to on boarding page right

121:04

and yeah that should do it let's just

121:06

import this and import the

121:08

redirect and now if we try to go to

121:12

dashboard yeah you can see we are in the

121:15

like let's do this again if we go to

121:16

dashboard we are directed to the

121:18

onboarding form great so now if the user

121:21

is not onboarded we will be redirected

121:22

to the SL dashboard page let's go back

121:25

to this onboarding form over here and

121:26

now we will be creating the form for

121:29

basically onboarding the user so for

121:31

that we will be using two very popular

121:33

libraries react hook form and Zod so I'm

121:35

going to say npm installed react hook

121:39

form space Zord and at hook form SL

121:46

resolvers so this library is for making

121:49

sure that these two work fine with each

121:51

other so I'll press enter there we go it

121:54

has successfully installed and now since

121:55

this is going to be a client component

121:57

I'm going to be adding a use client flag

122:00

over here so inside this onboarding form

122:03

I'm going to say use form and use form

122:06

comes from react hook form over here

122:08

right so this is a hook that we'll be

122:10

using and for creating our form we will

122:12

also be creating the schemas right so

122:15

schemas that will monitor our form if

122:17

the user has entered the correct

122:18

information or not right so to create

122:21

the schemas I'm actually going to be

122:23

creating a new folder over here called

122:26

lib and inside of it I'm going to be

122:28

adding a new file called

122:30

schema. JS and here we'll be creating

122:33

all of our schema right so let's see how

122:34

do we create an schema using Zod and by

122:37

the way if you want to get more

122:38

information about react hook form and

122:40

Zord I've created a completely separate

122:42

video on this topic as well so you can

122:43

check it out from Link in description

122:45

down below so let export const on

122:49

boarding schema equals Z and this will

122:52

be imported from Zod Z doob and this

122:55

will take an object inside of it right

122:58

so first of all the

122:59

industry I'll say industry and Z do

123:02

string it will be a string and if it is

123:05

not a string we will provide the error

123:07

to the user right so I'll say requir

123:09

error and I'll say please select an

123:10

industry similarly for sub industry as

123:13

well if the user has not selected it

123:14

I'll say please select a specialization

123:17

similarly for our bio we'll say this

123:19

will be a string and Max 500 character

123:21

vors and this will be optional then we

123:24

will be adding the you know inputting

123:25

the user experience right so experience

123:28

will be Z do string but we will add some

123:30

conditions over here not conditions

123:32

actually we will transform it so we will

123:34

be inputting the experience in the

123:35

number of years right so it be provided

123:37

to us as a string let's say four or five

123:40

right so we will transform it into the

123:42

integer value before storing it inside

123:45

of our database so we will use this

123:47

transform over here and parse int

123:48

function then after this we will add

123:50

this conditions over here that means

123:51

minimum it can be zero or 50 years of

123:54

experience Max then we are going to be

123:56

having skills from the users right so z.

123:59

string and user will be inputting this

124:02

in form of the comma separated values

124:04

right so I'll Transform this into an

124:06

array over here so I'll say value do

124:09

split split it with the comma and I'll

124:11

map through each and every one of these

124:13

trim any space around them and I'll say

124:15

filter out if there's any you know empty

124:17

spaces over there so we will have the

124:19

array of strings over here cool then so

124:22

we will just simply take this onboarding

124:23

schema go back and inside of this use

124:26

form over here we will have an object

124:28

and we will say resolver and inside this

124:31

we will import the Zod resolver so this

124:34

Zod resolver will come from the you know

124:38

this library that we installed the hook

124:39

form resolvers so make sure to import it

124:43

right here Zod resolver from Hook for/

124:45

resolvers SL Zod right and this will

124:48

take our onboarding schema which will

124:52

come from that schema file that we just

124:54

created right here all right so now this

124:57

use form will return us a few things

125:00

right first of all register and this

125:01

will be very important to connect our

125:04

form with the logic right I'll show you

125:06

in just a moment it will provide us the

125:08

handle submit for submitting our form

125:10

the form state which will contain things

125:13

like errors or is dirty is loading is

125:15

submitted Etc right before now we will

125:17

just take the errors then we will take

125:19

the set value and watch to watch any

125:23

particular field if it changes right

125:25

like if we are going to be selecting the

125:27

industry only after that we are going to

125:29

be displaying the select box for our

125:32

specializations right okay uh apart from

125:35

this we are also going to be having a

125:36

use state so use State hook which will

125:40

be storing our

125:42

selected industry and this will be null

125:45

by default we will also be having a hook

125:48

called use router which will be coming

125:51

from next / navigation make sure to

125:53

import it from this only and this will

125:54

help us to navigate to some other page

125:56

so I'll say router equals use router

126:00

that's all let's go on and create our UI

126:02

over here so I'll WRA this whole form

126:04

inside of a card right so card comes

126:07

from uh Shad CN UI so let's go back to

126:10

the docs over here and card right here

126:13

so I'll just take this card code from

126:16

here and paste it over here let's import

126:19

the card card header card title card

126:23

description we'll need the card count uh

126:26

like content and we won't be needing the

126:28

card footer so let me just remove it

126:30

let's see if it's working fine yep we

126:33

can see it all over here for this parent

126:35

D let me just provide some class names

126:36

so display Flex items are going to be in

126:39

a center and justify Center as well so

126:40

that we have the onboarding form in the

126:42

center of the screen background will be

126:44

of this background color defined by Shad

126:46

CI so let's see yep like that for the

126:49

card component over here I'll say class

126:51

name width to be full and Max width is

126:53

going to be large which is around 512

126:56

pixels margin top is going to be 10 and

126:59

margin horizontal is going to be two

127:01

like this for the card title I'll say

127:04

complete your profile and card

127:06

description I'm going to say select your

127:07

industry to get personalized career

127:09

insights and recommendations let's just

127:11

provide the gradient title to this card

127:13

title so I'll say class name to be

127:16

gradient

127:18

title and text to be 4 Excel okay let's

127:23

see yep that's more like it now inside

127:25

the card content is where we will be

127:27

creating our form let's remove this and

127:30

I'll have a form tag over here inside

127:33

this form tag first of all we will have

127:35

the industry and then the uh you know

127:37

specialization select box so we're going

127:40

to be using a select tag so let's go

127:42

back to Shad CN UI and let's use this

127:45

select Yep this is the select one let's

127:47

see the code for this this is going to

127:50

be the code so just copy it and paste it

127:54

right here let me just import all of

127:56

these from at component /ui select

127:58

trigger select value select content and

128:03

select item let's see how this looks

128:06

okay yeah something like that let's wrap

128:07

this select inside of a div and we will

128:10

also be having a label right here so

128:13

I'll just say label from shat cnii

128:16

inside this I'll say industry label will

128:19

have HTML for the industry that is this

128:24

particular select tag let's map all of

128:26

the industries so we are getting this

128:27

Industries over here right Industries

128:29

array so let me get rid of two of these

128:32

and over here I'm going to say

128:33

industries. map and let's have a call

128:37

back over here and I'll move this inside

128:38

of it return let's take one single

128:42

industry and right here I'll say

128:45

industry. name and in the value

128:49

industry. ID and and the key will be

128:53

industry. ID as well let's see label is

128:56

not defined okay let's import the label

128:59

oops not from over here make sure to

129:01

import it from slash

129:02

components so let's see okay yeah that

129:05

looks good why is this theme over here

129:07

instead of this let's keep selecting

129:10

industry and the in the trigger I'm

129:12

going to say ID equals

129:15

industry for this HTML 4 right so let's

129:19

see yep that's more like it if I select

129:21

anything I'm able to select it great for

129:24

this de let's have class name of space y

129:26

to two so that we have some spacing

129:28

between both of these oops not here

129:30

actually I want to keep it on the D yep

129:33

something like this now on our select

129:36

tag I'll say on value change I'm going

129:39

to say set value and we'll change the

129:41

value of this industry right so we have

129:43

taken this set value from over here if

129:45

you remember right so I'm saying set

129:47

value and take the current value that is

129:49

selected and provide it inside of our

129:50

form and and then we will have this

129:52

selected industry updated right so I'll

129:56

update the set selected Industries and

129:57

I'll find the particular industry and

129:59

provide it inside of it so that we can

130:01

you know display the other the

130:03

specialization select box over here and

130:05

I'll say set value to be sub industry to

130:07

be empty right so we will now display

130:09

the sub industry form but before that if

130:11

user has you know not selected the

130:13

industry and just press on the submit

130:16

form button then I'm going to display

130:18

the error so we have taken this error

130:19

from over here right so I'll say error

130:21

do industry if it exists I'll display a

130:25

paragraph tag with text small and texted

130:27

500 and display the errors. industry.

130:31

message over here all right pretty cool

130:34

let's just take this D and I'm going to

130:36

duplicate it right below it to display

130:39

our sub Industries but first uh okay I

130:42

have some uh mistake over here let's

130:45

just fix it okay this will be labeled

130:47

for sub

130:49

industry ID sub industry here the value

130:52

change will be pretty simple on value

130:54

change will just be set value to set the

130:56

sub Industries value and set this

130:58

Industries I'm going to say sub industry

131:00

do SUB industry so sub industry is our

131:03

state if you remember value can be um so

131:06

we don't need to add the ID over here

131:09

this will just be a simple name right so

131:12

we can just put indd on all of these

131:15

three places so let's see let's select

131:17

anything let's select technology and

131:19

yeah now we're able to see it but we

131:20

should not be able to see it right away

131:22

so what I'll do first of all instead of

131:24

this industry I'll say specialization

131:26

and I'll put it inside of a curly braces

131:30

and also over here instead of Industry

131:33

it should be sub industry right now

131:35

we'll watch this field if it's selected

131:37

or not and then add the condition there

131:39

so before return I'm going to say const

131:42

watch industry equals watch this

131:44

industry field over here if it's

131:46

selected only then we will show it so

131:48

I'll say watch industry and over here

131:50

right so let's see if I just refresh my

131:53

page now we can just see this if I

131:55

select technology only then we are able

131:56

to select the specialization let's

131:59

provide some gap between these so in the

132:01

form I'm going to say class name to be

132:03

space Y and I'll also say on submit I'll

132:08

call the handle submit function that is

132:10

provided to us by that use form hook and

132:13

this actually takes another call back

132:16

over here so let me just create a dummy

132:18

on submit so const on submit like this

132:23

let's keep it asynchronous and this will

132:25

provide us the values so let me just

132:27

take it and just provide it for now we

132:29

don't need to worry about it for now

132:31

right so okay so we have this select

132:34

Industries and specialization done now

132:36

we need to ask user how many years of

132:38

experience do they have so I'll just

132:40

copy this div and right below it let's

132:45

get rid of this select tag and over here

132:47

this will be for the experience right so

132:49

I'll say years of experience over here

132:52

and after this I'll have the input tag

132:54

so input which will be coming from SL

132:57

components that is shad CN UI I'll say

133:00

ID equals experience type is going to be

133:03

number it can be minimum zero maximum 50

133:06

and placeholder can be enter years of

133:08

experience right and now if you remember

133:10

we have taken this register from our use

133:15

form hook right so we'll be using this

133:17

now over here so I'm going to say in the

133:21

curly Braes dot dot dot register and

133:23

then provide where like which field does

133:25

this belong to so if you press double

133:27

codes over here I'll say experience

133:30

experience yep something like this let's

133:33

take this experience and replace it over

133:35

here in the errors as well cool

133:36

similarly we will do the same thing for

133:39

our skills so I'll just copy this do and

133:42

paste it right here I'll replace with

133:44

the skills over here I'll say skills as

133:46

well with the capital S over here I'll

133:49

just have two things the ID skills and

133:51

placeholder can you know denote some

133:52

skills like python JavaScript Etc and

133:55

over here as well I'll say skills here

133:57

as well instead of experience I'll say

133:59

skills right and let's just give users

134:01

some message below it that they should

134:03

only enter it in comma separated values

134:06

right so I'll say separated multiple

134:08

skills sorry separate multiple skills

134:11

with commas and this will be a small

134:12

text with muted foreground so let's see

134:15

yep something like this let's copy this

134:17

up and again paste it right here now we

134:20

will add the professional bio field so

134:23

I'll say bio this ID as well bio

134:26

placeholder can be tell us about your

134:29

professional background let's have a

134:31

height of 32 so this will not be the

134:33

input actually this will be text area

134:36

from uh shat CN so import that instead

134:38

of skills I'll say bio over here let's

134:41

get rid of this paragraph tag instead of

134:44

skills again I'll say bio over here then

134:46

I think that is all we needed to do

134:48

let's see our form yep that looks more

134:52

like it let's add the submit button on

134:54

the bottom so I'm going to say button

134:56

which will be imported from Chad CI type

135:00

submit and class name will be width full

135:03

and I'll say complete profile right so

135:05

let's see yep that's more like it and

135:09

now let's try to submit our form right

135:11

so let's see over here in the onsubmit

135:15

let me just console log this simply for

135:17

now so I'll say values let's see if I go

135:21

to inspect in the console let's try to

135:23

select the industry sub industry can be

135:25

software development years of experience

135:27

let's say four skills let's say

135:29

JavaScript react etc etc professional

135:32

bio can be anything right let's click on

135:33

complete profile and yep there we go we

135:36

are getting this object right here let's

135:38

not provide the years of experience and

135:40

you can see we are saying expected

135:42

number received n if I click on complete

135:45

profile it won't allow us to complete

135:46

our profile now if I just refresh it and

135:49

just click on complete profile you can

135:51

see we are getting these errors over

135:52

here if I just select this we are

135:54

getting the error please select our

135:55

specialization right so this is made

135:57

possible by using Zod so now we are

136:00

getting all of these values over here

136:03

right in this values object how do we

136:05

make the API call to our back end so we

136:08

have to call this update user API right

136:11

this is not a server component so we

136:13

cannot just use the await and call it

136:15

directly to use it inside of our client

136:18

component we have to use a traditional

136:20

way of you know using using something

136:21

like fetch right fetch or axio or

136:24

something like that and to manage that

136:26

we would have to manage some separate

136:27

states like loading error and maintain

136:30

data State etc etc right we have to use

136:33

that again and again so what if we

136:35

created a custom hook that will manage

136:38

all of this for us so what you can do

136:41

you can create a hooks folder over here

136:44

ins start this I'm going to create a new

136:45

file called use fetch. JS right so this

136:50

is the custom hook that we will be

136:51

creating JS or jsx whatever you want to

136:54

call it and if you don't know about what

136:56

you know hooks are these are basically

136:58

just like a normal functions but with

137:00

super power of react right and they are

137:02

written by using use keyword in the

137:05

beginning so let's say for this one I'll

137:07

say const use fetch equals whatever this

137:11

is right this is basically a normal

137:14

function and I'm going to take a call

137:15

back inside of it which is going to be

137:17

basically a API call in this case our

137:19

create project call

137:21

so what will this contain it will

137:23

contain the three states that I just

137:25

discussed data loading and error right

137:29

all of these three states which we

137:31

create again and again when we have to

137:33

do an API call let's create a FN

137:36

function over here and this is going to

137:38

be an asynchronous function which is the

137:41

only thing that we would be needing to

137:43

call in the end when we have to trigger

137:44

an API call and we will write all of our

137:46

logic inside of it which we're going to

137:48

reuse again and again right right and in

137:51

the end I'm going to return data loading

137:55

error and this function right here and

137:57

also if you want to you know manipulate

137:59

this data from outside I'm just going to

138:01

send this set data as well and I'll say

138:04

export default use fetch what's going on

138:08

over here uh let me just import use

138:11

State just like this okay now insert

138:13

this function over here first of all

138:16

before fetching our API we're going to

138:18

say set loading to true and set error

138:20

Tel right oops sorry it is export

138:24

default not export delete yeah so set

138:27

loading and set error by default values

138:29

this will be true and this will be null

138:31

then inside of this I'm going to have a

138:33

TR catch block for handling our errors

138:36

and all inside the tri block I'm going

138:37

to say const response equals a wait call

138:41

back whatever this call back is and

138:43

let's if you want to provide it with

138:45

some extra arguments I'm going to take

138:47

this args from over here and provide it

138:51

inside of this ARX then I'll say set

138:54

data to whatever the response that we

138:56

get from it so I'll say response and set

138:59

error to be null but what if we do get

139:02

any error over here then I'll say set

139:05

error to be error now after this set

139:07

error I'm going to be displaying a toast

139:09

as well to the user right and how do we

139:11

do that so I'll go to shat CI docs and

139:14

we have something called a serer that we

139:15

installed so if I click on show toast

139:17

you can see we are able to show these

139:18

toast so this is exactly what we will be

139:20

using

139:21

so to configure it we have to first you

139:23

know add this toaster to the code so

139:26

inside of our app in the layout. JS

139:29

right below main I'm going to add this

139:32

toaster import it from sonor and this

139:35

also takes Rich color I believe yeah

139:37

Rich colors which will display different

139:39

different colors for different different

139:40

types of toasts right warning success

139:43

etc etc and now simply over here I'll

139:45

say toast import it from sonor do error

139:49

and I'll say error. message and then in

139:53

the end finally I'm going to say set

139:54

loading to false that's all now let's

139:56

take this use fetch hook and go back to

139:59

our onboarding form and let's right

140:01

before it I'm going to say use fetch

140:05

oops use Fetch and import it and this

140:09

will take our server action that is

140:12

update user and we'll provide us a

140:15

couple of things like three things right

140:17

data function loading and error so error

140:21

we won't be needing I'll just say

140:23

loading and rename it to update loading

140:25

function rename it to update user

140:27

function data update it to update result

140:29

right these three things are the ones

140:31

that we are going to be needing and

140:32

let's call this update user function

140:34

inside of our onsubmit function over

140:35

here so simply I'll have a try catch

140:39

block over here first of all we will get

140:41

two things inside of uh like we will get

140:43

multiple things out of this values right

140:46

so if I show you see we are getting the

140:49

industry and sub indust industry so what

140:51

I'll do I'll combine them to form the ID

140:54

so what I'll say const formatted

140:56

industry is equals to value. industry-

140:59

value. sub industry and I'll take the

141:01

sub-industry convert it into the

141:02

lowercase and replace it replace the

141:05

space with the dash so it would look

141:07

something like this so Tech Das

141:11

software-development something like this

141:13

let's remove this and then after that

141:14

I'm going to call that function so I'll

141:16

say await whatever the values that we

141:18

are providing and the industry key with

141:20

this formatted industry variable and in

141:23

the catch I'll throw the error of

141:25

onboarding error this error we actually

141:27

don't need to handle catch over here

141:29

since we're already doing it inside of

141:31

use fetch but again it depends on you

141:34

right so cool then that's that after we

141:36

have submitted the form I'll run a use

141:39

effect hook so use effect which will run

141:43

when the component is loaded but will

141:45

run when something inside this

141:47

dependency array changes so I'll put the

141:49

update

141:51

result and update loading these two

141:53

things inside of it so that it will only

141:55

run when these two things change right

141:56

so first of all I'll say if update

141:59

result do success is true or update

142:02

loading is false right that is it has

142:05

fetched and we are no longer loading

142:08

right then what will we do first of all

142:10

we will show profile updated

142:11

successfully and let's import this toast

142:13

from soner then we will use this router

142:16

over here and I'll say router. push it

142:20

to dashboard and router. refresh right

142:22

we will refresh the page and yeah I

142:25

think uh that this should do it let's

142:26

just try it out I'll come back to this

142:29

and let's say industry technology

142:31

specialization software development

142:33

years of experience 4 let's select the

142:37

Industries or let's enter the skills

142:40

over here professional bio I am the best

142:44

complete profile and oh we have to add

142:47

the that loading indicator over here as

142:49

well right and anyway this failed right

142:52

here good thing now let's just add the

142:54

loading indicator to our button so this

142:57

button in the bottom whenever this is

142:59

loading I'll first of all disable it

143:01

right so I'll say disabled update

143:02

loading and over here instead this

143:04

complete profile I'm going to say update

143:06

loading is true show this loader right

143:08

here imported from Lucid react and I'll

143:10

spin this loader and show Saving else

143:13

I'll say complete profile okay let's see

143:16

what the error was go to terminal by the

143:18

way server components will display their

143:20

errors in this over here and the client

143:23

components will display in the inspect

143:25

so of course this is a client component

143:27

so let's just go to our use form hook

143:32

use fetch hook and uh so we are

143:35

displaying error. message over here I

143:38

think we are not properly handling the

143:39

errors so in the actions user.js in the

143:43

update user I'll say fail to update user

143:47

profile and I'll also add this error do

143:50

message message plus error do message

143:52

let's see now it should give us the

143:53

exact reason of failure so if I click on

143:55

complete profile okay uh what is it

143:58

invalid value of argument demand level

144:01

expected so are we not sending the

144:03

demand level let's see over here demand

144:06

level is being provided it is medium

144:08

over here instead of I think it should

144:11

be Capital medium instead of small

144:14

medium and it should be neutral

144:17

something like this probably with

144:19

respect to our enum also one thing I uh

144:21

made a mistake over here I realized so

144:24

we're returning result. user it should

144:26

not be this we should be returning

144:28

success to be true and apart from that

144:32

whatever the result is right so now

144:35

let's see let's select the industry

144:37

technology specialization software

144:39

development let me just open that uh

144:41

Network tab over here as well years of

144:43

experience for skills to be these

144:47

professional bio and yeah let's just

144:50

click on complete profile let's see if

144:52

it works okay profile completed

144:54

successfully and now we are routed to/

144:56

dashboard page amazing let's go back to

144:58

our database and refresh on this

145:00

industry insights table yep we can see

145:03

the industry insights have been added

145:05

those default values have been added for

145:06

now in the user we can see in the

145:10

industry we have this tech software

145:12

developer and this is connected to the

145:13

user table we can see in the end right

145:15

over here amazing so we have

145:18

successfully created our onboard cing

145:20

flow awesome let's go on and generate

145:23

all of these industries insights using

145:26

Ai and we will be displaying them right

145:28

here just like this right cool then

145:33

let's go first of all we would be

145:34

needing the Gemini API key so just

145:38

Google Gemini API key and select this

145:42

first link and you will land on this

145:43

page let's click on get a Gemini key in

145:46

Gemini studio so yep so click on this

145:48

create API key and over here just select

145:51

this Gemini API and click on create API

145:53

key in existing project and by the way

145:55

this is free to use so you can see over

145:58

here I've been proved my API key I'll

145:59

just click on copy over here and I'll go

146:01

back to my project in this EnV file and

146:06

I will add Gemini uncore API uncore key

146:12

right over here great let's close this

146:15

en EnV now and don't worry about the

146:17

pricing and stuff because they have a

146:19

very generous free plan as well if you

146:20

want to see I think you go to ai.

146:23

gooogle dodev SL prising and you can

146:25

find the pricing for all of these models

146:27

over here we will be using Gemini 1.5

146:29

flash so this has 1 million token per

146:33

minute limit over here let's go on and

146:35

create our API first over here so I'm

146:37

going to create a new file called

146:39

dashboard. JS to create our user

146:42

insights API over here to generate the

146:45

AI insights so let's first of all create

146:47

the server action to get the industry

146:49

insights from our database right so I'll

146:52

say use server just like we did earlier

146:56

since we're making a server action and

146:58

I'm going to say export async function

147:00

get industry insights all right similar

147:02

to before we will first check if the

147:04

user is logged in or not so simply I'm

147:07

going to copy this thing and paste it

147:10

right here let's import o from clerk sl/

147:15

server and also DB as well now after it

147:19

I'm going to check if the industry

147:21

insights exists inside of this or not so

147:24

basically this thing right here what we

147:26

have done over here right let me just

147:29

copy it up and paste it right here oops

147:32

I'll paste it right here but this will

147:34

not be as easy as this right so I'm

147:36

going to remove everything inside of

147:38

this and I'll say if user. industry

147:41

Insight does not exist now we are going

147:44

to be generating them using AI right so

147:48

let's just create a function on top of

147:50

it export cons generate AI insights

147:56

equals and this will be an

147:59

asynchronous arrow function this will

148:01

take the industry as an input and this

148:04

will generate the AI insights for it so

148:06

I'm going to take this and I'll come

148:08

back over here I'll say const insights

148:11

and we will say await generate AI

148:14

insights and we will provide user.

148:17

industry over here for which we are

148:20

supposed to generate the AI insights and

148:22

after that simply what we have done

148:24

earlier over here we have done this

148:26

industry insight. create right so that

148:29

is what we will do over here going to

148:30

say const

148:32

industry Insight equals a weit DB do

148:38

industry insight. create and here we

148:41

will provide it with the data which we

148:44

will be receiving from right here right

148:46

so first of all I'm going to say

148:47

whatever the users's industry is so I'll

148:49

say industry is equals to user industry

148:51

I'll take this insights and I'll spread

148:55

these over here and then I'll tell the

148:57

user when the next update is going to be

148:59

happening over here right so I'll say

149:01

next update equals new date date do now

149:06

and I'll add one week time to it right

149:08

so after one week we will be having a

149:10

next update for this thing cool then

149:13

after this we will simply return the

149:16

industry Insight but if let's say we

149:18

already had the industry insight over

149:20

here then we don't need to do anything

149:21

we will return the user. industry

149:24

Insight over here also we will be

149:26

getting this generate AI Insight right

149:28

so this is exactly what we will be using

149:30

over here as well we will replace this

149:32

code with this code right here very soon

149:35

so inside of it let's see how do we make

149:37

a generative Ai call right first of all

149:40

we need to install a package to use

149:42

Gemini API right so I'll say npm install

149:46

at Google SL generative d a and press

149:49

enter there we go it has installed now

149:51

on the top I'm going to say new Google

149:54

generative Ai and make sure to import it

149:56

from at Google / generative Ai and this

149:58

will take our API key so I'll say

150:01

process. env.

150:04

Gemini

150:06

apore key I'll say cons gen AI equals

150:10

this okay now that we have this instance

150:13

of this generative AI class I'm going to

150:16

say const model I'll Define what model

150:19

I'm going to be using over here so I'll

150:20

say gen. getet generative model and

150:24

insert this this will take an object

150:27

I'll say model and we can choose the

150:29

model that we're supposed to use over

150:31

here so I'm going to say Gemini D 1.5

150:34

Das flash so I'll be using Gemini 1.5

150:37

flash cool then we will take this model

150:40

object over here and we will go inside

150:43

of this function and we will prompt it

150:46

right so first of all let me just write

150:48

my prompt over here real quick just like

150:50

this and I know it's way too big so if

150:52

you want you can go on and you can copy

150:54

it up from my GitHub repo you can simply

150:57

go to this dashboard. JS and I've

150:58

written the complete prompt right here

151:00

right so what what is this prompt all

151:02

about so I'm saying that analyze the

151:03

current state of this industry that we

151:06

have over here and provide insights in

151:08

only the following Json format right

151:11

this is the Json format that we want

151:13

without any additional notes or

151:14

explanation so for the salary Rangers

151:16

I've already showed you right what are

151:18

all the types of these things is so so

151:20

I've just provided over here this for

151:21

this one enum of high medium low

151:24

positive negative etc etc right and in

151:26

the end we have again mention return

151:28

only the Json no additional text notes

151:30

or markdown formatting we're supposed to

151:32

include at least five roles for the

151:34

salary ranges and the growth rate has to

151:37

be in the percentage include at least

151:39

five skills and train awesome now how do

151:42

we make use of this prompt so after this

151:45

I'm going to say const result equals a

151:48

wait mod model dot generate content

151:53

right this will allow us to prompt the

151:54

model so I'll say prompt I'll provide

151:57

the prompt over here and this will

151:59

return us some response so I'll say

152:01

response

152:03

equals result do response okay now that

152:08

we have the response we need to fetch

152:10

the text from inside of it so let me

152:11

show you how the response will be so

152:13

there we go I've opened the

152:14

documentation for the Gemini and here we

152:17

go in the response body this is how you

152:19

will get the response after the code

152:21

that we have written and if we just want

152:23

the text like for example over here you

152:24

can see we have the text string over

152:26

here right if we want this we have to do

152:29

something like this so over here if I go

152:31

to the top see they've mentioned

152:33

response. text this function is what we

152:36

will have to use right so if I go back

152:38

I'm going to say

152:40

response. text and I'll call this

152:43

function right here and this should give

152:45

us the text response provided by this uh

152:48

API now this is actually a little bit

152:53

weird so it provides us a response in

152:56

the following format like for example in

152:57

starting it will add something like this

153:00

right and in the end as well it will add

153:01

something on the Json so we need to

153:03

clean this response right so what I'll

153:05

do I'll say const cleaned text equals

153:08

text. replace we'll take this text and

153:11

replace it whatever this these things

153:13

are over here and the Json and

153:14

everything that is additional things

153:16

that are written over here I will remove

153:17

all of them with nothing right and just

153:20

keep the normal response normal text

153:22

response over here and I'll trim it if

153:24

there's any spaces around it as well

153:26

right that's all so then we should get

153:28

some object like this now all we have to

153:31

do is to parse it and convert it back to

153:33

an object you know right now it's a

153:35

string so I'll just say return json.

153:37

pars and clean text there we go and I

153:41

believe that that is all we need to do

153:42

over here and this function should now

153:45

work this get industry insights function

153:47

should now work all right so what do

153:50

I'll go back to this dashboard page. jsx

153:52

and actually first we need to create a

153:54

layout file over here as well to show

153:56

the loading indicator and stuff so I'll

153:57

say layout. JS so I'm going to say r a

154:00

fce layout let's take the children oops

154:05

children over here and I'll render them

154:08

right here okay but before them I'm

154:11

going to have a div over here which will

154:14

render a H1 tag which will simply say

154:17

industry insights let's give it some

154:20

horizontal padding and this D the class

154:22

name of display Flex items to be Center

154:24

justify Center and margin bottom to be

154:26

two so this is on the very middle of the

154:28

screen right and for this H1 tag I'm

154:31

going to say text to be 6xl font bold

154:34

and gradient title so that is is

154:35

displayed in our gradient format right

154:39

and regarding this children over here

154:41

right we will be making an API call

154:43

inside of page. jsx so that will be fet

154:46

that will be fetched on our server right

154:48

so we have to something called as

154:50

suspense that is until that is fetched

154:54

we want to show some loading indicator

154:55

right we will put the children inside of

154:57

it let's import suspense from react and

154:59

I'm going to say fall back and over here

155:03

we can show some fall back UI which can

155:04

probably be a loader right so let's

155:07

import a like let's install a library

155:10

over here npm install react Das Spinners

155:14

right so this will install a bar loader

155:17

as well which I want to use over here

155:19

like let me show you Yep this this thing

155:21

is what I want we have more types of

155:23

loaders over here if you want you can

155:24

use some other loader that's fine let's

155:26

close this and if I go back it's

155:29

installed and over here I'm going to say

155:31

bar loader let's import it from react

155:35

Spinners and I'm going to give it some

155:36

props like class name to be margin top

155:39

of four width to be 100% and color is

155:41

going to be gray cool then okay so the

155:44

default export is not a react component

155:46

in dashboard / page let's see what's

155:48

wrong so print page. jsx it is a react

155:51

component what's going on let me refresh

155:53

this there we go it's working we can see

155:55

the industry insights heading over here

155:58

great also I forgot to do one thing if

156:01

we go back to this user.js I mentioned

156:04

that we will be replacing this uh with

156:06

the AI generation later on right so I'll

156:08

just uh remove this for now and what

156:11

I'll do I'll go back to my dashboard. J

156:13

so we're doing this over here right so

156:15

let me just copy it and paste it right

156:17

here and instead of const I'll just

156:19

remove the con from here and yeah that

156:21

is all we need to do and this will fetch

156:23

our AI insights let's just import it and

156:27

now what I'll do let's go back and

156:30

delete the industry insights the empty

156:32

uh industry insights that we kept over

156:34

here right so let me just go on and

156:36

delete one record and now go back to our

156:38

app refresh it this should take us to

156:41

our onboarding page yep like this so now

156:44

let's select technology I will choose

156:47

software development years of experience

156:49

let say four I'll choose the same thing

156:52

and professional bio okay let's click on

156:54

complete profile and let's see if this

156:56

you know fetches the AI insights or not

156:59

okay looks like something failed

157:01

argument industry might not be null uh

157:03

let's check okay so over here instead of

157:06

user. Industry we're supposed to provide

157:08

this data. industry right because that

157:11

is where our industry exists for now so

157:14

make sure to replace on both of these

157:16

places and now let's try it again I'll

157:18

click on complete profile there we go

157:20

profile completed successfully and now

157:21

let's go back to our database and

157:23

refresh this page let's see if we have

157:25

the AI generated insights or not there

157:27

we go amazing we can see all of these

157:29

salary ranges over here for different

157:31

different uh roles if I go back uh

157:34

forward you can see growth rate demand

157:36

level high top skills let's click on

157:38

this yep we have some top skills Market

157:40

Outlook positive and other things have

157:43

been populated as well amazing so Yep

157:45

this is how easy it is to generate stuff

157:47

using AI apis like Min let's continue to

157:50

build this page now I'll go back to my

157:53

code inside of this where is it yeah

157:57

page. jsx now over here first of all I'm

158:00

supposed to fetch the industry insights

158:02

right so apart from this I'm going to

158:05

say con insights equals await get

158:07

industry insights this is the server

158:08

action that we just now created if I go

158:10

to it you can see it takes us to the

158:12

dashboard. JS page right so this is

158:14

where we will get all of the insights

158:15

over here inside this D I'm going to be

158:17

creating a component called

158:20

dashboard view so again we're creating

158:22

this separate component because we want

158:24

this to be a client component and this

158:25

right here is a server component so I'll

158:28

say dashboard view insights equals

158:31

insights okay this obviously does not

158:34

exist first of all I'll just give this

158:35

some class name class name of container

158:40

and margin horizontal to be Auto so that

158:42

they are in the middle okay let's get

158:44

this dashboard view component so insert

158:46

this components right here I'll say new

158:48

file Dash

158:50

board- view. jsx r a fce dashboard View

158:56

and this will take the

158:59

insights all right also here we will be

159:03

using like we will be displaying charts

159:05

and stuff as well right so if I go to

159:08

our deployed app like this right so for

159:10

this thing we will be using something

159:12

called as recharts library right so also

159:16

I think we have some error over here

159:18

let's make this component use client

159:22

first and then we'll come back to that

159:23

error also we need to install the

159:25

recharge library right npm install

159:28

recharts press enter let's go back and

159:30

see I think that error was temporary no

159:32

it still exists so it's saying that uh

159:35

unique constant failed on fields

159:38

industry what's wrong let's see I think

159:40

this error is over here in the

159:42

dashboard. JS file so while fetching the

159:45

user from our DB we're supposed to

159:48

include the inter industry insight as

159:50

well right so I'm going to say wear this

159:53

and include industry insight to be true

159:57

now this should work this should fetch

159:58

if the industry Insight is there or not

160:00

okay yeah now it's a separate error

160:02

dashboard view is not defined so

160:04

dashboard view let's import it so let's

160:06

go back to the page. jsx and over here

160:09

I'll import dashboard view component now

160:11

let's go back there we go it is rendered

160:14

great now let's prepare our data that we

160:16

are supposed to display right over here

160:19

like this like Market Outlook industry

160:21

grow demand level top scale uh

160:23

categorizing you know salaries by the

160:25

role all of these key trends and

160:28

recommended skills right so I'll go back

160:30

to the dashboard view component and

160:32

inside of it first of all for the salary

160:35

data so let's see how we structured it

160:37

so it looks something like this right

160:40

roll minimum maximum for each uh you

160:44

know role and the location as well so

160:46

I'll simply over here I'll say const

160:48

salary data is equals to insights do

160:51

salary ranges do map and I'll map

160:53

through each and every one of them and

160:55

I'll categorize them in name Min Max and

160:58

medium right so the reason why I'm

161:00

structuring them in this way so that

161:02

recharts is able to render them let me

161:04

show you so if I go to recharts library

161:08

and over here we would need this simple

161:10

bar chart so over here simple bar chart

161:13

you can see this is kind of similar to

161:15

our example it's just our example has

161:18

three values so you can see name and it

161:20

has one value second value and the

161:22

amount right the this thing amount over

161:24

here so yeah we will come back to this

161:26

but let's prepare our other data as well

161:28

so apart from salary data let's

161:31

structure the demand level so what about

161:33

the demand level so it can be high

161:35

medium or low right so I'm going to say

161:38

I'm going to create a get demand level

161:40

color function over here which will take

161:42

the level and we'll have a switch case

161:44

first of all we'll convert it into the

161:45

lower case right so I'll say if it's

161:47

high it's green medium yellow yellow low

161:49

red by default it will be gray 500 okay

161:53

then after it for our Market Outlook it

161:56

can be positive neutral or negative I'm

161:59

going to create a similar function over

162:00

here if it's positive it will have the

162:02

trending up icon from Lucid react for

162:05

neutral it will have line chart else it

162:08

will have the trending down right and

162:11

respective colors for each and every one

162:13

of them okay and since Market Outlook

162:15

will just have one single value so let's

162:18

just U you know calculate the icon and

162:20

color right below it so I'm going to say

162:24

Outlook icon is equals to and I'll take

162:26

this function over here and I'll provide

162:28

the insights. Market Outlook to it same

162:32

with the color as well and I'll take the

162:34

icon and the color respectively now we

162:36

want to format the date because we are

162:38

also supposed to display this thing over

162:40

here so if I go to deployed website

162:42

we're supposed to display this last

162:43

updated right and it's optional if you

162:45

want to add the next updated or not I'm

162:48

simply rendering it right here next

162:50

update in these many days right okay so

162:53

for last updated I'm going to something

162:56

like this I'll use the format function

162:58

which will come from date- FNS Library

163:01

which is an awesome Library if you want

163:02

to manage dates inside of your

163:04

application so I'm going to say npm

163:06

install date- FNS and press enter I

163:09

would highly recommend you to you know

163:11

read more about it from their

163:12

documentation so they have a few

163:14

functions that we will be needing inside

163:16

of this project first of all the format

163:19

which will be used for formatting our

163:21

dates right we have provided this date

163:24

of last updated and I'm saying format it

163:26

in this format right here next to

163:28

calculate the distance between the

163:31

today's date and the date when this will

163:33

be next updated I'm going to something

163:35

like this const next update distance is

163:38

equals to format distance to now so we

163:40

will also be taking it from date- FNS

163:43

and I'll provide it with the first date

163:45

that is the next update date and it will

163:47

calculate the distance from now to this

163:49

this particular date right so let's just

163:50

import both of these so on the top I'm

163:53

going to say import format and format

163:55

distance to now from date- FNS great and

163:58

also this add suffix basically adds this

164:01

x ago or X days remaining something like

164:04

that in our local language right that's

164:06

why we need ad suffix over here cool

164:09

then so I guess we have prepared our

164:11

whole data let's start rendering them

164:12

right over here right so instead of it

164:15

first of all you can see we have to

164:17

render this last updated badge so we

164:20

have uh already installed badge from

164:22

shat CN UI if you want to see this you

164:25

can go right over here in the badge and

164:28

this is how you use it right so let me

164:29

just copy it up and inside of this div

164:32

I'm going to have another div with the

164:33

badge which will simply render last

164:35

updated to be this last updated date

164:38

let's just give this the class name of

164:41

display Flex justify between and items

164:45

to be Center and I'll provide this

164:47

parent Dev as well some space y of six

164:51

between everything inside of it right so

164:54

let's see how this looks okay I have not

164:56

imported badge so import badge from SL

164:59

components folder yep something like

165:01

this let's add those cards over here for

165:03

our Market overview and for cards

165:06

obviously we'll be getting cards from

165:07

Shad cnii so in the Shad cnii docs I'll

165:11

go to card and I'll copy this thing up

165:15

copy it up coming back and below this de

165:18

I'm going to have our D which will

165:19

contain all of them so let's paste the

165:21

first card and we are not going to be

165:23

needing the footer let's import the

165:25

header the title not going to be needing

165:28

the description let's import this card

165:31

card content and yeah let's see how does

165:34

this look yeah pretty cool for this one

165:37

the title will be Market Outlook and

165:39

let's display the icon below it so it

165:42

will be this Outlook icon and I'll make

165:45

it this Outlook color as well so I'll

165:47

say Outlook icon

165:49

and class name will be H1 like height to

165:52

be four width to be four and I'll give

165:53

this the color that is according to the

165:55

Market Outlook so let's see yep

165:57

something like that and inside of the

165:58

card content I'm going to be adding two

166:01

things first the div which will say how

166:04

the market is right like positive

166:06

negative Etc and the next update so next

166:10

update distance is in 7 days and you can

166:12

see it was last updated today so it

166:13

shows this thing right here okay for

166:16

this card header I'm going to say

166:17

display Flex items to be Center justify

166:20

between so that they are in the very

166:22

center space y to be zero between them

166:24

and padding bottom to be two so let's

166:26

see yep something like that and for the

166:29

card title I'll say text to be small and

166:32

font to be medium and actually I'll say

166:35

Flex row over here so that this is in

166:38

one single row okay yeah that looks good

166:41

let's make space for four different divs

166:43

over here right so I'm going to give

166:44

this display grid for the parent div and

166:47

grid columns 1 for the smaller screens

166:50

in the medium screens I'll say grid

166:51

columns to be two but in the larger

166:55

screens so I'll say I'll say grid

166:58

columns to be four and some gap of four

167:01

between them so now you will see yep we

167:03

have one single card and we have space

167:05

for four more cards over here let's just

167:07

duplicate this card three more times so

167:10

1 2 3 Let's see yep something like this

167:14

now let's start updating each card one

167:17

by one let me just put some gap between

167:19

them so that it's easier to

167:22

differentiate so for the second card I'm

167:24

going to render the industry growth and

167:27

this will have the trending up icon

167:29

right to demonstrate the industry growth

167:32

and I'll render over here the percentage

167:34

at which the industry is growing so I'm

167:36

going to say insights. growth rate. to

167:40

fix and I'll add the percentage over

167:42

here all of these things are already

167:43

provided to us using the AI insights

167:45

right and then after this we will render

167:47

the progress component so if you go back

167:49

to shat scen ui's documentation over

167:52

here we have a progress somewhere around

167:56

here yep this one so this is what we

167:58

will be rendering so let's take this and

168:00

I'll paste it over here make sure to

168:01

import it from SL components and value

168:04

will be this thing insights. growth rate

168:07

so I'll copy and paste it over here and

168:09

simply I'll say class name to be margin

168:12

top to two yep something like this let's

168:15

see how it looks like I come over here

168:18

yep this looks good after this for the

168:20

third card I will render the demand

168:23

level and simply over here I'll say

168:25

insights do demand level and after this

168:28

instead of this P tag I'm going to have

168:30

a div over here which will just display

168:33

the demand level so let me just bring in

168:35

real quick so over here I'm going to say

168:38

a div with the class name of height two

168:40

width full rounded full and margin top

168:42

to be two so we are just going to be

168:44

showing over here a color right so we

168:47

using this get demand level now if you

168:49

want you can also use over here this

168:51

progress bar right you just have to keep

168:53

the value to 100% and change the color

168:56

so it would look something like this

168:58

right and let's change this icon over

169:00

here as well instead of this Outlook

169:02

icon I'm going to say briefcase icon

169:05

with the text muted foreground let's see

169:07

I have not imported it so import it and

169:10

let's see yep something like this then

169:12

for the fourth card let's display the

169:14

top skills over here so instead of

169:16

Market Outlook I'll say top skills and

169:18

here I'm going to going to render the

169:19

brain icon from Lucid react and then

169:23

right here I'll just get rid of it and

169:25

we will have our div and inside of this

169:27

div I will render all of the skills

169:30

right so I'll say insights. toop skills.

169:33

map and I will render a badge icon over

169:36

here simply like the a badge over here

169:38

with this skill and variant is going to

169:39

be secondary and instead of this class

169:42

I'm going to say display Flex Flex to be

169:46

wrap so that they can go to uh you know

169:49

next line and GAP to be one between them

169:51

let's see yep something like this this

169:54

looks pretty good so far now below this

169:56

we are supposed to render the chart

169:59

right the graph over here so let me just

170:02

take this card and duplicate it one more

170:04

time and we are not going to be needing

170:07

these class names over here now let's

170:10

get rid of this insert the card header

170:12

simply we will have two things right the

170:14

card title salary ranges by rule and the

170:17

card description let's import displaying

170:19

minimum median and maximum salaries in

170:22

thousands right in obviously dollars

170:24

let's remove everything inside of this

170:26

card content over here let's see how

170:28

this looks okay there we go we are

170:30

supposed to display the chart below it

170:33

so let's go to the recharge library and

170:37

over here this is what we will be

170:39

getting this responsive container right

170:41

so I'll just copy this whole thing up

170:44

till this point and insert this I'll

170:47

have a div which which will have a class

170:49

name of height to be 400 pixels and to

170:53

give it in pixels you have to wrap it in

170:55

this square bracket and now paste it

170:57

right here right so import responsive

171:00

container this bar chart from recharts

171:04

this cartasi grid

171:07

xais y AIS import the tool tip we don't

171:10

need the legend but we would be needing

171:13

these bar component over here right so

171:15

import the bar component and obviously

171:17

I'll come to these one by one so let's

171:19

see from the beginning so this

171:21

responsive container is basically to

171:22

make sure this is responsive in the

171:24

smaller screens as well the chart is

171:25

responsive in smaller screens right so

171:28

this would need some data over here the

171:29

bar chart so we will provide it this um

171:33

data of salary that we have created

171:35

earlier so salary data if you remember

171:39

this salary data right here we'll

171:40

provide it in the data field and that's

171:42

all let's remove this width height and

171:44

margin from over here then in the

171:47

Cartesian grid we will leave it as it is

171:50

x-axis data key will be the name y AIS

171:53

we will leave it as it is in the tool

171:55

tape yep so over here if you go back to

171:58

our deployed app we have this in the

172:01

tool TI right the name of the role

172:04

minimum salary medium salary and the max

172:06

salary right so this tool tip actually

172:08

takes something called as insert this we

172:10

can have a call back function so

172:13

something like this and we can take

172:14

things from our data inside of it which

172:17

are active payload and label so what is

172:19

active active is basically if we are

172:22

hovering on any one of the bar charts it

172:24

is true right and if it's false then

172:26

tool tip is not displayed okay what is

172:30

payload payload contains basically all

172:31

of the data that is inside of over here

172:33

in the salary data and the label will

172:36

basically be the name so this thing

172:39

right here so this name right here right

172:42

cool then let's go back inside of this

172:45

call back and simply I'm going to check

172:48

if we are hovering on this that this is

172:49

active and payload has something and

172:51

payload do length has something right

172:53

then we'll do something inside of it

172:55

what will we do I'm going to say return

172:57

a Dev over here with the label and then

173:01

after that we have the payload right so

173:03

in the payload we have three things the

173:05

minimum salary the maximum salary and

173:07

the median salary so I'll render them

173:09

one by one the name like the median Max

173:12

etc etc and the value right in K like in

173:16

these many k dollars,

173:18

right if not I'm going to return null in

173:21

the very end and obviously we're going

173:22

to provide them some styles again you

173:23

are free to customize them as you want

173:26

I've just provided some background color

173:28

and some Shadow to it and some font

173:29

medium to this P let's see how it looks

173:33

so if I come over here okay it's saying

173:36

page not found I believe we have to do

173:38

more over here rectangle is not defined

173:41

okay yeah of course we have not

173:42

configure this bar at the bottom so let

173:45

me show you quickly what will we do over

173:47

here so it takes three things data fill

173:50

and active bar so each bar represents

173:52

like min max or median so over here I'm

173:55

going to display this so first will be

173:57

data key Min fill you can you know

174:00

provide any color I've provided a shade

174:01

of gray over here all of these are the

174:03

Shades of Gray and the name me m salary

174:07

to be this thing data key is main over

174:09

here it's important that it is what you

174:11

have written right here right min max

174:14

and median so now this should render yep

174:18

something like this you can see and when

174:20

we are hovering on these we can see the

174:22

label over here as well this looks

174:25

beautiful now after this inside of our

174:27

deployed website we can see we're

174:28

supposed to render the industry Trends

174:30

and recommended skills this will be easy

174:32

right let's go back to our code below

174:34

this card I'm going to actually

174:36

duplicate this card again and let's

174:39

remove everything inside of the card

174:40

content and for the title and

174:42

description I'm simply going to say key

174:45

industry Trends and current trends

174:47

shaping the industry and also we will

174:48

have two cards over here let me just

174:50

duplicate it and put both of these cards

174:53

inside of a d so that we can you know

174:56

create a grid of these two cards so I'll

174:58

give this the class name of display grid

175:01

grid columns one in smaller screens

175:03

above medium screens it will be two

175:05

columns and gap of four between them

175:07

let's see if we come down yep something

175:09

like this now we have the key trends so

175:12

we should be displaying them in points

175:14

just like this right so we'll be using a

175:16

ul and Li tags so inside of the card

175:19

content I'll say UL tag let's give this

175:22

the class name of space y to be four and

175:25

inside of this UL tag I'm going to say

175:27

insights. key trends. map we will take

175:30

each and every Trend and we will render

175:32

inside of a list item right with display

175:35

Flex items start and Space X tob2

175:39

between like both of these three like

175:41

both of these things right first it's

175:44

going to be a DOT over here and then a

175:46

span we have added this dot because by

175:48

default chat cnii you know removes all

175:50

of these styles from CSS so yeah we will

175:54

render the trend and if I go back yeah

175:56

this is our app so you can see it has

175:59

been rendered right here for the next

176:01

recommended skills right so I'll just

176:03

provide the title and description over

176:06

here and skills to consider while de uh

176:08

developing inside of this card content

176:10

again we will render the recommended

176:12

skills array as well everything is like

176:14

absolutely the same right we just at

176:16

this point we just repeating stuff so

176:18

we're just rendering all of the badge

176:20

just like we did earlier for this thing

176:22

right here top skills so yeah you can

176:24

see recommended skills has been rendered

176:26

and yeah with this we have completed

176:27

this industry Insight page now one very

176:29

crucial thing remaining over here and

176:31

that is we need to make sure that we

176:33

fetch it every single week right so now

176:36

we have to come back to inest and we

176:39

have to configure our background job for

176:41

this so what I'll do I'll go to my let's

176:45

just compress it and go to this lib

176:47

folder inside the inist and client.js

176:50

and actually functions. JS not client.js

176:53

and here we will be creating our

176:56

function which will be making the use of

176:58

gini API and fetching the industry

177:00

insights so here I'm going to be

177:02

creating a new function Sol export const

177:05

generate industry insights equals inest

177:10

do create function just like we did

177:13

earlier similar to this we will be

177:15

creating a new inest function and you

177:17

know what let's just go on and run our

177:19

injust client so npx inest CLI at latest

177:23

Dev right so press enter okay let's open

177:26

this Local Host link and there we go if

177:28

you go to the apps you can see it shows

177:30

no functions registered so never mind

177:32

we'll come back to this so over here

177:34

inside of this create function as I told

177:37

you the first object takes multiple

177:38

things like ID name etc etc right so

177:40

I'll just provide the name which will be

177:42

generate industry insights then we will

177:45

have another object over here where we

177:47

will be creating our Cron job now what

177:49

is a Cron job so cron Expressions look

177:52

something like this right now you might

177:54

be confused what is this all about so

177:56

this basically means that this job this

177:58

function will run every single Sunday at

178:00

midnight now how do you know what Crown

178:03

to write over here first of all each and

178:05

every one of these mean something right

178:07

so if I show you I've opened claw AI

178:09

over here and I've simply asked it to

178:11

explain what cron is right so this will

178:13

be more easier for you to understand so

178:15

each and every one of these mean

178:17

something like first one means the

178:19

minute then the hour then the day of the

178:21

month then the month and the day of the

178:23

week right it can be 0 to 6 like if we

178:26

want to run it on Sunday we would put

178:29

zero over here right like just like

178:31

they've given this example over here we

178:33

can Define exactly on that particular

178:35

day what minute this will run so I'll

178:37

put zero what hour I'll put zero that is

178:41

midnight day of the month I will put

178:43

star that means every single day of the

178:45

month and what which month that means

178:48

I put a star over here that means every

178:50

single month of the year right so this

178:52

is how you write Chon expressions and

178:54

again if you want to you know write cron

178:57

for anything simply come over here to

178:59

CLA or you know chat GPT and ask it to

179:01

generate a cron expression to you that

179:03

is much more easier right so coming back

179:05

to this after this we will have a call

179:08

back function right so I'll take the

179:10

call back function this will be an

179:11

asynchronous call back function and

179:13

again we will take the steps over here

179:15

so as I already uh showed you earlier we

179:18

have different different steps for a

179:20

particular job right so first of all we

179:22

will fetch all of the industries over

179:24

here so we want to refetch all of the

179:26

data for the industries right so we want

179:28

to uniquely fetch the industries so I'm

179:31

going to say const Industries equals

179:33

await step. run so this is the first

179:37

step that we are running and this is

179:38

called as fetch Industries and start

179:41

this we have provided this call back

179:43

what it's doing over here it's taking

179:44

this DB let me just import DB over here

179:46

it's saying db. indust insights. find

179:49

many and we are selecting all of these

179:51

industries right over here okay so

179:53

inside this Industries we will get all

179:54

the industries cool then we will Loop

179:56

through all like each and every one of

179:58

them so I'll say for const industry

180:02

industry of Industries right so

180:05

basically we are taking out this

180:07

industry from each and every object of

180:09

these industries right inside this for

180:12

Loop now again we will be running that

180:15

API call over here so in just actually

180:18

provides some functions right out of the

180:20

box for making the uh you know API calls

180:23

so let me show you in their

180:25

documentation yep over here in the AI

180:27

inference you can see they have this

180:29

step. a. RP and step. a. infer these two

180:33

types of functions what we will be using

180:34

is step. a. RP over here if we further

180:38

scroll down you can see not this one if

180:40

we further scroll down you can see this

180:42

is an example of step. a. infer simply

180:45

we are providing this unnamed and then

180:48

we're sying step. a. models this is an

180:51

example of open AI model but if you want

180:53

to use Gemini it also supports Gemini

180:55

right and we can provide the exact model

180:57

name for it and then we can provide the

181:00

prompt and you might be thinking what uh

181:02

you know what is the benefit of using

181:03

these right r or infer so basically

181:06

these functions provide us additional

181:09

information about our API right like

181:12

metrics data sets and adds the

181:14

monitorings to our calls right so it is

181:17

much more easy easier to Monitor and get

181:19

the information from these apis so this

181:21

is what we will be using so first of all

181:23

we will be providing it any name you can

181:25

name it whatever right then we'll be

181:27

providing it a call back function we'll

181:28

be fetching the content and then the

181:30

prompt right so if I go back now let's

181:32

bring our prompt back so we had written

181:36

it over here in the dashboard yep let's

181:39

take this prompt from over here and I'll

181:42

paste it right here after this we'll be

181:44

making use of ai. trap right so I'll say

181:47

con

181:48

response equals await step. a do WP and

181:54

you can read more information about it

181:57

over here as well now what should we

181:59

call it let's call it Gemini then let's

182:03

have a call back function over here

182:05

let's make it an asynchronous since

182:08

we'll be fetching the API data then the

182:11

third thing will be our prompt right so

182:14

how do we get the prompt inside of this

182:16

function we'll get it from right over

182:18

here and inside of this simply we will

182:21

be using the same thing this await

182:23

model. generate content so I'll paste it

182:26

right here instead of prompt I'll

182:27

provide p over here and I'll say return

182:30

cool so this should give us the response

182:32

that we need now from inside of it we

182:34

are supposed to fetch our text right so

182:37

after this I'm going to say const text

182:39

equals r s.

182:41

response. candidates you you might

182:43

remember earlier in the video I showed

182:45

you what response jini AP provides us so

182:48

candidates zeroth index we'll take the

182:51

content we'll take the parts zeroth

182:53

index and then we will get the text if

182:55

you want to get more information about

182:56

it you can just you know simply console

182:58

log and you will realize it's this thing

183:01

right okay if this is not there we'll

183:02

just take it as an empty string and then

183:05

obviously we're supposed to clean it as

183:06

well just like we did earlier over here

183:09

clean text so I'll paste it right here

183:11

cons clean text equals text. replace

183:13

this and trim and yeah that's all after

183:16

this we will do json. and provide it

183:18

with this clean text cool then now all

183:21

we need to do is need to update our

183:23

database right so I'll say a wait step.

183:27

run in this step we will be updating our

183:30

database so I'll say update let's keep

183:32

it inside of back Tex actually update

183:35

this particular industry so industry

183:38

insights and then we will provide the

183:40

call back after it so it will be an

183:41

asynchronous call back it will be a

183:43

simple API call to our database just

183:45

like we have done over here this thing

183:48

right here I'll just copy it up and

183:51

paste it right here so db. industry

183:54

insight. update and I'll say where

183:56

industry is this and the data can be

184:00

I'll say insights and I'll update the

184:02

next update so whatever the date do now

184:05

is and I'll add one week to it and I'll

184:08

add the last updated as well which is

184:10

going to be the current date which I

184:12

think will automatically generated by

184:13

our DB as well right so yeah I think

184:16

that should do it the only only thing

184:18

remaining over here is this how do we

184:20

provide the API key to inest right so we

184:23

have to basically go to our client.js

184:25

and over here after the name I'm going

184:27

to provide credentials inside of the

184:30

credentials it will take Gemini and the

184:32

API key which is our Gemini API key yep

184:35

that is all let's go and try it out so

184:39

I'll go back to my inest de oh sorry I

184:42

have not provided it to our API right

184:44

arang just API so instead of our app the

184:48

API route. JS yep let's provide this

184:51

function over here generate industry

184:53

insights and now if we go back and

184:55

refresh it you can see one function

184:56

found let's go to the functions yep

184:58

there we go let's click on invoke and

185:01

invoke function and let's see how this

185:03

is running okay it has fetched the

185:05

industries but something went wrong with

185:06

Gemini let's see what went wrong model

185:09

is not defined okay let me just cancel

185:12

this job and see what's the error so

185:15

model yeah this one we need to have the

185:18

model right just like we did over here

185:22

yeah we need to copy it up and actually

185:25

and I realize uh this will get the

185:27

Gemini API key from here as well but

185:29

that credentials that I showed you that

185:31

we added that can work in you know cases

185:34

when we are using ai. infer right which

185:37

uses the model like this like this right

185:42

in this case we don't need to create

185:43

models separately it's just taking it

185:45

directly from step. a. models right so

185:48

yeah let's just copy it up and paste it

185:52

right over here on the top let's import

185:55

Google generative AI over here and now

185:57

we should uh be good to go let's rerun

186:00

it let's close this one and open this

186:02

okay fetch Industries it worked let's

186:05

see if Gemini works or not okay looks

186:07

like Gemini has fetched the data and you

186:09

can see this is the exact content that

186:11

we get in the response and see this is

186:14

what we were trying to clean from our

186:15

response and if we go further yep we

186:18

have updated all of the industries as

186:20

well amazing so you see how easy it was

186:23

to set up a background Cron job you

186:25

might have thought I'm pretty sure that

186:27

this would be something very difficult

186:29

but see it was a piece of cake I would

186:31

say with the help of inist creating a

186:33

background function is super easy and I

186:35

have actually uh you know discussed in

186:37

just in one of my previous videos of

186:39

Finance platform as well so you know

186:40

after you have done following this

186:42

project you can go and follow that

186:44

project as well all right then so we

186:46

have successfully created our industry

186:48

insights feature now this is my most

186:51

favorite feature that is the interview

186:53

prep we are going to be creating the

186:55

interview prep page which will be this

186:57

slash interview page right here so first

186:59

of all I'll go to this actions folder

187:02

and create the apis for generating the

187:04

quiz and saving the results of the quiz

187:07

so I'm going to say interview. JS inside

187:10

of this I'm going to be creating a

187:11

function called generate quiz the server

187:13

action and I'll also use the use server

187:17

at the top this is very important don't

187:18

forget it now inside this what will we

187:20

do first of all obviously we need to

187:22

check if the user is logged in or not so

187:24

let me just take it from right here let

187:27

me just take it from this server action

187:30

and just paste it make sure to import o

187:33

from clerk sl/ server and I'll also

187:37

import DB from the Prisma file okay now

187:41

after it we're going to have to write

187:43

the prompt for you know generating our

187:46

quiz so let me show you how I'll do it

187:48

so here it is I'm going to say generate

187:50

10 technical interview questions for a

187:53

user. industry like whatever the user

187:57

industry is I'm going to say generate 10

188:00

interview questions for this and since

188:01

we already have the user skills right

188:03

then we will say if the user uh skills

188:05

are there I'm going to say with

188:07

expertise in whatever the user skills

188:09

are right else we will give empty string

188:13

and then I'm going to say each question

188:15

should be multiple choice with four

188:16

options and we have to return the

188:18

response in the Json format only no

188:21

additional text and the format will be

188:22

this like the question like the array of

188:24

questions with the question options

188:27

correct answer and the explanation of

188:28

that answer right so yeah pretty

188:30

straightforward if you don't want to

188:32

write it over here you know just you can

188:34

go to my GitHub repo and open this

188:36

interview JS file and copy this prompt

188:38

from there after this we will write the

188:40

same thing that we have done earlier

188:42

over here I believe in the dashboard JS

188:44

right y to structure the response I'm

188:46

just going to copy this up up and paste

188:48

it right here so result will be model.

188:51

generate content on obviously we need

188:52

this model as well right so I'll take it

188:55

from right here and put it on the top

188:59

right over here and let's import the

189:01

Google generative AI from at Google /

189:03

generative Ai and then over here I'm

189:06

going to say model. generate content

189:07

with this prompt response will be

189:09

result. response and obviously we are

189:11

supposed to clean the response as well

189:13

right so I'll just copy both of these

189:15

just like this instead of learning this

189:18

I'm going to say cons quiz equals json.

189:21

bar clean text and then in the end we

189:23

would get the array of all the questions

189:25

right so I'll simply say return quiz do

189:31

questions and I think we should keep it

189:33

in a TR catch block so let's keep it in

189:35

a TR catch block I'll move this part

189:38

I'll cut it and move it right after the

189:41

return and inside of the catch I'm going

189:43

to say console. error error generating

189:46

quiz and throw error fail to generate

189:48

quiz questions okay now after we have

189:50

attempted the quiz right we also want to

189:53

save the results of the quiz right so

189:55

I'm going to be creating a new server

189:57

action called save quiz result which

190:00

will take all of the questions that is

190:02

this array that was provided to us all

190:04

of the answers by the user and the final

190:07

score of the user right we will

190:08

calculate these things in the front end

190:11

and then send it to this save quiz

190:13

result server action again same thing we

190:15

will check the user Authentication first

190:17

so I'm just going to copy it and paste

190:19

it right over here now we first of all

190:22

need to structure what we are going to

190:25

be sending to our DB right if we refer

190:27

back to our schema so right here schema.

190:31

Prisma we have this assignment right so

190:35

inside of this we will be storing it

190:36

inside of this questions like array of

190:39

questions answer user answers and what

190:41

is the correct answer and also the quiz

190:43

result so if I go back I'm going to say

190:46

const question

190:47

results and I'll take each and every

190:50

question like questions do map and we

190:53

will return an object from inside of it

190:56

I will take each and every question over

190:58

here and the index of that question and

191:01

this array that we will be forming will

191:03

contain first of all the question right

191:05

so I'll say question equals Q do

191:08

question then the answer the correct

191:10

answer that is not the users answer so

191:12

I'll say Q do correct answer then I will

191:16

take the users answer right so we have

191:18

the users answers array over here so

191:20

we'll simply use the index so I'll say

191:21

user answer equals answers and this

191:24

Index right here if it's the correct

191:25

answer or not so we will compare both of

191:28

them so I'll say Q do correct answer if

191:29

it's equals to answers index then this

191:31

will be true or false accordingly this

191:33

will help us to you know render rui even

191:36

better with less calculations and

191:38

obviously the explanation for each and

191:40

every question and yeah this is what we

191:42

will be storing inside of our database

191:44

but first of all for each and every quiz

191:46

if you might remember we have this

191:48

Improvement tip as well right so

191:50

Improvement tip will obviously be based

191:52

on the questions that are answered

191:54

incorrectly by the user right so we

191:57

would fetch all of the answers that are

191:59

been uh you know like the all of the

192:01

wrong answers so over here what I'll do

192:03

I'm going to say con wrong answers

192:04

equals questions question results do

192:07

filter and whatever question is not

192:11

correct that is not Q do is correct we

192:13

will take it from this particular array

192:15

right and now we will take this wrong

192:17

answers and we will feed it to Gemini

192:20

API so I'm going to say if wrong

192:22

answers. length is more than zero only

192:24

then we will generate the Improvement

192:26

tip so let's fetch all of the uh you

192:28

know text from inside of this array so

192:30

I'll say con wrong questions text equals

192:32

wrong answers. map and for each and

192:35

every child I'll form a text right it

192:38

will be question whatever the question

192:40

is the correct answer and the users

192:43

answer right three things and this is

192:45

what we will be providing for each and

192:47

every question we will be providing for

192:48

uh the AI the Gemini Ai and then we will

192:51

join all of them so after this simply

192:54

I'm going to form my prompt and again if

192:56

you want you can get this prompt from my

192:57

GitHub repo as well or you can just

193:00

watch this video and copy from over here

193:02

so the Improvement prompt the user got

193:05

the following whatever the industry is

193:07

let's say software development industry

193:09

technical interview questions wrong and

193:11

then we will provide this thing that we

193:13

generated right here right and then I'm

193:15

going to say based on these these

193:17

mistakes provide a concise specific

193:19

Improvement tip focus on the knowledge

193:21

Gap revealed by this wrong answer and

193:23

keep the response under two senten right

193:25

we don't want to keep it longer so that

193:27

our UI breaks don't explicitly mention

193:29

the mistakes instead focus on what to

193:31

learn and practice cool then I think

193:33

this will help the user a lot then

193:37

simply I'm going to have the TR catch

193:38

block and we will make the call to

193:40

Gemini API so I'll just go up here and

193:45

just take this just like we've been

193:46

doing up until this point and I'll come

193:48

back and paste it right here so result

193:51

await model generate content and let's

193:53

take this Improvement prompt and provide

193:54

it to it and actually since this is not

193:56

going to be a Json so we won't be

193:58

needing this cleaned text over here and

194:00

neither this json.parse let's just

194:02

simply trim what we get after it right

194:07

and let's see we should take a variable

194:09

over here for the Improvement tip as

194:11

well right so before this I'm going to

194:12

take let Improvement tip equals null and

194:15

I'll update it after it like after we've

194:16

got this so instead of this text I'm

194:19

going to say Improvement tip equals

194:20

response. text. trim and yeah that's all

194:24

uh if there's any error we will just

194:26

console log the error and then outside

194:28

of it let's store all of this inside of

194:30

our database right so I'll have another

194:32

Tri catch block and obviously this thing

194:36

is optional since it depends on the

194:38

wrong answers if wrong answers are there

194:41

only then we will make this Gemini API

194:42

call so now simply over here we will

194:44

feed it to our assessment table so I'm

194:46

going to say const assessment equals

194:48

await db. assessment. create and we will

194:51

provide the data from over here that is

194:52

user ID quiz score questions result so

194:55

if you remember this array that we

194:57

created questions result the category

194:59

and the Improvement tip right cool then

195:02

after this we will simply return the

195:05

assessment and in the catch I'm going to

195:08

provide the console error that error

195:10

saving quiz result and fail to save quiz

195:12

result and yeah that should do it let's

195:15

go on and build the UI for it so I'll go

195:18

to the interview and over here in this

195:21

route let's just create a layout. JS

195:24

file so I'll simply go to dashboard uh

195:27

layout page probably and just copy it up

195:30

and paste it right here let's just get

195:32

rid of this div on the top and yeah that

195:34

should be it this will be more useful

195:36

when we fetch all of the you know

195:37

results and the stats in the interview

195:40

page but let's go on and build this mock

195:43

interview page now so over here first of

195:45

all I'm going to have a div which will

195:47

contain the link to go back right so I'm

195:50

going to have a link tag inside of it

195:52

which will say hre and this will take me

195:55

back to the interview page and then I'm

195:58

going to have a button inside of it with

196:00

variant link let's import this button

196:03

from components and this will have some

196:05

class name of Gap two and padding left

196:07

to be zero because we will have an arrow

196:09

left and back to interview questions

196:11

text over here so let's see so default

196:13

export is not a react component let me

196:16

just refresh it yep there we go let's go

196:18

to// mock over here and then you'll see

196:22

that link Arrow left is not defined

196:23

obviously we have not imported this icon

196:26

right here and also uh let's just add

196:29

some class name of display Flex Flex to

196:31

be column space y to be two and margin X

196:33

to be2 because right below this link we

196:35

will be adding our heading over here as

196:37

well so let's see yep there we go

196:39

something like this back to interview

196:40

preparation cool then so below it I'm

196:43

going to have a Dev over here which will

196:45

contain an H1 tag and a paragraph tag

196:47

just like we've been doing up until this

196:48

point H1 tag will be text 6 Excel font

196:51

Bold and the gradient title class that

196:53

we created three specific questions and

196:55

this will be a text muted foreground so

196:56

let's save it yep something like this

196:58

sorry below this div is where we'll be

197:00

rendering our quiz interview question

197:02

opponent folder over here quiz okay

197:05

let's see oh we have not imported I

197:07

believe so let's just import it over

197:10

here as well and yep we can see this

197:12

quiz right here all right so this is

197:14

let's go ins start this quiz. jsx for

197:16

each and every quiz let me just first

197:17

you know let's just have a look at the

197:19

deployed app and go to the interview

197:21

prep section let's start a new quiz so

197:25

over here you can see we have a box

197:27

saying ready to test your knowledge and

197:30

as soon as we click on start quiz it

197:31

will obviously make the call to Gemini

197:33

and will generate five or 10 questions

197:36

whatever for us there we go now notice

197:38

for each and every question how many

197:40

states would be required first of all

197:42

when we are selecting it we need a state

197:44

to store uh the answer right another

197:47

state for you know storing whatever the

197:49

current question is and also these

197:52

explanation with respect to each and

197:54

every question right not exactly the

197:56

explanation actually uh if you're

197:58

supposed to show the explanation over

198:00

here or not right if it will be a true

198:01

or false state so if I go back I'm going

198:04

to take three states over here and

198:07

obviously since we're using States we

198:09

need to make this a client component so

198:11

use client let's import use state from

198:14

react and yeah you can see I've taken a

198:16

current question all of the answers

198:18

array and the show explanation

198:20

Boolean okay now we would need to fetch

198:23

the data right so again we have already

198:26

created that use fetch hook so I'm going

198:28

to be using the use fetch hook let's

198:30

just import it and this generate quiz

198:32

server action that we created and we

198:34

will take the loading rename it to

198:35

generate quiz generating quiz and

198:38

function rename it to generate quiz

198:39

function and data to quiz data right and

198:41

we will use this function right here to

198:43

call this and you know generate all the

198:45

questions using AI let's just first

198:47

create that UI where we will you know

198:49

show that box to the user so that they

198:52

can click on start quiz button and start

198:55

the quiz so I'm going to say if no quiz

198:59

data is present then I'm going to return

199:01

a card over here right so let's just get

199:04

the card from Shad ceni from over here

199:08

let me just copy it and paste it over

199:11

here we won't be needing the card

199:12

description for the title let's say

199:14

ready to test your knowledge inside the

199:16

card content I'm going to say this quiz

199:19

contains 10 questions blah blah blah

199:20

you've already seen this right text

199:22

muted foreground and in the card footer

199:24

let's just display a button saying start

199:27

quiz and this will be width full so

199:29

let's see card is not defined obviously

199:31

we have not imported all of these three

199:33

uh things so card header card title card

199:38

content card footer and is button there

199:41

no let's import the button as well and

199:43

let's see yep something like this let's

199:45

create some Gap between them or actually

199:48

on the sides so I'll say MX to be 2 that

199:51

is margin horizontal to be two and for

199:54

the uh page. j6 let me just give some

199:56

class name over here which will be

199:58

container margin horizontal to be Auto

200:00

some space between these and some

200:02

padding vertical to be six so now you'll

200:05

see yep we have some spacing between

200:07

them cool let me just close this now

200:10

when we click on this button start quiz

200:13

button we want to call a function right

200:15

so I'll say on click

200:17

generate quck quiz function which you

200:19

already know comes from right here cool

200:22

so when we click on it this will

200:23

generate the quiz let's just show the

200:25

loader as well I'm going to say if the

200:27

quiz is being generated like if

200:29

generating quiz then return bar loader

200:32

let's import this bar loader and same

200:34

things that we have already given it

200:36

earlier and also as soon as the quiz is

200:39

generated what I'll do I'm going to say

200:41

inside of the use effect let's just

200:43

import the US from react I'm going to

200:45

say if the quiz data changes then set

200:47

all of the answers in this set answers

200:50

array cool then so let's just work on

200:52

the UI so first of all uh you can see

200:54

the current question is zero by default

200:56

right so that is where we will be

200:57

starting our quiz from from the zeroth

200:59

index so after this I'm going to say

201:01

const question equals quiz data and

201:04

whatever the current question is it's on

201:05

the zero so that will be our current

201:08

question so insert of this div is where

201:09

we will be writing our UI and instead of

201:11

this div actually I'll just take this

201:14

card and paste it right right here yep

201:17

and let's update it so for the card

201:20

title I'm going to say question whatever

201:22

the question is 0 + 1 so obviously we're

201:25

going to start from zero so 0 + 1 of

201:28

whatever the total length of the

201:29

questions is inser the card content I'm

201:32

going to render my question so I'm going

201:34

to say question do question and it will

201:36

be text large and font medium let's

201:38

remove this button from card footer we

201:40

will come back to this card footer and

201:42

after this after entering this question

201:44

we will render all of the four options

201:45

over here as well right so for that

201:47

we'll be using radio group that we have

201:48

installed so let's see we have this

201:52

radio group over here yep something like

201:55

this so let's just copy this code from

201:57

over here and paste it right after this

202:00

so insert this let me just remove both

202:02

of these options over here and yeah so

202:05

radi inside of the radio group we will

202:07

render the options from inside of our

202:09

question so I'll have uh question.

202:11

options. map over here let's take the

202:15

call back inside of it we will take each

202:17

and every option and the index of that

202:20

option let's move this div inside of

202:23

over here and I'll say return let's give

202:26

this the class name of space y to be2

202:30

and since we're using the map let's just

202:32

give this the key of index now for this

202:34

radio group item we're taking each and

202:36

every option right so I'm going to say

202:37

value will be option and the ID will be

202:40

option and whatever the current index is

202:42

similarly for this label as well I'm

202:44

going to say HTML for and whatever the

202:46

ID of this uh radio group so when we

202:48

click on this it selects the radio group

202:50

right when we click on the label let me

202:52

just import all of these one by one so

202:54

make sure to import from SL components

202:56

only radio group item from SL components

202:59

and radio group as well let's see how

203:02

this looks like so I'll go back to our

203:05

app and click on start quiz so it is

203:07

loading the quiz I believe and let's see

203:10

and there we go our quiz is loaded

203:13

successfully amazing now we just have to

203:14

work on this UI right now right so let's

203:17

focus on that let's add the logic for

203:19

selecting a particular option now for

203:21

this radio group I'm going to say on

203:23

value change and I'll call this handle

203:25

answer which we will just go on and

203:26

create in just a moment and the value

203:28

will be answers of the current question

203:31

so if you remember this is an array

203:33

populated with null so on value change

203:36

we will provide the users answer to this

203:38

handle answer uh you know function so

203:40

let's just go on right below this use

203:42

effect I'm going to say const handle

203:45

answer equals

203:47

whatever the user's answer is I'm going

203:50

to take that and notice in start of it

203:52

first of all I'll just make a shallow

203:54

copy of the state of the answers right

203:56

so I'm going to say new answers equals

203:58

whatever the existing answers is then

204:01

I'll take this copy and for that

204:03

particular question for like whatever

204:05

the index is right I'll update the

204:07

users's answer and then I will update

204:10

the array back right this state back to

204:12

this simple enough then after this I'm

204:15

going to be adding the Logic for you

204:17

know displaying the explanation as well

204:19

so after the radio group actually I'm

204:22

going to say show explanation so if the

204:24

show explanation is true only then we

204:27

will be showing the explanation so let's

204:29

take a div over here andert this I'm

204:32

going to have a P tag which will say

204:34

explanation and then another P tag which

204:36

will show the question do

204:40

explanation oops explanation let's keep

204:43

it font medium and for the explanation

204:46

keep the color as muted foreground for

204:48

the div containing this I'm going to say

204:50

margin top to be four padding four

204:52

background muted and rounded large so

204:54

let's just make it true so that you can

204:56

see what are we getting over here oh

204:59

sorry I think I lost the UI uh you know

205:01

what let's just um let's just do it

205:04

again let's click on start quiz yep you

205:05

can see we have the explanation right

205:07

here let's give some spacing between

205:09

both of these so I'll go to this card

205:12

content and I'm going to provide the

205:13

class name of space y to be four okay

205:16

now in the footer and by the way let's

205:18

just R it back to show explanation now

205:22

in this card footer right here we will

205:24

display the button for you know for

205:26

triggering the show explanation only if

205:28

the user has selected any option and

205:30

also the ability to you know go to the

205:33

next question so pretty simple UI if the

205:35

show explanation is not true I'm going

205:38

to display a button over here with

205:39

onclick set show explanation to True

205:41

when we click on it it will be true

205:43

variant will be outlined and if that

205:45

particular question has not been

205:46

answered I will display like disable

205:49

this button right and after this I'm

205:51

going to have a button for going to the

205:54

next question so I'm just going to copy

205:55

this button and paste it right here so

205:57

it's going to say if the current

205:58

question is less than the last question

206:01

right if we are not on the last question

206:03

we will show the next question else we

206:05

will show the finished quiz and this

206:07

will also be disabled if the question

206:09

has not been answered let's keep the

206:11

class name to be margin left Auto and on

206:14

click I will trigger a function called

206:17

handle whoops handle next we'll create

206:21

this function as well so I'll go over

206:23

here below let's say handle answer I'm

206:27

going to say const handle next let's

206:30

create a arrow function and now notice

206:32

inside of it I'm going to say if the

206:34

current question is less than the quiz

206:39

data do length minus one that is it is

206:42

not the last question right then simply

206:44

I'm going to say Set current question

206:46

question to current question plus one

206:48

and also I'll make this shed explanation

206:51

to false so that we don't see the

206:53

explanation for the next question right

206:54

away else we will trigger the

206:57

Finish quiz function which obviously

207:00

does not exist yet so let me just create

207:02

a dummy function for now finish quiz

207:05

something like this and we will

207:06

basically be calculating our score

207:08

inside of this finish quiz function and

207:11

then we will make the API call for

207:12

saving the result of our quiz so you

207:15

know what let's just take the other

207:18

server action as well let me just import

207:19

that right here save quiz result let me

207:22

just import it from SL action SL

207:24

interview so over here we'll take

207:25

loading function data and set data now

207:28

this set data as I already explained you

207:31

can be manually used for setting the

207:33

data of our quiz so basically when our

207:36

quiz is done we can take this set data

207:38

and you know set it to null after the

207:40

new quiz is started you know so that our

207:42

result data state is empty all right so

207:46

let's take this save quiz uh result

207:48

function and uh let's go inside this

207:51

finish quiz now first of all before uh

207:53

you know making this API call we have to

207:56

also calculate the score of the user so

207:58

I'll say const score let's just keep it

208:01

Zero by default for now and I'll have a

208:04

try catch block and insert this I'll say

208:07

await call this save quiz result

208:10

function and we will send the quiz data

208:14

we will send the answers the users

208:16

answers and obviously the score then we

208:18

will show the success toast so I'll say

208:20

toast. success and make sure to import

208:22

toast from sonor and set the catch block

208:24

I'll say toast. error if you know

208:26

anything fails over here now let's

208:28

calculate this score so for calculating

208:31

this score let's just have a function

208:33

called calculate score and this will be

208:35

a pretty straightforward function let me

208:37

show you so if I put it right here so

208:39

yeah calculate score we will start with

208:42

zero right the correct answers are zero

208:45

so far and then we will Loop through all

208:48

of the users answers we'll go inside of

208:50

it I'll say if the answer is equals to

208:53

the actual correct answer right whatever

208:55

the user has answered I'm going going to

208:57

go insert the user data dot like off

208:59

index and take the correct answer will

209:02

compare it if it is equals to it then

209:04

I'll say correct Plus+ and then in the

209:06

end I will return the number of correct

209:08

answers divided by total ansers into 100

209:11

that is we are calculating the

209:12

percentage over here and that is what we

209:14

will be sending to our back end to

209:16

displayed all right so also let's see

209:19

let's make use of this saving result

209:21

over here this loading indicator so I'm

209:23

going to go to the very bottom where we

209:25

had our button and I'm going to say this

209:27

will be disabled when we are saving our

209:30

result and also let's just display a bar

209:33

loader over here when we are saving our

209:35

result right cool then let's go on and

209:37

try it out um what I'll do I'll just uh

209:40

for now I'll just console log this

209:42

result data over here just to see what

209:45

do we get inside inside of it so result

209:47

data okay let's go back to our website

209:50

I'll click on start quiz and I'll open

209:52

my inspect over here as well console and

209:56

let's see so I'll just randomly answer

209:58

all of the questions over here and let

210:01

me just do this real quick okay there we

210:04

go I'm in the ninth so now after this it

210:07

should display a finished quiz and let's

210:10

just randomly choose something and click

210:12

on finish quiz and now it's not

210:14

displaying the loading indicator we'll

210:16

check what's wrong over here let's see

210:18

what happens okay quiz completed and

210:20

there we go we get something over here

210:23

we get all the questions the quiz score

210:26

10 did I answer everything correctly and

210:29

I don't think so that would be the case

210:30

but let's see what do we get over here

210:32

okay this is is correct false this

210:35

is is correct false over here okay yeah

210:38

you can see it has created the complete

210:40

structure for every single thing like uh

210:43

what is the correct question was what

210:45

user answer was right I shouldn't have

210:47

displayed the quiz score to be 10

210:49

probably I did something wrong over here

210:51

let's check probably we will check it

210:53

later on let's just first uh render all

210:56

of the results and then we can check it

210:58

so also uh apart from this bar loader

211:00

let's just display this loader to from

211:03

Lucid react I think this will be better

211:05

uh in showing the loading indicator

211:06

right and also let's just check if this

211:08

has been entered inside of our database

211:09

or not so I'll go to the assessment

211:11

Table and there we go I think we have

211:14

something over here but this is is wrong

211:16

most probably quiz score to be 10 this

211:19

shouldn't be that the case so let's do

211:21

one thing I'll go back to the code and

211:24

above this return and above this not

211:27

quiz data I'm going to say if the result

211:30

data is there I'm going to return a d

211:32

with the quiz result component and this

211:34

component does not exist we will build

211:36

it right now we will send it the result

211:39

data in the result and also we will send

211:41

it a prop on start new where we will

211:44

trigger this start new quiz function and

211:46

this will be pretty simple we will just

211:48

you know null everything inside this

211:50

function so I'll just say const start

211:52

new quiz equals set currect question to

211:55

zero set answers to empty set show

211:57

explanation to false H we're going to

211:59

generate know a new quiz when we trigger

212:01

it and set result data to null right we

212:03

just resetting every single thing over

212:05

here let's just create this component

212:06

first of all so I'm going to go and

212:07

start the components create a new file

212:09

called quiz result.

212:13

jsx r a fce quiz result let's import

212:17

this component right over here so I

212:20

actually tried it out once again and uh

212:23

looks like this is working now now the

212:25

quizes score is not being generated

212:27

fully not sure what went wrong earlier I

212:31

tried generating it with just three

212:33

interview questions let's just put it

212:35

back to 10 maybe some bug but it's

212:38

working fine now so yeah we're good so

212:40

let's start working on this quiz result

212:42

component so this quiz result component

212:44

we'll be using in multiple places right

212:46

over here in this quiz component as well

212:48

and also on the page of the interview

212:50

page like the where we'll be displaying

212:52

all of the stats and stuff as well right

212:54

so there we don't want to show this

212:56

start new quiz button so I'm going to

212:59

say I'll have a result I'll have highest

213:01

hide a start new flag over here as well

213:03

we won't be using it right here but

213:05

we'll be using it somewhere else and an

213:07

on start new function over here as well

213:10

okay so first of all I'm going to say if

213:12

the result is not present obviously

213:13

return null but if it is present then

213:16

first of all I'm going to say quiz

213:17

result as the title and I'll display the

213:20

trophy icon from Lucid react and simply

213:24

I'm just going to say display Flex items

213:25

to be Center some Gap to be two between

213:27

both of these text to be 3 Exel and

213:29

gradient title then after it let's just

213:31

take a card content component from Shad

213:36

CN uui and inside of this we can render

213:39

the quiz result right so first of all

213:41

the overview of the score I'm going to

213:43

have a Dev with the H3 of result do quiz

213:47

score and whatever the percentage is

213:49

right this will be in the percentage so

213:50

I'll say two fixed one and percentage

213:52

and we will also render the progress

213:54

component just like we've done in the

213:56

you know insights page as well similar

213:58

to that we'll be rendering result.

214:00

quizes score over here after that we

214:02

would have also gotten the Improvement

214:04

tip generated by AI so if you see yeah

214:07

in these results yeah you can see the

214:09

Improvement tip focus on mastering blah

214:11

blah blah we cannot see it fully right

214:13

now yeah you can see this tip was

214:15

generated using using AI so we will

214:17

render this now so after this I'm going

214:19

to say result do Improvement tip if that

214:22

is present then inside of a Dev I'm

214:24

going to be rendering uh P tag with the

214:26

Improvement tip title and the result do

214:28

Improvement tip and obviously we will

214:30

say text muted foreground for this and

214:32

font medium size for this then after

214:34

this we will display question wise uh

214:37

you know explanation like what went

214:39

wrong if and what went right so I'm

214:41

going to have a div over here with the

214:44

H3 tag which will say say

214:46

question review then below this I'll

214:49

take the result and map through it so

214:51

result do question questions actually do

214:56

map so we will map through each and

214:58

every question and we'll render them

215:00

over here let's give this div some space

215:02

y of four and the H3 of font medium and

215:06

also this paren Dev I'll just give this

215:08

margin horizontal of Auto that this is

215:10

in the very middle and now over here we

215:13

will have a d inside this we're going

215:15

have another day which will display the

215:17

question and if that question is correct

215:19

or not so I'm going to have a P tag

215:22

which will display the question so Q do

215:24

question and if it's correct then we

215:26

will show the check Circle so it will

215:28

look something like this and if it's not

215:30

correct I'll show The X Circle which

215:32

will look something like this and both

215:34

of them will be imported from Lucid

215:36

react and for this one I'll put the text

215:38

green of 500 and this one textured of

215:40

500 at some generic styles of height

215:42

five width five and flex shrink of zero

215:45

this div is going to be having a class

215:47

name of display Flex item start justify

215:49

between and some gap of two between them

215:51

and this parent div will have the class

215:53

name of some border rounded large and

215:56

padding to be four space y to be two

215:59

because after this div right here we

216:01

will be displaying more things right

216:02

like our answers the correct like your

216:05

answer and the explanation of the answer

216:08

so first of all I'm going to say your

216:10

answer is this and if it was not correct

216:13

only then we will display the correct

216:15

answer over here and also we will

216:18

display the explanation after it

216:20

regardless of the fact the answer was

216:22

correct or not so I'll have a d and I'm

216:24

going to say explanation and just render

216:26

the explanation just like we've done

216:28

earlier right and yeah after after this

216:31

de actually after this card component

216:33

sorry card content I'm going to say if

216:36

hide start new is not true then we will

216:39

display this start new quiz button over

216:41

here so I'll say up button on on click

216:44

on start new that we are getting from

216:46

right here and yeah I think uh this

216:49

should do it this should display all of

216:51

the results so let's go back and how

216:53

about we attempt a new quiz over here so

216:55

I'll click on start quiz and it's

216:57

loading it and there we go so we have 10

217:00

questions over here let's just randomly

217:02

answer all of these one by one there we

217:05

go we are on the last question now let's

217:08

click on finish quiz it is loading it

217:10

and let's see progress is not defined oh

217:13

man okay let's just import the progress

217:16

over here let's see if there's something

217:18

else that we have not imported I believe

217:20

I have imported this how about card

217:22

footer let's import card footer button

217:24

let's import button card content must be

217:26

already imported trophy is this imported

217:29

yeah this is imported let's try it out

217:31

again anyway let's me just put this to

217:34

three questions now instead of 10 10

217:37

questions every single time this will be

217:39

easier for me to test it out so again

217:41

let's randomly answer them one by one

217:43

and also let's just click on show

217:44

explanation and yeah this is working

217:46

fine and okay let's finish the quiz and

217:49

hopefully nothing goes wrong now Q is

217:51

not defined wow where is this coming

217:53

from so quiz result so we are mapping it

217:57

and obviously we have not taken the que

217:59

over here and also the index which we

218:03

will be using as a key so key equals

218:07

index and hopefully that should be it

218:09

let me just try it out again let's click

218:11

on finish quiz and there we go we are

218:13

getting the quiz results just just like

218:15

this amazing so you can see we have the

218:19

Improvement tip on the top I believe

218:21

this would need some spacing between

218:23

these so for this card content I'm going

218:25

to put this class name space y26 I'm not

218:27

going to save this right now because

218:28

this will you know refresh the page so

218:31

apart from that let's see the question

218:32

review yep we can see we have answered

218:34

all of them incorrectly and we have the

218:36

option to start a new quiz over here as

218:38

well great so let's just click on start

218:41

new quiz and let's start to actually

218:43

attempt the quiz this time and there we

218:45

go looks like like I have answered all

218:46

of the questions correctly now great if

218:49

you want you can wrap this quiz results

218:51

into a card component over here as well

218:53

instead of this div so if I just say

218:55

card and if I go back now yeah I think

218:58

div was much better so I'll revert it

219:01

back to the dev and cool then next what

219:04

I'll do we can click on back to

219:06

interview preparation and this is the

219:08

page where we can render all of the

219:10

stats related to the you know assessment

219:12

that user has attempted and all of the

219:14

quizzes that user has attempted in the

219:16

past so let's build this so I'll go to

219:19

this interview. JS again and let's

219:23

create the server action for this so

219:25

it's going to be pretty straightforward

219:27

I'll say export async function get

219:29

assessment and inside this first of all

219:31

let's check for the user authentication

219:34

uh sorry not authentication

219:35

authorization I'll just copy this and

219:38

I'll paste it right here to check if

219:40

user is found or not then I'll have a

219:43

try catch block over here

219:46

and here let's fetch all of the

219:48

assessments so I'm going to say const

219:50

assessments equals await db. assessment.

219:53

find many and I'll say where user ID is

219:55

this whatever the current user logged in

219:57

is and sort them in the ascending order

220:00

with respect to the created and return

220:02

the Assessments in the end and in the

220:03

catch I'll again handle the console

220:05

error error fetching assessments cool

220:08

then let's go to our page. jsx and start

220:12

building it so let's plan this uh

220:14

interview page first so so what are the

220:16

three things that we will be having over

220:18

here let's go and check inside of our

220:19

deployed website right here so first of

220:22

all we will have these cards which will

220:24

show us the statistics then our

220:26

performance Trend graph and then after

220:29

it we will render all of these quizzes

220:31

and when we click on it we will just

220:32

reuse that uh you know quiz results

220:34

component that we created earlier okay

220:37

so I'll go back first all over here

220:40

let's just display a H1 tag so I'm going

220:42

to have a de and start of this I'm going

220:45

to display the H1 tag just like we've

220:46

been doing up until till now texx XL

220:49

gradient title and font bold and also

220:51

let's just give it some margin bottom of

220:54

five over here let's save this and check

220:56

it out Yep this is what we want now

220:58

below this I'm going to have a div and

221:00

we will display three components over

221:02

here that we already saw right so let's

221:04

just create uh a new component for each

221:06

and every one of them so I'll say stats

221:08

card and by the way we just now created

221:11

this API endpoint like server action

221:14

right so let's get all the assessments

221:16

over here so I'm going to say const

221:20

assessments equals a weight get

221:23

assessments let's import it and also

221:25

let's make this an asynchronous

221:27

component since this is a server

221:29

component and I'll take this assessments

221:31

and I'll provide it to these stats card

221:34

over here like that similarly I'll

221:37

create two more components and they will

221:39

also take the assessments one will be

221:41

for displaying the performance chart

221:43

another will be for displaying the quiz

221:44

list

221:46

simple enough let's go on and make these

221:48

components so inside of the components

221:50

folder I'm going to say stats cards. jsx

221:56

R A fce stats cards second one will be

222:02

performance chart. jsx let's paste the

222:06

same code over here and I'm going to

222:08

rename it so

222:09

performance chart and then the third one

222:12

will be quiz list oops quiz list.

222:16

jsx I'll rename it to quiz list okay

222:22

cool let's just uh import all these

222:24

three over here stats cards performance

222:28

chart and quiz list cool let's just see

222:30

if it's fine yep we can see all these

222:33

three over here let's first work on this

222:34

stats cards so since we have to display

222:37

three cards over here inside of it right

222:39

so let's just use display grid over here

222:42

so I'm going to say class name to grid

222:45

Gap to be four between them and if the

222:46

screen size is more than medium I'll say

222:48

grid columns to be three let's take the

222:51

assessments over here from the props and

222:53

now let's see what are all the types of

222:54

Assessments that we'll be displaying

222:56

we'll be displaying the average score

222:58

the questions that we have practiced up

223:00

until this point and the latest score

223:02

that we got in the last quiz right in

223:04

the most recent quiz so for calculating

223:07

the average score it's going to be very

223:09

simple we'll be taking all of the

223:10

assessments over here right first of all

223:12

we'll check if we have any assessments

223:14

or not if we don't we'll just simply

223:15

return zero but if we do I'm going to

223:17

say assessments. reduce I'll take each

223:20

and every assessment and the sum like

223:22

this is an accumulator and this is the

223:24

each and every value if you know about

223:25

reduce I've created an in-depth video on

223:27

map filter reduce if you want to check

223:29

it check it out you can you know go and

223:31

search my channel so I'm going to take

223:34

an accumulator and the assessment so by

223:36

default sum will be zero and we will be

223:39

adding assessment do quiz score to it so

223:41

we will get all of the total and then we

223:43

can simply say total divide by

223:45

assessments. length and we will get the

223:47

percentage for it now if you want to get

223:49

the details of the latest assessment

223:51

simply I'll just say if assessment.

223:53

length first of all we'll check if it's

223:54

there or not else we will just return

223:57

assessment of zeroth index and we will

223:59

get the latest assessment then how do we

224:01

get the total number of questions I'm

224:03

going to say const get total questions

224:04

and inside of it again we will have the

224:07

check for it and I'm going to say

224:09

assessments. reduce this time instead of

224:12

this uh quiz score I'm going to say qu

224:15

questions. length right so we will take

224:18

each and every quiz and add the

224:19

questions length inside of it right so

224:22

cool then we got all of these three

224:24

stats right here now insert this div I'm

224:26

going to be using three cards so we have

224:29

already created similar cards right if

224:31

we go back to our industry insights see

224:35

we have created similar cards over here

224:36

as well right so these are very similar

224:39

to what we will be building over here so

224:40

what I'll do I'll just go back to

224:43

dashboard right here and let's go over

224:45

here dashboard View and let's just take

224:48

this first card and let's copy it up

224:51

let's go back and I'll paste it right

224:53

here let's just import all of these

224:55

things card card header card title

224:59

instead of Outlook icon I'll just say

225:02

trophy icon card content and yeah let's

225:05

work on this I'm going to say instead of

225:07

Market Outlook I'm going to say average

225:08

score and instead of this I'll have

225:11

simply H4 withd for and text muted

225:13

foreground and here we can display the

225:16

average score right so this thing get

225:18

average score so I'll just take this and

225:21

put it right here call this function and

225:23

put a percentage after it and on this

225:26

line I'm going to say across all

225:28

assessments so let's see if this looks

225:30

good I'm going to go to the interview

225:32

prep page yep that is exactly what we

225:34

want let's see if the UI is similar to

225:37

this yep it's exactly the similar to

225:39

this one and these other two cards will

225:41

also be same so let me just duplicate

225:43

this card right here two times in the

225:46

second one we want to display the

225:48

questions practiced so instead of

225:50

average score I'll say questions

225:52

practiced instead of trophy I'll have

225:54

brain as the icon Let's uh render the

225:58

total questions over here so I'll say

226:01

get total questions and below it total

226:04

questions okay for the third one I'll

226:07

display the latest score so instead of

226:09

average let's say latest score here

226:12

instead of get average score I'm going

226:13

to say get latest assessment and I'll

226:16

take out the quiz score from it fixed to

226:19

one decimal point and I'll say

226:21

percentage instead of across all

226:23

assessment I'm going to say most recent

226:25

quiz right let's check it out yep there

226:27

we go looks good let's start working on

226:29

this performance chart now so I'll go to

226:32

this and this will be using like making

226:35

the use of recharts right so let's see

226:38

what chart will be uh building over here

226:40

so it must be a line chart right so

226:43

let's see I'll go to the rechart

226:45

documentation and open this simple line

226:48

chart component so you can see this is

226:51

how we will be using it let let's come

226:53

back to this first let's prepare our

226:55

data for rendering the chart it will be

226:58

very similar to how we did earlier so

227:00

first of all let's just create a state

227:01

over here and also we need to input the

227:03

assessment right so I'll say assessments

227:07

and let's create a u state for chart

227:09

data chart data and set chart data and

227:12

now after it I'm going to say use effect

227:15

and I'll run this use effect as soon as

227:18

we render this component right so as

227:20

soon as the assessments changes we're

227:23

going to write the logic inside of it so

227:25

I'll say if assessments has anything

227:27

inside of it I'll say const

227:30

formatted data equals

227:33

assessments. map and I'll take each and

227:36

every assessment and go inside of it and

227:39

I'll format it so we want two things we

227:41

want the date and we want the score for

227:44

that particular quiz right so that's

227:46

what we'll write over here so instead of

227:48

this curly braces actually I'll have a

227:51

round bracket or parenthesis and then

227:52

inside of it I'm going to create an

227:54

object like this and I'll have a date

227:57

and I'll format it so for formatting it

227:58

we will be importing format from date-

228:01

FNS just like we did earlier and we will

228:03

provide the date of when that assessment

228:06

was created and we will provide this

228:09

formatting right month and date like for

228:10

example January 2 or something like that

228:13

right and this score for that particular

228:15

quiz and that is how we will get this

228:17

formatted data and let's just set this

228:19

data after xile say set chart data to

228:23

formatted data cool let's just take the

228:26

card component from shat CN UI uh to

228:28

render this what's going on oh sorry

228:30

this is a client component right so I

228:31

have to use use client over here

228:35

directive so that uh it does not break

228:37

let's go to shat CN UI and I'll take the

228:40

card component this one let's copy it up

228:43

and paste it right over here we don't

228:47

need this div over here get rid of it in

228:49

the card title I'm going to say

228:51

performance Trend and let's make this a

228:53

gradient title right just like we've

228:55

been doing up until now so I'm going to

228:57

say class name is going to be gradient

228:59

title text 3 XEL and in the larger

229:02

screens text is going to be 4 XL let's

229:04

see how this looks card is not defined

229:06

of course we have not imported all of

229:08

these things card card header card title

229:12

card description card content and no

229:16

need for the card footer let's see now

229:19

yep that is what we want let's provide

229:20

the description to it and that will

229:22

simply be your quiz course over time

229:26

okay so now instead of this P tag over

229:29

here let's just take that chart from

229:31

recharts so simple line chart and let's

229:35

just copy this responsive container from

229:38

over here till right here let's provide

229:40

a div over here first of all and I'll

229:42

give the class name of height to be 3

229:44

100 pixels and then inside of it I'm

229:46

going to paste that responsive chart

229:48

let's make sure to import all of these

229:50

things line chart from recharts make

229:53

sure to import it from recharts only

229:55

cartasi grid xais y AIS tool tip from

230:01

recharts as well we won't be needing the

230:03

legend and we will just have one line

230:05

right so I'll get rid of this one I'll

230:08

just have this line right here okay

230:10

let's see I think currently it will be

230:12

breaking since we have not provided dat

230:15

yep we have not puted the data so let's

230:16

see over here in the line chart let's

230:19

get rid of this and this instead of this

230:22

data right here I'm going to say chart

230:24

data right then uh for this Cagan grid

230:28

let's keep it as it is data key will be

230:30

the date so we have date and the score

230:32

right you can see date and the score so

230:34

on the x-axis I'm going to keep the date

230:36

and on the y axis it will go from 0 to

230:38

100 right so I'm going to say domain it

230:39

goes from 0 to 100 and it will map the

230:42

scores over here now for the this tool

230:45

tip if you remember uh let me show you

230:47

so yeah you can see it is starting to

230:49

show up see we have this tool tip over

230:51

here with score % Etc right we did this

230:54

earlier when we were working on the uh

230:56

insights so it takes something called as

230:59

content oops content inside this we will

231:02

have a call back function and this call

231:04

back function will take active and

231:07

payload the these are the two things

231:09

that we will be needing right now so

231:10

I'll say if it's active that is we are

231:12

hovering on it oops Act

231:15

and payload has something inside it it's

231:17

called payload do length let me just put

231:19

a optional chaining over here so that it

231:21

doesn't break and inside of this I'm

231:24

going to return a very simple de which

231:27

will contain the score and the date so

231:29

I'll have two paragraphs score payload

231:31

do value percentage right and the date

231:34

of from inside of that payload and let's

231:36

provide it some background as well so

231:38

I'm going to say BG background border

231:40

rounded large padding to be two and

231:42

Shadow to be medium let's check it out

231:44

this looks like if I go back to my app

231:47

okay yeah again we have not rendered the

231:48

line over here right so yeah we have to

231:51

configure this so line will display the

231:53

score right so uh data key can be score

231:56

stroke I'm going to provide the primary

231:58

color from shat cnii if you want you can

232:00

provide it some other color as well and

232:03

instead of this active dot over here I'm

232:05

going to say stroke width and let's

232:08

provide it to be two let's check it out

232:11

now there we go it looks awesome with

232:14

all the tool tool tip and everything

232:15

right we can see over the time how we

232:17

have performed in the quiz we can see

232:19

the questions practiced latest score and

232:21

the average score as well awesome let's

232:24

render the you know list of the quiz

232:26

right here and also let's provide some

232:28

gap between these so I'll go to the

232:30

page. jsx and in this div right here I'm

232:33

going to say class name space y to be 6

232:37

and let's see yep we can see the SPAC is

232:40

between them all right let's work on uh

232:42

the quiz list so let's take the

232:45

assessments over here and this will be

232:47

pretty straightforward we will render

232:49

the card for each and every quiz and

232:52

then when we click on it we have to

232:54

display a dialogue box for the results

232:56

and also have the option to start new

232:58

quiz right so for routing to mock

233:01

interview page let's just have a use

233:03

router hook over here imported from next

233:06

/ navigation we will be using it in just

233:08

a moment and we will also create a state

233:10

over here for the selected quiz right

233:13

the one that we want to open the

233:15

dialogue for so let's import use State

233:17

as well from react let's take the card

233:20

component right here so let me just have

233:23

a fragment and inside of it we'll have

233:25

the card component so let me just take

233:26

it from shat CN UI again and paste it

233:29

right here let's import the card card

233:32

header card title card description card

233:37

content and again we won't be needing

233:39

the card footer over here now I've used

233:42

these react fragments over here because

233:43

this is where we will be having a

233:47

dialogue for our results right so we

233:50

will come back to this first let's build

233:52

this card for the card title and

233:54

description I'm going to say recent

233:56

quizzes and let's provide it gradient

233:58

title text 3 Exel and in the larger

234:00

screen text 4 XEL and the description

234:02

will be review your past quiz

234:04

performances let's see how this looks uh

234:07

what's wrong oh we are using hooks over

234:09

here so this should be a use client

234:12

component and now let's see okay yeah

234:15

recent quizzes review your past quiz

234:17

performances and also what we want to

234:20

display over here is a button to start

234:21

new quiz right so I'll have a div and

234:24

wrap both of these in this div and I'll

234:27

have a button after it and then button

234:30

will simply say start new quiz and on

234:32

click we will say router. push and push

234:34

it to/ interiew SL mock let's see button

234:37

is not defined obviously let's import it

234:40

from Shad CNC okay so we want it to be

234:43

this side right here right so over here

234:45

in the card header I'm going to say

234:47

display Flex items to be Center and

234:48

justify between so that they are on Far

234:51

ends okay I think we need to do Flex row

234:55

over here as well yep something like

234:58

that start over here in the card content

235:00

we will be rendering all of our

235:02

assessments so instead of this paragraph

235:05

tag I'm going to have a div with the

235:07

class name of space y to be4 and here

235:10

I'll take the assessments do map and

235:13

over here

235:15

I'm going to render each and every

235:16

assessment I'll take the assessment and

235:18

the index and here I'll say return and

235:22

let's just take a card component over

235:24

here again so I'll just copy the card

235:27

component and paste it right here let's

235:29

get rid of the footer again in the card

235:31

title I'm going to say quiz whatever the

235:33

number of the quiz is right I + one in

235:36

the description let's just have two

235:39

things first thing will be the score of

235:42

that quiz and when that quiz was

235:45

conducted right so I'm going to say

235:46

under with the format from date- FNS and

235:50

new date whatever the date is and I'll

235:52

format it in this format right here

235:54

right let's see yep we can see all of

235:57

our quizzes being rendered right here

236:00

cool over here in the car description

236:01

I'm going to say display Flex justify

236:03

between and width to be full so that

236:06

these dates are right over here inside

236:08

the card content simply let's just

236:10

display our Improvement tip right so

236:12

that this is easily accessible so I'll

236:13

say as assment do Improvement tip with

236:16

text small and text muted foreground so

236:18

yeah this looks good we can easily see

236:20

these right here and now let's add the

236:22

logic for having the dialogue so first

236:25

of all let me just add some hover effect

236:27

on it so on the card on each card I'll

236:30

say cursor pointer on Hover we'll say

236:32

background muted to be 50 opacity and

236:35

transition will be added on the color so

236:38

y something like that on click we want

236:41

to select that particular quiz on inside

236:43

of this state right here right so I'm

236:45

going to say on click set selected quiz

236:47

to be that particular assessment and

236:49

obviously we need to provide the uh key

236:51

over here as well since we're doing the

236:52

map right so Al key equals assessment.

236:55

ID okay so let's see now how does the

236:58

dialogues work inui so I'll go over here

237:02

in the dialogue and if you click on edit

237:04

profile you can see it's like a model

237:06

pops up just like this so let's copy

237:10

this dialogue up and I'll go back and

237:14

right here I'm going to paste this

237:15

dialogue code so we have this dialogue

237:18

header and a trigger which you know

237:20

opens the dialog I guess we won't be

237:22

needing a trigger because our triggers

237:24

are right here and we will make sure to

237:26

open the dialogue when we have something

237:28

inside of this selected quiz right and

237:30

if we close this then we will remove

237:31

everything inside of the selected quiz

237:33

so I'll say on open change set selected

237:35

quiz to null simple as that let's try it

237:37

out so obviously we need to import uh

237:40

this dialogue as well so make sure to

237:42

import from slash comp components dialog

237:46

header dialog title we won't be needing

237:49

the description so let's get rid of it

237:51

and let's see how it looks I have not

237:54

imported alert dialog header okay let's

237:56

import that as well and now check if I

237:59

click on this quiz yep you can see we

238:01

are rendering it over here let's instead

238:05

of this alert dialogue header let's just

238:08

take the simple dialog header right

238:10

let's import it from Shad CN UI and

238:12

remove this alert dialog header so we

238:16

actually accidentally imported from

238:18

another component and we won't be

238:20

needing any title over here actually and

238:23

this is important to keep this tag over

238:25

here because shat seni might throw us

238:27

some errors if we don't provide it off

238:29

the accessibility right so now we will

238:31

just simply we would need the quiz

238:33

result component because that is what

238:35

we're supposed to render over here right

238:37

and here we will give the result which

238:39

is selected quiz on start new we will

238:43

push it to sl/ Mock and we will also

238:46

provide the hide start new so you might

238:48

remember we added this flag over here

238:50

right so it was for this place hide

238:53

start new and now we won't be seeing

238:55

start new quiz button over there so if I

238:57

click on any of these Yep this is

239:00

breaking for some reason I think we need

239:02

to add some styling over here in the

239:04

dialog content I think it's because of

239:05

this so I'll simply say Max WID to be 3

239:08

XL Max height to be 90 VH and overflow y

239:11

to be Auto so we can see the complete

239:13

result on this screen itself so if I

239:15

click on it now yep looks beautiful and

239:18

you see how awesome this feature is the

239:21

complete entent feature I mean this

239:22

feature in itself is a whole app right

239:25

but this is a part of our complete

239:27

Sensei app so great then let's move on

239:30

to the next big feature which is to

239:32

build our resume we will start by

239:35

creating the server actions for it so

239:36

I'm going to come to this actions folder

239:38

over here and I'm going to create a new

239:39

file called resume. JS and see most of

239:42

the things in this are going to be

239:44

performed in the front end part because

239:46

we will be building a Resume Builder and

239:48

all all of those these things is are

239:49

going to be on the client right but

239:51

after we have built the resume we want

239:54

to save that rume right so we will

239:56

create This Server action export ASN

239:58

function save rume and we will provide

240:00

it with the markdown content to save the

240:02

resume so cool let's start with simply

240:05

user authorization right if user is

240:08

logged in or not I'm going to import the

240:10

AU from clerk /n/ server and I'm going

240:14

to import this DB from Prisma file now

240:17

after this there can be a possibility

240:19

that uh rume already exists inide of our

240:21

database right for that particular user

240:23

so we'll be using uh a function called

240:25

upsert so let me show you so I'm going

240:27

to say con resume equals a wait db.

240:31

resume. upsert so basically this means

240:34

update or insert right whatever's

240:37

suitable first of all I want to search

240:38

the resume for that user so I'm going to

240:40

say where user ID is user. ID if rume

240:43

already exist we are going to update it

240:45

with this content just update the

240:47

content and if it does not exist we will

240:49

create for that particular user ID and

240:51

we will insert the content simple enough

240:54

and then we will refresh all of the data

240:56

inside of the/ resume path so I'm going

240:58

to say revalidate data let me just

241:00

import it from next SL cach and then in

241:03

the cat I'm going to throw the error

241:05

error saving resume with error do

241:08

message now similarly we will create a

241:10

function to get a rese if a res is

241:12

already created right

241:14

so it will be a very simple function so

241:16

let me just bring it real quick we will

241:18

just first check if user is logged in or

241:20

not and then I'm going to Simply say

241:22

await db. res. find unique where user ID

241:25

is simple enough right now for the third

241:28

thing let me show you if I go back to

241:32

the deployed app and you can see I'm in

241:33

this Resume Builder feature and I have

241:36

my rume right here if I go to form and

241:40

let's say if I want to add a work

241:42

experience over here right I'm going to

241:44

say frontend developer organization can

241:49

be let's say Google date and whatever

241:52

you can set these on your own and then

241:55

if I want to add the description let's

241:56

say if I worked on creating a Chrome

241:59

extension right or let's say basically a

242:01

Chrome browser I worked on Chrome

242:05

browser in Google right so now we are

242:09

blanked right what do we write in your

242:10

resume so we can add this feature of

242:13

improving with AI so if I click on this

242:15

button see it has improved this

242:18

description with respect to the uh you

242:20

know our the little description that we

242:22

have provided it so this is an awesome

242:24

feature let's try to build this right so

242:26

I'll go back to my app and I'm going to

242:28

create a new server action over here

242:31

called improve with AI now in our

242:33

current application I have added this

242:36

feature just for this description right

242:39

here right improve with a and I've left

242:41

this professional summary like this can

242:43

also be improved with AI right so

242:45

professional summary or if you want you

242:46

can add it in the skills as well so I

242:48

would highly encourage you guys to

242:50

follow the similar patterns to implement

242:52

it over here as well right so but it's

242:55

pretty simple let me show you how you

242:57

can do that so first of all obviously we

243:00

need to check if user is logged in after

243:02

that we want to write the prompt for it

243:05

so you know what uh instead of writing

243:06

it out over here let me just go back

243:09

into my GitHub repository and let me

243:11

copy this whole prompt if you want you

243:12

can also copy it from right here or of

243:14

course you can also add your own

243:16

variation to it so yeah this is the

243:17

prompt as an expert resume writer

243:20

improve the following we're going to

243:22

provide the type like if it's for the

243:24

experience if it's for the project if

243:26

it's for the education right this

243:28

feature is on all of these three places

243:30

so over here education projects all of

243:33

these have the Improv with AI so we'll

243:35

provide the type for the description for

243:37

a user who is in this industry which

243:39

let's say for example software

243:41

engineering or front end developer Etc

243:42

right make it more impactful

243:44

quantifiable and aligned with the

243:46

industry standards and then we will

243:47

provide the current content that user

243:49

has provided then the requirements are

243:52

following use action verbs include

243:54

metrics highlight relevant technical

243:56

just like we should be writing a resume

243:57

description right so this will help us a

243:59

lot in building a resume and format the

244:02

response as a single paragraph without

244:03

any additional text or explanation

244:05

simple enough and then after this let's

244:07

make an API call to Gemini right so let

244:10

me just uh do one thing let me bring in

244:13

my import for the Gemini yep these two

244:15

things and I'm going to put them on the

244:18

top right here right let's import this

244:21

Google generative AI over here and then

244:23

I'm going to use this model variable to

244:26

call it so inste of the try I'm going to

244:28

actually just go back and simply do what

244:30

we have already done right so yeah this

244:32

thing right here let me just copy it up

244:34

and I'll paste it right here so const

244:36

result equals model do generate content

244:38

then result do response and then I'll

244:41

get the text and actually I'll just say

244:43

dot trim if there's any spacing outside

244:46

of it let's call it improved content let

244:49

say return improved content all right

244:52

and in the catch block simply I'm going

244:54

to throw the error error improving

244:55

content if there is any error that's

244:57

going to happen right so yeah these

245:00

three are my server actions now let's go

245:03

to inside of this app folder Main and

245:08

yeah we have not created for resume so

245:10

I'll say resume and I'm going to create

245:11

a page doj SX right here instead of it

245:15

I'm going to say R A fce let's call it

245:18

resume page and now over here if there's

245:21

any resume pre-existing I'm going to

245:23

fetch it so I'll say const resume equals

245:27

a wait await get resume so this F

245:31

function that we just now created server

245:33

action make sure to make it an

245:35

asynchronous component since this is a

245:37

server component and yeah we will get

245:39

the info right here obviously does there

245:41

is no resume right now so what I do

245:44

instead of this resume page I'm going to

245:45

go inside of it and create a component

245:47

called resumé Builder again this will be

245:50

a client component so that we can use

245:52

the hooks and stuff inside of it let's

245:53

get a new folder over here underscore

245:55

components and I'm going to create a new

245:57

file resume builder. jsx now this is a

246:02

very you know logic heavy component so I

246:05

need you guys to focus properly we will

246:07

be sending this the initial content so

246:10

I'll say initial content oops contenter

246:14

this I'll say resume dot content right

246:18

I'll put a optional chaining over here

246:20

just in case if our resume does not

246:22

exist which currently it obviously does

246:23

not exist for this div I'm going to

246:25

Simply give class name container margin

246:28

horizontal to Auto and padding vertical

246:30

to six also since we are you know

246:33

loading the resume right here I would

246:35

recommend you guys to add a layout file

246:38

just like we have added right here or

246:41

like um it's pretty simple right you can

246:42

just copy it

246:44

and paste it right here inside of it

246:46

right simple enough and now it will show

246:48

a bar loader whenever this rume is being

246:51

loaded right here let's import this rume

246:53

Builder component am I not exporting oh

246:56

sorry R fce Resume Builder and I'll take

247:01

the

247:02

initial content right here well let's

247:05

just import it right over here like this

247:09

and go back and see yep we can see the

247:11

res Builder right here okay let's go

247:12

inside of our Resume Builder component

247:14

and start building our Resume Builder

247:16

first of all this will be a client

247:19

component so I'm going to say use client

247:21

directive over here so first of all

247:23

inside of this div I'm going to have

247:25

another div which will contain our H1

247:29

Resume Builder just like we've been

247:31

doing up until now I'm going to give

247:33

this the class name font bold gradient

247:34

title text to be 5 XEL in smaller

247:36

screens in the medium screens it's going

247:38

to be 6xl below this I'll have a div

247:41

which will contain our buttons like

247:43

saving the resume or you know

247:45

downloading the PDF Etc so I'll say

247:48

button import it from shat CN UI this

247:51

will be save and I'm going to have an

247:54

icon before it save icon from Lucid

247:56

react let's see how it looks yep

247:58

something like this let's give it the

248:00

variant of destructive so that it's red

248:02

color let me just duplicate this button

248:04

right here and this one will before

248:07

downloading the PDF and let's import

248:09

this download button from Lucid react

248:10

something like this and I don't want

248:13

this to have a destructive variant this

248:15

div can have a class name of Space X

248:18

tob2 and this parent div for both

248:20

heading and buttons can have display

248:22

Flex Flex column but in the larger

248:24

screens it's going to be Flex row that

248:25

is on one single row justify between so

248:28

at the AR far ends item Center and GAP

248:30

to be two so they would look something

248:32

like this parent div can be class name

248:35

space y to be four now below this div

248:37

right here we will have two tabs so you

248:40

may have already seen over here we have

248:42

two tabs one one for form one for

248:44

markdown so we have already installed

248:45

the tabs component from chat CN UI so it

248:48

looks something like this let me just

248:51

copy it up and paste it right here so

248:53

basically what's going on over here is

248:55

we have this tabs uh parent tag imported

248:58

from components and then we have tabs

249:00

list one for account one for password

249:02

for an example over here when we click

249:03

on account this value account matches

249:06

this value of tabs content and it

249:08

renders this component else it will

249:10

render the other component let me show

249:11

you let me just import all of these from

249:13

SL components folder tabs content and

249:17

yeah I think all of them are imported

249:19

now let's see y you can see account

249:22

password looks good instead of these two

249:25

I'm going to have form and markdown and

249:29

default value can be form but you know

249:31

what we don't want a default value

249:34

because that will differ right if we

249:36

already have a resume we will show the

249:38

markdown tab else we will show the form

249:39

tab let me get rid of this class name

249:41

over here as well and and let's just

249:43

create a separate State for the active

249:47

tab right so I'll just put this active

249:50

tab State over here let's import U State

249:52

and by default I'm going to put it to be

249:54

edit and right here I'm going to say the

249:57

value is going to be active tab on value

249:59

change we will use this set active tab

250:01

so this one can be edit and this one can

250:04

be preview let's check it out form and

250:08

markdown okay so now let's first go on

250:10

and build this form tab right so so for

250:13

forms obviously we are using react hook

250:15

form and zort so I'm going to import the

250:17

use form hook over here and this for

250:20

this we will need to create the schema

250:22

as well right so I'm going to go to this

250:24

lib schema. JS file and inser of this

250:27

let's see first what are all the

250:28

different things that our form will

250:31

contain so we will have this contact

250:34

information then professional summary

250:36

skills and for each and every one of

250:39

these this will be an array right we can

250:41

add a work experience then we can add it

250:43

then we can add another work experience

250:44

right something like that so this has to

250:47

be an array so I'll create a separate

250:48

schema for this separate schema for this

250:50

and then I'll combine them in one single

250:51

schema so first of all for contact

250:53

schema I'm going to say export cons

250:55

contact schema Z doob and we will keep

250:58

four things over here let's just keep

251:00

email as required only and other things

251:03

as optional so z. string email and if it

251:07

it's not provided I'm going to say

251:08

invalid email address and for mobile

251:10

LinkedIn and Twitter all of these three

251:12

will be optional now let's understand

251:13

the entry schema we can call it like

251:16

these these ones right let's build these

251:19

so export con entry schema do object and

251:22

inside this we'll take an object what

251:24

are the different things that we are

251:25

going to be having inside of it uh title

251:28

organization start date end date we can

251:32

have a checkbox for current experience

251:34

and we can add the you know check to see

251:37

if this is selected we won't be

251:38

requiring this or if if this is added no

251:41

need to enter this right so and yeah

251:44

also description right so we would need

251:47

all of these things so it would look

251:48

something like this title it can be a

251:51

string minimum one character else title

251:53

is required same for organization start

251:56

date is going to be minimum one

251:57

characters as the start date is required

251:59

end date can be optional description and

252:03

the current right which will be a

252:05

Boolean now let's add the check so I'm

252:07

going to say refine over here and refine

252:10

will help us to add some you know checks

252:13

over here if it's working properly or

252:14

not so inside of this call back I'm

252:16

going to take the data that we have

252:18

received and simply I'm going to say if

252:20

data do current is not present and data.

252:24

end dat is also not present then we will

252:26

return false that is we will throw the

252:28

error else if either of one is present

252:30

I'm going to say return true and how do

252:32

we throw the error after it so I'll say

252:34

comma and inste of an object I'm going

252:37

to say message and date is required

252:39

unless this is your current position

252:41

right and we will throw the err on the

252:43

end it like below end it if none of

252:45

these are

252:46

selected yeah and uh then in the end

252:49

let's combine this one and this both of

252:51

these schema into one single schema so

252:53

I'll say resume schema equals z doob

252:56

first I'll add the contact info contact

252:58

schema then summary

253:01

skills experience all of these will be

253:03

z. array and we'll provide this entry

253:05

schema that we have created just over

253:07

here right simple enough let's take this

253:09

rese schema go back to our rese Builder

253:12

inside of use form form I'm going to say

253:14

resolver equals to Zord resolver import

253:18

it from uh this hook for/ resolver Zod

253:21

and inste of this I'm going to give this

253:23

resume schema make sure to import this

253:25

as well and then we can provide some

253:27

default values to our form which I'm

253:29

going to say contact info to be empty

253:30

array sorry empty object summary to be

253:33

empty skill to be empty and all of these

253:34

to be an to be empty arrays yep and just

253:37

like before we will take out a few

253:39

things from inside of it like control

253:42

register so we did not uh you know took

253:45

out earlier so I'll explain you what

253:47

this is all about so register handle

253:49

submit to you know submit the form watch

253:51

to watch a particular field inside of

253:53

our form or multiple Fields as well and

253:55

from the form State we will take out the

253:57

errors to display the errors now this

253:59

control basically helps us to

254:02

essentially take the control of the

254:04

whole form and we can manipulate it

254:06

using this variable right here and I'll

254:08

show you how we are going to be using it

254:10

and now while we are at it let me just

254:12

take our a API over here as well so I'm

254:14

going to say use fetch import use fetch

254:17

I'll take the save resume as well which

254:20

will enable us to save the resume when

254:22

we submit the form and we will take out

254:23

loading function data and errors and

254:25

rename all of them one by one cool now

254:29

as we are going to be uh you know

254:31

writing inside of our form right we'll

254:33

be entering some data over here right

254:36

like something like this we will be

254:38

updating our markdown in real time right

254:41

so for that we need to watch all of of

254:43

the form Fields so what I'll say I'll

254:46

say const form values equals watch right

254:49

now we will make use of it very soon and

254:51

also if there has been the initial

254:54

content provided to us right if a resume

254:56

already exist then we can say we'll have

254:58

a use effect over here make sure to

255:00

import it from react I'm going to say if

255:01

initial content is there then the SE

255:03

active tab will be previewed right that

255:06

means we will go to markdown tab

255:08

directly without going to the form okay

255:10

and obviously I'll put it in the

255:12

dependenc area because because if it

255:13

changes then this changes as well all

255:15

right now let's go on and first start

255:17

building our form so I'll go down inside

255:20

of this tab content value edit and I'll

255:23

say form over here inside of this first

255:26

of all we will be taking the contact

255:28

information so let's create the dev for

255:30

that I'll say H3 to be contact

255:32

information then after this I'll have

255:34

our div which will contain four

255:36

different things like four different

255:38

inputs so the first one will be label

255:41

email and the input let's import input

255:44

from Shad CN UI we will use register

255:46

over here obviously to tie it up with

255:48

the contact info schema so contact

255:50

inside the contact infos schema I'm

255:51

going to go and tie it up with the email

255:53

right and I'm going to say type email

255:55

some placeholder over here and error

255:57

equals errors. Conta info. email if you

256:00

remember this errors object comes from

256:02

right here right and after this let's uh

256:05

display our errors as well just like

256:07

we've done earlier errors. Conta info.

256:09

email if it exists then we will show

256:11

inside of a P tag this this exact error

256:13

message with the text at 500 and text

256:16

small let's provide some Gap in between

256:18

of those I'll say space Y tob2 and since

256:21

there are going to be four such divs

256:23

over here so actually we should be

256:26

wrapping them in another div over here

256:28

so I'll have a div I'll wrap this whole

256:31

thing in another div and for this div

256:34

right here I'm going to say class name

256:36

to be display grid in the smaller

256:38

screens we show one single column in the

256:41

medium screens two column Gap to be four

256:43

between them some padding four around

256:45

them some border rounded Corners are

256:49

going to be large like back uh border

256:52

radius background is going to be muted

256:54

with 50 opacity right let's see how this

256:57

looks currently inside of our app server

256:59

only cannot be imported okay so I

257:02

believe we have not added yeah use

257:04

server directive over here so I'll say

257:07

use server and save it now we should not

257:09

see the error yep something like this

257:12

cool let's build the other contact

257:13

information so I'll actually duplicate

257:16

this one three times 1 2 3 okay let me

257:20

provide some gap between these and for

257:23

the second one this will be for mobile

257:25

number right so I'm going to Simply say

257:28

mobile number in the label and in the

257:30

input this will be contact info do

257:32

mobile with some with the type of

257:33

telephone and some placeholder over here

257:36

in the errors instead of email I'm going

257:38

to say mobile then next this one will be

257:41

for LinkedIn URL again same contact

257:44

info. LinkedIn and change this error

257:47

over here as well then the last one will

257:49

be for the Twitter account so I'll say

257:52

Twitter or X profile I'll say contact

257:55

info. Twitter and I'll provide some

257:56

placeholder and the errors as well cool

258:00

then after this Dev we will have the

258:03

professional summary and again it would

258:05

look exactly the same so I'll just

258:07

quickly import it it's just a Dev with

258:10

the ag3 of professional summary and now

258:12

over here this is something that you

258:13

need to understand so when it comes to

258:16

react hook forms or react hook form it

258:19

works fine with the native HTML tags

258:22

right but when it comes to such third

258:25

party components like text area which is

258:27

provided by you know shaten UI or

258:30

probably like SEL it component or

258:31

something like that we need to wrap it

258:33

inside of this controller component

258:35

which comes from react hook form right

258:37

so we will name it summary with respect

258:40

to what it was in our schema then we

258:42

need to provide the control like this

258:44

control if you remember we took it from

258:46

right here from our form right so this

258:48

will help it to get the control of the

258:50

form then in the render this is where we

258:53

can render the component in our case

258:55

this is text area for writing the

258:57

professional summary and this gives us

258:59

this field over here which we need to

259:01

spread over here so it this takes the

259:03

control of this text area then we can

259:05

simply give some class name placeholder

259:07

and error to be errors. summary and

259:10

simply render the errors in the end

259:12

let's see how it looks text area is not

259:14

defined obviously we need to import it

259:16

as well yep something like that let's

259:18

just give the parent if some class so

259:20

that we have some gap between them so

259:23

this one I'm going to say class name to

259:24

be space y to be four and our form to

259:27

have space y to be8 and also we will

259:31

have an on submit over here right which

259:33

will give which we will give it handle

259:35

submit Ander this we will provide the on

259:37

submit form which sorry on submit

259:40

function which does not exist so let me

259:43

just create a dummy function for now

259:45

just like this let's make it an

259:46

asynchronous function which will get all

259:48

of the form data okay so now after where

259:53

is it professional summary we need to

259:55

add the skills but let's see how it

259:56

looks currently yep something like that

259:59

this looks much better so that one will

260:01

also be a text area so what I'll do I'll

260:03

just copy it and paste it right here

260:06

instead of professional summary it will

260:08

be skills name is going to be skills

260:11

over here we can say list your key

260:13

skills and in the error as well instead

260:16

of summary I'm going to say errors.

260:18

skills now after this we will render The

260:20

Experience projects and education part

260:23

right where we we can add multiple

260:25

experiences or you know skills Etc sorry

260:28

not skills I mean projects Etc so simply

260:31

it will be uh just like what we have

260:34

done over here as well so I'm just going

260:36

to copy it and paste it at here and

260:38

notice what I'll do so we won't be

260:39

rendering text area of course we will be

260:41

rendering a custom component over here

260:44

so first of all this will be called as

260:46

work experience let's say experience and

260:49

then in the errors as well I'm going to

260:50

say experience after this we will be

260:52

doing the same thing for the education

260:55

and the projects as well so let me just

260:58

duplicate it multiple times so I'll

261:00

paste it right here and then Gap paste

261:02

it right here obviously this will give

261:03

us error since we don't have anything

261:05

over here so the second one can be

261:08

education education over here as well

261:10

and over here as well for the third one

261:13

instead of this I'll say projects and

261:15

over here as well okay so what do we put

261:18

inside this render we will be creating a

261:21

separate component a new component

261:23

called entry form where we'll be writing

261:25

the logic for this thing right so let's

261:27

just create a a component right here I'm

261:30

going to create a new file entry Das

261:33

form. jsx R A fce entry form and then

261:38

inside of this we will take three things

261:40

the type all of the entries that we have

261:42

and on change what happens right so we

261:45

will be controlling this component

261:46

obviously using uh use form as well and

261:48

also we will be using that improve with

261:51

AI logic inside of this entry form as

261:53

well now over here first of all let's

261:55

create our use form just like we did

261:57

earlier so I'll import use form from

262:00

react hook form Zord resolver and

262:02

obviously entry schema that we have

262:05

created separately right here right then

262:07

we will provide some default values to

262:09

title organization started ended etc etc

262:12

right and we will take out the register

262:15

handle submit form State reset watch set

262:18

value and all that over here as well and

262:20

I'll rename this handle submit to handle

262:22

validation because simply this will help

262:25

us in validation only right not

262:26

submitting the form that's why this

262:28

makes more sense and I'll also watch

262:30

this uh current field so that we can

262:33

disable the end date field let's import

262:36

this right here so first for the work

262:38

experience I'm going to say entry form

262:40

type experience entry field. value and

262:43

on change field.on change same for the

262:46

education just type education and for

262:49

the project as well with the type

262:52

project okay let's go back to the entry

262:55

form and let me just first see if

262:56

there's any error or not so yeah we can

262:59

see all these three right here so first

263:01

thing first we need to have a button

263:03

over here which will be responsible for

263:05

adding the you know whatever experience

263:07

and stuff and we need to have a state as

263:10

well which will tell us that if a new

263:13

experience or project or education is

263:15

being added currently so what I'll do

263:18

I'm going to say is adding and let's

263:20

take use State from here and let's make

263:24

it a client component so say use client

263:27

and now I'm going to say if is adding is

263:30

not true then only we will show this

263:32

button and on click we will say set is

263:34

adding to True right now above it we can

263:37

add the form when is adding is true we

263:40

can display that form right so now above

263:42

this button I'm going to say if is

263:44

adding is true then we will you know

263:47

let's add a card component over here so

263:49

let's just take the card from Shad CN UI

263:53

yep over here and paste it right here

263:55

let me import the card card header we

263:58

not going to be needing the card

264:00

description card content and also import

264:02

card footer as well okay so card title

264:05

can be add and the type like whatever it

264:07

fits Experience Project Etc in the card

264:10

content we can create our form so this

264:13

can have a class name of space y to be

264:15

four inste of it I'm going to have a div

264:18

which will contain it and then separate

264:19

divs for things like title organization

264:22

etc etc so inside of it I'm going to

264:25

have a div first of all for the input of

264:28

title /os we will register it with our

264:31

hook form with the title in the schema

264:34

right so error will be errors. title and

264:36

then error St title if it's there an

264:37

error then we're going to display the

264:39

error right here then below it I'm going

264:41

to have another d similarly for

264:44

organization as well and I'm going to

264:45

register it along with the errors and

264:48

these both will be inside of one single

264:50

div right here so I'm going to say class

264:52

name display grid grid columns to be two

264:55

and some gap of four between them so

264:58

let's see how it looks button is not

264:59

defined okay let's import this button

265:02

from over here plus circle is not

265:04

defined okay yeah I have not imported

265:06

this let's click on ADD experience now

265:09

and yep we can see title position

265:11

organization company ET Etc okay now

265:13

below this div we will have another

265:16

similar div but that one will be for you

265:18

know our start date and end date so

265:21

again similar class name so I'll just

265:23

take this grid class name and I'll put

265:26

it right here and I'll put it right here

265:29

then insert this div first of all I'm

265:31

going to have a div for type month input

265:34

type month and register with the start

265:35

date and similarly I'll have another div

265:38

I'll just duplicate it below it and I'm

265:41

going to have this for

265:42

and date but this one will be disabled

265:47

if the current is enabled so if you

265:48

remember this current is watching this

265:50

current checkbox right if this checkbox

265:53

is ticked then end date will be disabled

265:55

and we will be creating that checkbox

265:58

right below it so I'm going to have a

265:59

div and input inside of it of type

266:02

checkbox ID is going to be current

266:04

register current onchange we will set

266:07

the value like manually setting the

266:09

value inside the hook form for the

266:11

current field to be e. target. checked

266:14

and if it is checked then I'll say set

266:16

value of end it to be empty right then

266:17

we don't want to have an end it over

266:19

here and of course we're going to have a

266:21

label called current besides the

266:23

checkbox let's see how this looks so far

266:26

if I click on over here yep you can see

266:27

this is disabled now we cannot select it

266:29

now below it we need a description as

266:31

well again exactly the same just like

266:33

what we've done until now we're going to

266:36

have a d with text area placeholder

266:38

description of your whatever you know

266:40

experience or project Etc class name

266:43

height 32 register with the description

266:46

error errors. description and we will

266:48

render the errors over here as well

266:50

let's see text area is not defined if I

266:54

click on ADD experience yep we can see

266:55

if I click on ADD education we can see

266:57

all the things related to education

266:58

let's add a button for you know

267:00

improving with AI but actually before

267:02

that let's just uh import that API right

267:06

here that we created improve with AI API

267:09

or server action whatever you want to

267:10

call it so I'll take the use fetch hook

267:13

and improve with AI so this will have

267:15

loading function data and error let's

267:18

also have a function for handle delete

267:22

which we will come back to very soon

267:24

which will enable us to delete uh you

267:26

know the experiences or the projects or

267:28

education we will also have a function

267:31

for improving our description with a so

267:34

I'll say handle improv description and

267:36

another function for handle add as well

267:39

right to add the experience education of

267:41

projects and while we are at it let's

267:43

just write this handle improv Des uh

267:45

description function right away so it

267:48

will be very simple uh let's just it

267:50

will be an asynchronous function and

267:52

start of this I'm going to Simply say

267:54

take the description like I'm I'm going

267:55

to watch the descriptions value we will

267:57

have the descriptions value inside of it

267:59

and then I'm going to say if description

268:00

does not exist I'll say toast error

268:01

please enter a description first you

268:03

know before trying to improve it with AI

268:06

then after that I'm going to say await

268:08

improve with AI FN this thing right here

268:11

I'm going to call it with two things

268:13

first of all the current description

268:16

right in the current field and what the

268:18

type is right that is experience

268:20

education or project let's render the

268:22

button now so I'll go right over here

268:25

yep text area and right below the text

268:28

area Dev I'm going to have a button of

268:30

type button sorry we don't submit

268:32

anything like not submit the form over

268:34

here in the Resume Builder variant is

268:36

going to be ghost size is going to be

268:38

small on click we will call that handle

268:40

improve description that we just now

268:42

wrote it will be disabled when the

268:44

description is being improved so is

268:46

improving is like loading is going on or

268:48

we are or we don't have the description

268:50

over here and we will display the

268:53

loading indicator when it's loading

268:55

using the loader to so make sure to

268:57

import it from Lucid react and we will

269:00

also import the Sparkles icon to improve

269:03

with AI let's try it out if it's working

269:05

or not so let's just say same thing

269:08

Google sde even though these two things

269:10

does not matter say I worked on Chrome

269:16

browser let's click on improve with AI

269:18

okay improving and this should generate

269:20

a description for us which it did not

269:23

let's see let's open the network Tab and

269:25

try again improve with AI it did

269:27

something yeah you can see we are

269:29

getting the uh no when oh sorry it

269:32

should be in the preview developed

269:33

Implement oh yeah we are getting the

269:34

response but we are not able to see it

269:37

right here I think I have missed

269:39

something oh yeah I have to add a use

269:42

effect over here inside of this we will

269:45

take the data from the API right

269:47

improved content so inside of the use

269:50

effect I'm going to say if we get this

269:52

uh improved content right here first of

269:53

all over here in the dependency area we

269:55

need to add a few things like improved

269:57

content only then this will run or

270:01

improve error or is improving or set we

270:06

don't need actually this one so yeah

270:08

these three things if any of these three

270:09

things changes then we will say if

270:11

improved content has something and it is

270:13

not loading anymore then we will set the

270:15

value of the description and I'll show

270:16

the toast. success otherwise if there's

270:19

any error I'll show toast. error fail to

270:21

improve description let's check it out

270:23

now let's just say I worked on Chrome

270:27

browser if you want you can also you

270:29

know Supply the name of the company as

270:31

well I think that would be much helpful

270:34

okay toast is not defined import the

270:36

toast one more time let's click on

270:38

improve with AI and now it should work

270:41

yep just like like that awesome and

270:43

again I would recommend you guys to add

270:45

like send this company name to the API

270:47

as well you just have to you know send

270:49

it from over here and make changes in

270:52

this API inside of this right here you

270:54

have to take this spam over here and

270:56

provide it to the prompt very simple I

270:58

believe you guys can do it on your own

271:00

all right now how do we add this uh to

271:02

our form add this like particular item

271:07

for the experience and all let's add two

271:09

buttons inside of this card footer first

271:12

one will be for cancelling so when we

271:14

click on cancel we will reset the form

271:16

and set is adding to false this will be

271:18

of type like variant outline and type

271:20

button then another one we will had have

271:23

the add entry button which will trigger

271:26

this handle add function that we have

271:27

created but not added any logic inside

271:29

of it and we will say add entry let's

271:31

import this yeah plus circle is already

271:33

imported so let's check it out yep

271:35

something like this let's give this some

271:37

class name to be displayed at the very

271:39

end so I'll say display Flex justify end

271:41

and Space X to be two so this will yeah

271:43

appear right here now when we click on

271:45

ADD entry we want to add it right so

271:48

let's go to handle add function over

271:51

here and first of all we want to format

271:53

the data so I'm going to save and by the

271:56

way since we are submitting this right

271:57

so let's wrap this in handle validation

272:01

or this handle submit function that we

272:03

took right here right so that we get the

272:04

date like access to the data of the form

272:07

then I'm going to say const formatted

272:09

entry insert this we're going to have

272:10

the object which will take data and then

272:13

let's format the date right the start

272:16

date and the end date so for that I'm

272:18

going to create a function right here a

272:22

helper function so I'll say const

272:24

format display date this will be a

272:27

function obviously which will take a

272:30

date string andert this first of all

272:33

I'll check if date string does not exist

272:35

return empty but if it does I'm going to

272:38

take this pass from date- FNS and pass

272:41

this date string in this format right

272:43

here and then return I'll like import

272:46

this format from D- and return it in

272:49

this like month and whatever 2024 Etc

272:52

okay let's go back to this format entry

272:55

and here simply I'll take the start date

272:57

and end date and I'll use this format

272:59

display date and provide it with the

273:02

data. start date and obviously if the

273:04

current is true then we won't be needing

273:06

the end date right else we will provide

273:08

the end date as well after this we would

273:10

get this on on change function over here

273:12

right so if you remember if I go back we

273:14

get this onchange field. on change which

273:16

will enable us to add this to our main

273:18

form which is inside this Resume Builder

273:20

so after this I'm going to say on change

273:23

whatever the entries are already I'll

273:26

provide it and then after that formatted

273:28

entry and then reset the form set is

273:30

adding to be false after this after

273:32

handling the addition we need to render

273:35

all of these fields over here as well

273:37

right so above this I'm going to map

273:39

through all of the entries so let let's

273:42

just have a div over here and for this

273:44

parent div I'm going to say class name

273:46

space y24 and this div as well space yb4

273:49

and inside of it we will simply just you

273:51

know map through all of the entries that

273:52

we have inside of it so I'll say entries

273:56

do map and here inside of this call back

273:59

we will just have a card component so

274:02

again let's go back to shaten UI and

274:05

take this card component and I'll paste

274:07

it over here make sure to add return

274:09

over here I'll say key to be index

274:12

obviously we need to take the index from

274:14

here and also each and every entry so or

274:17

each and every item so item and index

274:19

for the card title I'm going to say this

274:23

title of the user at the organization

274:26

whatever companies or whatever the

274:27

project that you're building for right

274:29

let's remove this

274:31

description and the footer let's import

274:34

all of these things I think they are

274:36

already imported since we have used them

274:38

in other places below this I will have

274:40

the option to delete them right so I'll

274:42

have a button variant outline size icon

274:44

type button and on click we will trigger

274:47

this handle delete function which we

274:48

will come back to this very soon and

274:51

let's import this x icon from Lucid

274:53

react then inside the card content

274:55

simply we will just render item do

274:57

current if this is true that is if this

274:59

is a current organization then I will

275:01

render the date from start date to

275:02

present else we render from start date

275:04

to end date and obviously the

275:07

description that they've written for

275:08

that particular experience education or

275:10

project for this header let's give this

275:13

some class name of display Flex Flex to

275:15

be row so there are one single line

275:18

items to be Center justify between so

275:21

that they are on Far ends Spacey to be

275:23

zero and padding bottom to be two

275:25

between them so that we have some Gap

275:27

and I think this should render it let's

275:28

just quickly go over here and handle it

275:31

and write the logic so this will simply

275:32

take the index right so if you see we

275:35

are taking the index over here right and

275:37

it will take the index and it will say

275:38

con new entries and it will simply

275:40

filter out that particular Index right

275:42

if index is not equals to this index

275:44

only then return else remove it and on

275:46

change we will add these new entries

275:49

let's check it out I'm going to add

275:51

let's say XYZ XYZ

275:54

XYZ description XYZ org let's just say

275:58

I'm going to select any random month

276:00

current experience and click on ADD

276:01

entry okay there we go it has been added

276:03

if I click on X yep it is removed from

276:06

over here as well awesome so we have

276:08

successfully built this form right here

276:11

now let's render this form and this

276:14

markdown and add the logic to save our

276:16

resume inside of our database as well in

276:18

the markdown format so for doing that we

276:20

will be using this package right here

276:22

react MD editor and this will allow us

276:24

to you know render in markdown format

276:27

and also allow us different different

276:29

views to you know edit the markdown

276:31

directly as well if you you know if you

276:33

don't want to edit the form so cool all

276:36

we have to do is just copy this up npm

276:38

install and I'm going to go to my

276:39

terminal and paste it right here npm

276:41

install at uw/ react MD editor and press

276:45

enter we will also be using this another

276:47

Library called HTML to PDF to save our

276:50

markdown resume as a PDF file so copy

276:53

this up as well and paste it right here

276:56

and actually I don't think we need to

276:57

add uh the version so yeah this should

277:00

install it now so now let's go inside of

277:03

this other tab where is it sorry not

277:07

here in the Resume Builder component

277:09

over here in the tab content value value

277:11

to be preview so inside of it we want to

277:15

First display a button over here so that

277:18

we can add the ability to directly edit

277:19

the markdown so if you see in our

277:21

deployed application we have this button

277:23

called edit resume when we click on it

277:25

see we are able to directly edit the

277:27

markdown and we also show this warning

277:29

that if we you know edit the markdown

277:31

and then go on to edit the form again we

277:33

will lose all of the you know progress

277:34

over here after editing the markdown so

277:36

okay we only want to show this button

277:38

right here if we are on the preview

277:40

right so so I'm going to be adding this

277:42

button right here which will say variant

277:44

link type button and class name to be

277:46

margin bottom to be two and we will have

277:48

this edit icon over here let's import it

277:51

from Lucid react and let's see how this

277:53

looks inside of our application if you

277:54

go to markdown yep we can see this edit

277:56

resume so let's create a state right

277:59

here on the top which will check if the

278:01

resume mode is on preview or not if it's

278:04

on preview we will show the you know

278:06

preview else we will show the edit

278:09

markdown State and then right here if we

278:11

are on the resume mode preview we will

278:14

show edit rume else we will show Show

278:17

preview and on click whenever we click

278:19

on it I'm going to say set res mode if

278:21

it's on preview set it to edit else we

278:23

will say preview okay let's see oh

278:27

monitor icon is not being imported so

278:30

let's see if I go over here Yep this is

278:34

working fine now below it is where we

278:37

will be rendering markdown editor but

278:39

before that like if we are on the edit

278:41

mode mode we want to show that warning

278:43

as well right so I'm going to say here

278:45

if resme mode is not equals to preview

278:48

that is we are on the edit mode then

278:49

I'll have a d which will show this alert

278:52

triangle and a message called you will

278:54

lose edited markdown if you update a

278:56

form data and by the way I created this

278:58

custom over here but you can also take

279:01

this uh alert from Shad CN UI so alert

279:04

yeah you can see it provides you with

279:06

pre-built component similar to this but

279:09

this also works fine right so again

279:11

let's go on and check it out yeah

279:14

something like this now below it we can

279:16

uh render the mdor so how do we do it so

279:18

let's go and check in the docs we simply

279:21

have to take this component MD editor

279:23

and we need to provide the value of what

279:25

we want to render and on change whatever

279:28

the function is we want to trigger it

279:30

right so let's create a state for it I'm

279:32

going to say preview content right this

279:35

is where we will have our markdown

279:37

content we'll provide it the initial

279:38

content right here if there's already

279:41

some content inside of our database now

279:43

let's just create a function over here

279:45

to get the you know to basically convert

279:48

the form data ins to the markdown format

279:52

So Below this use effect right here I'm

279:54

going to create a new function called

279:57

get combined content and inide of this

280:01

is where we will be creating our

280:02

markdown content now our markdown

280:04

content contain multiple different

280:06

things right so let me just take out the

280:07

things from form values so it will be

280:10

summary skills experience C education

280:12

etc etc so I'm going to say return and

280:14

it's going to be an array and first of

280:16

all we need to combine uh the contact

280:19

information right and then we will add

280:22

summary skills and then the experience

280:25

education and project so first of all

280:26

for creating the contact I'm going to

280:29

have a function over here get contact

280:31

marked down and I will have one more

280:33

function so let me just uh you know

280:35

create a separate helper file for it so

280:38

helper. JS over here

280:41

inside this I'll be creating entries to

280:44

markdown function which will take the

280:45

array of you know experiences or

280:47

projects Etc and it will convert them

280:49

into the markdown format right so these

280:52

two functions are what we will be

280:53

building and then inside of this return

280:56

I'm going to use them something like

280:57

this so first of all get markdown

280:59

contact it should create the contact

281:00

markdown summary I'll render the summary

281:03

in this format so this hashes and two

281:05

hashes are what you know represent the

281:08

headings I would recommend you guys to

281:10

uh learn more more about markdown it's

281:12

basically a format on how you can create

281:15

a particular document or something right

281:17

just the way you create your readme

281:18

files on GitHub right so I'll say this

281:21

professional summary heading and then

281:23

I'll say slash n for changing the line

281:25

and then add this summary similarly for

281:26

skills and this entries to markdown will

281:28

take the experiences education and

281:29

projects and will structure them

281:32

accordingly let's first see this get

281:33

contact markdown also let me just import

281:36

it yeah so first of all for getet

281:38

contact markdown we will take the

281:40

contact info from the form values and

281:43

this has four parts right email mobile

281:47

LinkedIn or Twitter right so I'm going

281:49

to say const parts I'll take an empty

281:51

array I'm going to say if email is there

281:52

then parts. push with this emoji and

281:55

contact INF for email same with mobile

281:59

same with ledin and same with Twitter as

282:01

well and then in the end I'm going to

282:03

combine all those four parts by saying

282:05

Parts dot length if it's more than zero

282:07

if we have something inside of it then

282:09

we will take a div and we want to render

282:11

it in the very center right so I'm going

282:12

to say align Center some inline styling

282:14

user do full name on the top and then

282:18

after this the contact information that

282:20

is part parts. join with this thing

282:23

right here right simple enough and then

282:25

we will render it right here what about

282:27

entries to markdown first of all we will

282:29

check if entries has anything inside of

282:31

it so if it does not have anything

282:33

return empty but if it does then return

282:35

this so I'm going to say first of all

282:38

what is the type right so let's say if

282:39

it's experience so I'm going to

282:41

experience then change the line Plus for

282:44

each and every experience we will do the

282:46

following we'll take each and every

282:48

experience over here and we will render

282:51

the date from this like if the current

282:53

is present then from start date to

282:55

present else from start date to end date

282:57

and then after that we will render

282:58

things like what is the title the

283:00

organization how much time we have

283:02

worked there and the description let me

283:04

show you how this will look like so if I

283:06

go to my deployed app see something like

283:08

this title at theate organization and

283:11

then the date and then the description

283:14

right after obviously this heading of

283:17

work experience or education Etc all

283:20

right let's go back and now we have this

283:22

get combined content function and now I

283:25

want to render it in the markdown right

283:26

so let's just let's just before this I'm

283:29

going to create a use effect hook over

283:31

here inside of this whenever our form

283:34

values changes so inside of this array

283:37

I'm going to say form values if this

283:40

changes or the active tab changes then

283:43

we will update the markdown content with

283:46

whatever we have inside the form right

283:47

so I'm going to say if active tab is

283:50

equals to edit then I'm going to take

283:52

the content from this get combined

283:54

content over here and then I'm going to

283:56

set preview content if we have anything

283:58

inside this new content then we will set

284:00

it else we will take whatever the

284:01

initial content was being provided to us

284:03

so if you remember this state that we

284:05

just now created set preview content

284:07

okay now we will take that uh preview

284:09

content and then render our markdown

284:11

right over here inside of the other tab

284:15

content right in the preview So Below

284:18

this so just like we saw in the docs let

284:20

me just have a div over here with the

284:22

class name of border and rounded large

284:27

and instead of it I'm going to import MD

284:30

editor and provide it with the value

284:33

preview content and on change set

284:35

preview content and I'm going to say hi

284:36

to be 800 and in inside of the preview

284:38

we'll provide this resume mode so if you

284:40

remember we created this state right if

284:42

it's preview we will show the preview if

284:43

it's edit we will show the edit so let

284:45

me just check it out inside of our app

284:47

right here what is the error maximum

284:49

update depth increased okay let me just

284:52

refresh this I think something is wrong

284:54

over here it is updating this again and

284:56

again so it's right here let me check I

284:59

think I know what's causing that error

285:01

we have this return over here right

285:03

after this we need to say do filter

285:05

Boolean like if we don't have anything

285:07

in any of these we need to filter it out

285:09

and then join them with the sln so that

285:12

they are on the separate lines now let's

285:14

see let's see if I add anything over

285:16

here user is not defined okay yeah we

285:19

are taking user over here right in the

285:21

contact uh markdown so I need to take

285:23

the user from clerk so I'll say use user

285:26

and I'll take out the user info over

285:29

here so I'll say user now it should work

285:32

let's add something and go to markdown

285:34

yep something like that let's add some

285:36

gibberish over here some

285:39

skills right and let's see yep we are

285:42

starting to uh you know form it let's

285:45

add some chish in the

285:49

experience let's say it's a current

285:51

experience add entry it should have been

285:53

added now awesome you see how beautiful

285:56

this looks we are able to add our resume

285:59

right here how do we get the PDF

286:01

generated out of it let's see so what

286:04

I'll do right below this one this MD

286:08

editor I'm going to have another div and

286:10

and I'm going to be rendering just the

286:12

markdown we will give this the class

286:13

name of hidden so that we cannot see it

286:16

but since we will have the HTML inside

286:19

of our Dom we will just take it and

286:21

convert it into the PDF right so that's

286:23

why we given this ID resume PDF over

286:25

here because we will be using this thing

286:27

HTML to PDF library to convert it right

286:31

so how does it work let's go and see

286:33

first of all we need to add the button

286:35

for downloading PDF which I believe we

286:36

have already added right so it should be

286:40

right here yeah let's create a state for

286:42

it while the PDF is generating right so

286:44

I'm going to have U State over here is

286:47

generating and set is generating okay

286:50

then in this button download PDF I'm

286:53

going to say if is generating is true

286:56

then display the loader imported from

286:58

Lucid react and show generating PDF else

287:02

show the download button with download

287:03

PDF right now over here in the button

287:06

I'm going to call a function right here

287:08

called generate PDF and it will be

287:10

disabled when the PDF is being generated

287:12

so let's create this generate PDF

287:13

function uh let's create it right here

287:16

just generate PDF this will be an

287:18

asynchronous function and first of all

287:21

I'm going to say is generating to true

287:24

then I will have a try catch block over

287:26

here inside the tri block first of all

287:29

we will get that particular element from

287:31

which we will be generating the PDF so

287:32

I'll say const element equals document.

287:35

get element by ID resume D PDF okay

287:38

after it how does it uh work html2 PDF

287:40

PF first of all let me just import it so

287:42

HTML to PDF import it like this let's

287:45

see if it has been imported yep I think

287:47

this might cause some issues because you

287:50

know while I was developing this project

287:52

this is how it allowed me to use it

287:55

right so make sure that you also import

287:58

this HTML to PDF like this I'm not sure

288:00

if it has been fixed or not but let's

288:02

see we will try it out and check if it's

288:04

been fixed so this will be a wait call

288:08

html2pdf Dot and I will set some options

288:12

over here so let's see what options so

288:14

I'll say const options equals inside of

288:18

an object I'm going to provide it few

288:20

things like there will be margin 1515

288:23

file name is going to be resume.pdf

288:25

image type JPEG and we'll provide the

288:28

quality we will use HTML to Canvas so

288:30

basically these are some of the things

288:31

that I have taken from their

288:32

documentation and we will provide some

288:35

PDF configuration over here as well

288:38

right like in the format of A4 and

288:40

orientation be portrayed Etc then I'm

288:42

going to say these are the options and

288:43

from this particular element so I'm say

288:45

from element and then save it in the end

288:48

after this for the catch I'm going to

288:50

say console. error PDF generation error

288:53

if there's any error and finally I'm

288:55

going to say set is generating two fs

288:56

and this should give us our PDF let's

288:59

try it out so yep over here so let's

289:03

just write anything for let me just have

289:06

this contact information and try to

289:07

download this so if I click on download

289:09

PDF okay generated is okay let's see oh

289:13

yeah amazing it has generated this file

289:15

for us we can select all this text and

289:17

all as well we this is clickable you can

289:19

see at the bottom you can see mail to

289:20

this email address right so this is

289:22

fully interactive resume over here as

289:24

well if you want to add some you know

289:25

links and all to this experience

289:27

description over here they will continue

289:29

to work awesome now the only thing

289:31

remaining over here is to be able to

289:33

save this resume inside of our database

289:36

and by the way one more thing if we want

289:38

to edit this directly we can click on

289:39

edit resume and and we can edit it right

289:42

over here if I want to Let's remove agal

289:45

and click on Show preview yep you can

289:47

see this is editable in real time

289:49

awesome let's go back to the code and we

289:51

have already created this on submit

289:54

function let's see what do we get when

289:56

we submit it right so I'm just going to

289:58

console log the data for now and go back

290:01

open inspect console click on Save uh

290:05

doesn't do anything let's see on submit

290:09

and this form should have have that

290:11

button for submitting it so I don't

290:14

think we are calling that function so

290:16

let's see yeah we have this save oh yeah

290:19

we are not calling it right here so I'm

290:21

going to say on click all this handle

290:23

submit on submit and this won't be

290:26

useful over here so we can remove it

290:28

from here yeah so handle submit and

290:31

we'll call this on submit right here and

290:34

it will be disabled when this is being

290:35

saved and let's just use this loading

290:37

indicator over here as well so I'm going

290:40

to say if it's saving show the loader to

290:42

Icon and saving else show the save

290:45

button okay what else do we need to do

290:47

let's try it out first if I click on

290:49

Save still doesn't work what's wrong oh

290:51

I believe it because we have not filled

290:53

this professional summary over here so

290:55

let me just write anything right here

290:57

can I save it now oh yeah email address

291:00

let me just open the inspect click on

291:02

Save okay it's asking for the skills

291:05

again let me just add in gibberish over

291:07

here click on Save again yes now we are

291:09

getting something over over here okay

291:11

cool then but I don't think we would be

291:13

making use of this data anyways so it's

291:16

not useful for us so you know what uh

291:19

when I'm clicking on that button over

291:21

here we can choose to remove this handle

291:24

submit from over here right like this so

291:27

inside of this onsubmit I'm just simply

291:29

going to have a try catch block and I'll

291:31

say await save resme function and

291:33

provide the preview content that we

291:34

earlier had save resume function this

291:37

one and obviously we won't be making use

291:39

of this data now now and inside the

291:41

catch just simply say console error and

291:44

whatever the save error is if there's

291:45

any error right and yeah we need to have

291:48

a use effect as well which will trigger

291:50

our toast right so I'm going to say if

291:52

save result changes save error changes

291:54

or is saving changes then trigger this

291:56

and I'll go inside of it I'll check if

291:58

save result has something and it's not

292:00

saving right now then display this toast

292:02

make sure to import it from sonor resume

292:04

save successfully else if there's an

292:05

error show the error message right here

292:07

right that is all I think this should

292:10

work now now let's see let me just add a

292:12

bunch of jish again over here so this is

292:15

a random number don't try calling it

292:16

it's not my number so let's just say XY

292:19

Z XY Z let's add some work experience

292:23

XYZ

292:24

XYZ from this to this add entry and

292:28

let's go to markdown yep we can see some

292:30

rume over here let's click on Save and

292:32

it should save it yeah resume save

292:34

successfully if I refresh it now we

292:36

should still see that rume being fetched

292:39

yep we can see our resume being fetched

292:41

from the DB let's go and check it out

292:42

inside of our neon DB there we go this

292:45

is the content the markdown content that

292:47

you can see is being stored and which

292:49

user does it belong to and yeah that's

292:51

pretty much it for the resume right

292:54

awesome so you have just built a

292:57

production grid feature right this is a

293:00

I would say pretty engineering heavy

293:02

feature if you have not built something

293:04

like this up until now right we are

293:06

rendering stuff in markdown format we

293:08

are downloading this as a PDF this

293:11

feature alone in itself trust me is such

293:14

an impressive thing to be added inside

293:16

of your resume right building a rume

293:18

added to your resume so yeah definitely

293:20

I would recommend you guys to Showcase

293:22

this in your interviews whenever you're

293:24

applying to a company and all right now

293:27

the next feature is building the cover

293:29

letter so let me first go to my deployed

293:31

website and check how this feature works

293:33

so you can see we have all of our cover

293:35

letters over here if you click on create

293:36

new we would enter the company name the

293:39

job title and the description over here

293:41

and click on generate cover letter and

293:43

what this will essentially do and you

293:45

can see over here we have used Zord

293:47

validation here as well right and this

293:48

will basically provide it to the Gemini

293:50

API and generate a cover letter for us

293:53

very very simple very straightforward

293:55

feature and I want you guys to build

293:58

this feature because let's be honest if

294:00

you have followed this tutorial up until

294:02

this point and if you're not able to you

294:04

know build a feature like this because I

294:07

would say this is probably the simplest

294:08

of features and don't worry I'll tell

294:10

you as well how you can build this if

294:11

you're not able to still build a feature

294:13

like this then there's something wrong

294:15

with your learning trust me so I don't

294:17

want to spoon feed you guys by building

294:20

every single aspect so this is an

294:22

assignment for you guys if you want me

294:24

to make a separate video on this I will

294:25

make a separate video on this let me

294:26

know in the comments down below but let

294:27

me explain you how you're going to be

294:29

expl like you know building this and I

294:32

already have the code for the whole

294:34

thing inside of my GitHub repo so if you

294:36

get stuck you can go over here so first

294:37

of all you will have to build the server

294:39

actions right and again if you don't

294:40

want to see this part you can skip this

294:42

part and go directly to the deployment

294:44

right you can check from the chapters

294:46

below the video I have mentioned where

294:47

the deployment starts so if you want to

294:49

get an idea how you can build this

294:50

feature see we will create this function

294:54

very simple generate cover letter right

294:56

and we will send it the data of the

294:58

title company description and the like

295:00

the job title right and we will write

295:03

this prompt over here we'll provide the

295:05

user industry years of experience the

295:06

skills from what user has entered in the

295:09

top like at the beginning in the

295:10

onboarding screen right so that is the

295:13

information that we will be using to

295:15

craft this cover letter and we will

295:17

enter the requirements on how we want it

295:19

we would want it in the markdown format

295:21

as well keep that in mind so if you go

295:24

back and see the one that I've already

295:26

generated if I click on over here in the

295:28

I button see this is in the markdown

295:30

format so this is pretty straightforward

295:32

to store it and then you can create a

295:35

server action to get all of the cover

295:37

letters if you want to get one single

295:39

cover letter for one single page right

295:41

that is what you can do as well and if

295:43

you want to delete you can write dis

295:44

delete all of these things we have

295:46

already covered in this course and now

295:48

you need to take action from your side

295:50

and build this feature right and the UI

295:54

which is I would say in this case is

295:55

pretty simple is inside of over here in

295:58

the main folder AI cover letter right I

296:00

have a separate component for cover

296:02

letter generator list preview and

296:05

obviously the page over here as well the

296:06

dynamic ID page and obviously for

296:08

creating the new cover letter as well

296:10

right so definitely try it out yourself

296:12

if you're not able to do it let me know

296:14

in the comments down below for now if

296:16

you want to host this res uh project

296:18

let's go on and host it on verell right

296:20

and then maybe later on you can continue

296:22

building this cover letter feature

296:24

awesome so first thing first we need to

296:26

push our project to a GitHub repository

296:29

so let's open GitHub and click on over

296:31

here to create a new repository let's

296:34

name this Sensei let's keep it a public

296:37

repository create repository all right

296:39

now let's push all of our code to it so

296:42

I'm going to go to the terminal and I'll

296:44

say first of all get in it press enter

296:48

and also by the way we need to add

296:49

inside of package.json a script over

296:52

here called post install which will run

296:55

Prisma generate you know generate all of

296:57

our schemas after deployment all right

297:00

now I'm going to say get add dot to add

297:03

all the files and then I'll commit the

297:05

changes so I'll say get commit dasm oops

297:08

one one thing I don't don't want to add

297:10

the do EnV so let me just check if I

297:13

have not accidentally pushed it or let's

297:16

see I don't think we have make sure in

297:19

the dogit ignore we have EnV over here

297:22

yes we do so no issues so now I'm going

297:25

to say get commit DM and provide the

297:28

message let's say preparing for

297:31

deployment press enter there we go now

297:34

I'm going to say get push

297:37

origin master and this should push it uh

297:40

what's oh sorry we have not added the

297:42

origin so make sure to copy this line

297:44

and paste it over here first get remote

297:46

add origin and then get push origin

297:48

Master there we go it is posted so if I

297:50

refresh this page now we should see our

297:52

code right here awesome so now let's go

297:55

to verell ver.com and we want to deploy

297:59

our website right here so click on add

298:01

new project over here let's click on

298:03

import and this will import our get

298:06

repository and by the way we need to

298:08

configure inist as well so I'll go to

298:11

in.com slocs and inside of this we want

298:15

to find the deployment so over here in

298:17

the deployment overview deploy with

298:19

versell okay so we are using App router

298:23

yes installing injest official versell

298:25

Integrations click on over here yep

298:27

right here we need to connect our versel

298:29

account so click on connect account and

298:31

let's select the team connect account

298:35

okay and then after this oh yeah we

298:37

after this we need to select that uh

298:40

verel project right so right now let's

298:42

just first log into verel I'm going to

298:45

sorry not verel I mean inest we will log

298:47

into inest right here it's going to show

298:48

me all of these projects so this is not

298:50

the project this is actually my previous

298:51

deployment so never mind let me just

298:53

close it for now let's just first go to

298:56

versel and deploy it so let's add the

298:58

environment variables first of all over

299:00

here so I'll go to my code go to EnV

299:03

let's take these one by one and add it

299:06

right over here the key and the value

299:10

let me just add them quickly and come

299:12

back there we go I have added all of

299:14

these values over here and now I think

299:17

we are good to go let's click on deploy

299:20

and let's see so it has started

299:21

deploying right here and first of all

299:24

it's installing all the dependencies

299:26

okay creating an optimized production

299:28

build hopefully no error will occur okay

299:31

it is generating static Pages now and

299:33

this is a good sign I think our

299:35

deployment is about to be completed

299:37

amazing our website is successfully

299:40

deployed awesome let's click on over

299:42

here and see and yeah we need to do one

299:44

more thing we need to connect inist as

299:46

well right so click on connect account

299:48

now in the same page that we opened

299:50

earlier and now we need to choose over

299:52

here that Sensei website y this one

299:55

right and click on Save configuration

299:57

continue to injust worel dashboard let's

300:00

click on configure and yeah we should be

300:02

taken to right over here and we should

300:04

see yep our Sensei website over here so

300:06

if I click on configure our project

300:08

status enabled versal deployment

300:10

protection might be block syncing uh

300:12

might block syncing okay yeah we need to

300:13

change this actually so one thing that

300:15

you need to change uh let's click on

300:17

continue to dashboard invers Cel go to

300:19

settings and we need to disable the

300:21

deployment protection over here so turn

300:23

it off and save it and now if I refresh

300:26

this up yep now it's working fine so if

300:29

I go back if I should see over here I

300:32

don't think we have over let's click on

300:34

sync new app and we need to get the uh

300:38

URL for our app so our URL is Sensei D1

300:42

verel app so let me just copy it up

300:44

paste it over here and add/ API SL inest

300:49

after it and click on sync app and there

300:52

we go our app is synced successfully if

300:54

it does not work for the first time try

300:56

doing it again sometimes it fails right

300:58

so you can see we have our injust

301:00

functions over here as well and we can

301:01

see how many times they have been

301:03

replayed obviously right now we have

301:05

deployed so they have not been replayed

301:06

but we can manually trigger it from over

301:08

here invoke it from over here right so

301:10

this is awesome let's go on and test out

301:12

our app I'm going to click on sign in

301:14

and let's sign in with Google okay we

301:17

are signed in let's click on get started

301:19

and there we go we are inside of our

301:21

dashboard if I go to build resume okay

301:25

this was the resum that we built earlier

301:27

right great we have our form and

301:28

everything over here amazing so you have

301:31

successfully created this awesome

301:33

project to your resume now the next step

301:35

for you guys is to start applying for

301:38

interviews and if you want to prepare

301:39

for you already know you can check the

301:41

link in description down below for my

301:43

front inter preparation course and enter

301:45

the coupon career for the maximum

301:47

discount

UNLOCK MORE

Sign up free to access premium features

INTERACTIVE VIEWER

Watch the video with synced subtitles, adjustable overlay, and full playback control.

SIGN UP FREE TO UNLOCK

AI SUMMARY

Get an instant AI-generated summary of the video content, key points, and takeaways.

SIGN UP FREE TO UNLOCK

TRANSLATE

Translate the transcript to 100+ languages with one click. Download in any format.

SIGN UP FREE TO UNLOCK

MIND MAP

Visualize the transcript as an interactive mind map. Understand structure at a glance.

SIGN UP FREE TO UNLOCK

CHAT WITH TRANSCRIPT

Ask questions about the video content. Get answers powered by AI directly from the transcript.

SIGN UP FREE TO UNLOCK

GET MORE FROM YOUR TRANSCRIPTS

Sign up for free and unlock interactive viewer, AI summaries, translations, mind maps, and more. No credit card required.