✈️ Build & Deploy Full Stack AI Trip Planner NextJs App Using React, Typescript, Arcjet, Convex
By TubeGuruji
Summary
## Key takeaways - **Build a Full Stack AI Trip Planner**: This tutorial guides viewers through building a comprehensive AI trip planner web application from scratch, integrating technologies like Next.js, React, TypeScript, Convex for database, Clerk for authentication, Mapbox for maps, and Google Places API for location data. [00:00], [45:00] - **Leverage Shadcn UI for Rapid Development**: The tutorial emphasizes using Shadcn UI, a component library built on Tailwind CSS, to accelerate the development of a professional and visually appealing user interface, reducing the need to write extensive CSS from scratch. [01:23:36], [01:44:43] - **Integrate AI for Trip Generation**: The project utilizes AI models to generate personalized trip itineraries based on user inputs such as destination, duration, budget, and preferences, demonstrating how to implement generative UI for a more interactive experience. [01:36:16], [02:14:15] - **Implement Real-time Database with Convex**: Convex is employed as a real-time database solution to efficiently store and manage user data, trip plans, and other application information, ensuring data consistency and seamless updates. [58:47], [01:01:16] - **Secure App with Arcjet and Clerk**: Arcjet is used for rate limiting and security, protecting the application from abuse, while Clerk handles user authentication and simplifies the integration of subscription billing models with minimal code. [01:19:13], [04:43:41] - **Visualize Trips with Mapbox 3D Globe**: Mapbox is integrated to provide interactive 3D global maps, allowing users to visualize trip locations and destinations, enhancing the user experience with dynamic and engaging map features. [04:15:27], [04:26:48]
Topics Covered
- Introducing the AI Trip Planner: Your Personal Travel Assistant
- Interactive AI Trip Planner with Generative UI and Maps
- Securing Your App with Arcjet and Implementing Subscription Billing with Clerk
- Rendering a 3D Globe Map with Custom Styling
- Adding Markers to the Map: A Step-by-Step Guide
Full Transcript
Tired of spending hours researching
destinations, hotel and activities? Our
AI trip planner does it all for you in a
second. Just type in where you want to
go, your travel duration, budget, if you
have any preferences and watch our AI
power assistant instantly build a
personalized trip itinary for you. It
completes with the hotel, restaurant,
attraction, any hidden gems tailored
just for you. So today we are going to
build an AI trip planner fullstack SAS
application which give you a day-by-day
travel plan interactive maps with the
pins and smart recommendation. This is a
fullstack application which we are going
to build it completely from the scratch
with the help of React NexJS TypeScript
and many other popular text stack we are
going to use to build this full stack
SAS application. If you are a beginner
and don't know how to code, this AI trip
planner web project is perfect for you
in order to get started. Let me walk
through the application first and then
we'll talk about the all the text stack
which we are going to use to build this
application. If you see we have this
beautiful landing screen for our AI trip
planner web application where we have
the hero se hero section in order to
directly start creating a trip. We have
video tutorial section along with this
beautiful scrolling corrosal that also
we are going to learn how can we build
this landing screen. Next we added the
email and password authentication.
Simply log uh to your account and then
you'll find an option to create a new
trip. Simply click on that and then you
will jump onto this page where you can
directly start chatting with an AI trip
planner agent. On the right hand side
you will see this beautiful interactive
map. Obviously you can switch between
your trip information and then this map
as well. Now once you start uh charting
with an AI agent depends on your
personalized preference it will generate
the personal trip for you. So let's get
started. So over here I want to start
creating a new trip. We'll add an source
and destination. So we'll say New York
to London.
Then we we also added a gender to UI.
And here if you see we got an gender to
UI option to select. So just select the
option for you. And obviously depends on
your answer. It will ask the next
question. How cool it is.
You're going to learn how easily we can
add this generative UI into your u text
conversation. Now you can even select
the dates and once you confirm it, it
will generate an complete itonary trip
for you. Now we'll wait to finish this.
After finishing this uh trip generation
here on the right hand side you will see
all the details the trip itonary from
your source to destination. Then all
your select uh selection uh which you
made it and here you'll find the hotel
recommendation. If you see how easily
you can scroll it and then you will find
a daybyday uh trip planned for you. Here
you will find a best time to travel, the
beautiful attraction along with the
ticket pricing and when uh the best time
to travel at that particular location.
You can even see this on Google map by
just clicking view on map and here we
have how cool it is right next you will
see the day second day the third day it
depends on how many day you are planning
to travel now most interesting part on
this one you can switch this to the
globe and boom if you see we have this
beautiful map animation where you can
directly jump on to that particular
location and here you will find all the
location which is from your itonary. You
can see where it actually uh placed on
the map. This is how easy it is and
that's everything we are going to build
in this particular project guys. Okay.
Next, you can even go to the my trip
section where you will find all your
trip plan. Click on that and then you'll
jump on your itinary with the same
details on a different uh screen. Next
with the help of arjet we added an extra
security for our our application. We
also put a rate limiting for the free
user. So user cannot create more than uh
one
itonary per day and that is possible
with the help of arjet. Then we also
added the subscription billing model to
our application where you can easily
subscribe and uh start paying monthly
basis which is possible with the help of
clerk billing within just single line of
code. You can easily add the pricing um
subscription model into your
application.
Obviously uh you don't need to integrate
a big chunk of code in order to
integrate payment gateway with the help
of clerk billing. It is possible within
a second. Everything is getting saved to
our convex database which is a realtime
database. And here if you see all the
details if you never use the convex
don't worry because in this particular
project I'm going to tell you how easily
we can set up this convex and easily
connect to your application. This is a
fullstack SAS application which we are
going to build it completely from uh
from scratch. Now if you see all these
places and their photo as well that also
we are going to learn how can we fetch
it and display it on the screen. Now all
the resources uh services which we are
going to use in this project to build
this application is free. So you don't
need to pay a single penny to build this
application. So guys, if you are new to
this channel, don't forget to subscribe,
press notification bell icon so that you
will not miss any update and you did not
join our tube guruji pro membership.
Just go ahead on a tube guruji.com where
you will find an exclusive courses and
the source code for each of my project.
Not only that, but you'll get an special
uh technical support on a discord
channel. Just go ahead on tube pro and
join the membership just under $15.
So guys without doing any further delay
let's start developing this AI trip
planner fullstack SAS application with
the help of React NexJS TypeScript and
many other text stack.
Now in order to create this React
application we are going to use a NexJS.
NexJS is a React framework to develop
the web application. It provide many
inbuilt feature like built-in
optimization, React server components or
even client server rendering as well.
Not only that but most important the
routing. NextJS contain a folder based
routing. So you don't need to manually
configure the routing inside your React
application and that's the reason we are
going to use a NexJS. Now in order to
create this React NexJS application,
this is the command in order to use it
which is npx create next app at latest.
So we'll copy this command.
Go to the folder where you want to
create this project and then open a
terminal at that folder. If you are
using Windows then make sure to uh open
a command prompt at that folder and
simply paste this command. Now at latest
will install the latest version of the
NexJS application. But if you want to
use a specific version just provide that
specific version number. Now 15.4.4 is
the latest version of the NexJS. We'll
click install and then it will start
installing. It will ask do you want to
proceed? Say yes and then give the
project name. So here we'll say AI
trip
planner.
Then it asked do you want to use
typescript? Now in this particular
project we are going to use a typescript
and if you are new to the typescript
don't worry because I'm going to teach
you everything step by step. Typescript
and the javascript is quite similar
except 10% of changes and that's I'm
going to tell you how to uh do it. Then
say no to the es say yes to the telvin
css no to the source directory and yes
to the app router. And then we'll say no
for the remaining questions.
If you see it start installing some
dependency like react, react and some
div dependency for a typescript and
tailwind CSS as well.
And once done you are ready to go. Now
we'll close this window. Simply open a
VS code and inside the VS code you have
to open that particular project inside
this VS code. Hello
and here we have if you see on the left
hand side we have some files and folder.
Let's walk through the walk through each
of these folder. Now the very first
which is the app folder which contain
all our pages routing APIs. Now very
first file which is a global CSS which
contain a globally apply style or CSS to
your application. Now whenever you want
to apply some style throughout the
application you can mention inside this
global CSS the layout.tsx file which is
the root layout of your application
which contain a font the metadata which
is helpful for SEO purpose and HTML body
tag as well. through this body. If you
see the children are rendering, it means
all our pages are going to render
through this children. Now this
layout.tsx file is on the server side
and we want to keep it on the server
side all the time. Then we have the
page.tsx which is the default page of
our application and if you see we have
some default code as well. Now each page
we need to mention with page.tsx. Now
once we run the application you'll get
to know much better. Then we have this
node module folder which contain all our
packages. Obviously we are not going to
touch this folder any time. Then we have
a public folder which contain all the
images, logos, whatever the assets you
want to use from your local project, you
can keep it inside this public folder.
Then we have next doconfig.ts file which
contain the nextjs related
configuration. Then we have package.json
JSON which contain the name version of
your application along with the script
to run uh to start or to test your
application the dependency along with
their version and some dev dependency
along with their version as well and
then we have post CSS and tsconfig.js
file as well. Now in order to run this
application simply go to the terminal
click new terminal
inside this simply type a command npm
run dev and click enter. Once you run
this command you will see your
application is running on a port 3000 on
localhost. Simply open this inside the
browser and then you will see the
default landing page. Obviously this is
the default page when you created the
NexJS application getting rendered
inside the browser. Now let's consider
we'll go to the app inside the page.tsx
and we want to remove everything and
we'll simply add empty div. Now if I
save this one and go back you will see
empty screen. Now over here we'll add a
h2 tag and we'll simply say subscribe to
tube guruji. So guys, if you did not
subscribe to our channel, please do
subscribe. Once you save this file, you
will see this simple text. As soon as
you save the file, it automatically
render to your uh application and
getting display on the browser as well.
So you don't need to refresh manually.
Okay. So that's how guys you need to run
your application and create your
application.
Now the next step is we want to uh
install the shad CN. So simply go to the
shad CN. Now, Shaten is an UI based
component library which is based on a
tailwind CSS obviously and we are going
to use this library in order to develop
our UI uh pages which help us to build
our application and design our
application much uh faster and
professional way. So in order to install
this simply go to the ui.shadcen.com
click get started and make sure to
select the correct framework to install.
Then you have this command. Just copy
this npm command in order to initialize
this shad scen. Open a terminal. Make
sure to add a new terminal and play
enter or paste this particular command.
Then say do you want to proceed? Say yes
to that. And then you can select the any
base color whichever you want. Okay. And
once you select the base color you will
see this CSS variable is updated inside
the global CSS file. Okay. with the
tailwind CSS version 4, we don't have
dedicated tailwind.config.js
file. Everything move to this global CSS
file.
Now once you save it, your shad cen is
now ready to go. Now let's install this
button component from the shad cen.
So again we'll paste this command and
then this button component will install
to the shad c. Now whenever you want to
use any components from the shad CN like
let's say you want to use popover right
like this then you have to make sure
that component need to be installed
every time okay now once you install you
will see uh this new file get added
called component js json which contain a
configuration related to your shad cen
then you have component folder which
contain the whichever component you
install from the shaden that component
will be added to this u component folder
Obviously you can customize this
according to your need and then we have
li folder. We are not going to touch to
this particular folder at all. Now once
you add this button component you can
easily use it. So I will say button and
if you see it's importing from this
component folder and then you can write
any text. Let's save this one. We'll go
back to our application and this is how
it look like. But that's weird right? If
I go to the shadian button component,
it's supposed to look like this, right?
So sometimes it happens. So what you
need to do with the inside the global
CSS, remove this twwan animate CSS file.
Save it. Go back to your application and
boom. Now it come to your uh original uh
style. Now obviously you can
you can paste this again. Okay. So I
will sorry
I will paste this and save it. And
obviously you will not find any issue.
Now so that make sure you have to fix
this issue. If you uh face this issue uh
while adding this button on your screen
now once you add this button you will
see this button and inside this button
component if I go to this component UI
button.tsx file you can see different
different variant like default
destructive outline. Now if you want to
use this variant just type variant and
you can select the whichever variant you
want you want. Once you select that you
will see that change. How cool right? So
that's how easy it is. So you don't need
to write the tailwind CSS classes for
these basic components.
Now the next thing before move to the
next chapter that we are going to update
the font for our application. Currently
this is the default font that we are
using. But if you want to use any other
font simply go to the layout.tsx and
currently they are using this default
font. So I will remove this font.
completely because we don't want that
and we want to use our own custom font.
Now in order to use the custom font you
simply go to the Google font
and once you are on the Google font you
can select any font which you want to
use for example in my case I like to use
this outfit font okay and if I want to
use this font simply make sure to
remember this name then if you see this
next font.google Google here I will
remove this font and just type outfit
you will find this suggestion called
outfit then initialize this font so
we'll say constant outfit is equal to
outfit
then inside this we need to write
subsets and then we'll say latin and
then this outfit font you need to
provide to this body so we'll say outfit
dot class name and then save it and
boom. If you see now font uh style or
font family is now changed. Okay. So
that's how you need to update the font.
You can use any font guys. Okay. Just
you need to make sure to import that
font and then initialize that font as
well.
Now it's time to add a landing screen
for our application. If you see this
mockup, we have this header section.
Then we have this hero section and then
and after that we have this video
section in which we are going to
demonstrate how it works, how our
application works. That video
integration we going to add and then
some popular destination.
Each of these component we going to add
u with the help of some UI component. So
it will be very easy. You don't need to
write a lot of code. Okay. And that's
what we are going to learn in this
particular chapter as well. Also in the
header along with this logo and this
button we are going to add some more
option in the middle. So let's go back
to our application. And remember one
thing that this complete page we are
going to divide into a small small
components like header hero section and
this popular destination section. So
inside our application, let's close all
of this tab. And inside this app folder,
we are going to create a new folder
called components or underscore
components. When you start your folder
name with a underscore, then this
component or this particular uh folder
will not consider as a route. Okay. Then
inside this we'll add header.tsx
file. Let's add a default template. Now
if I if you see once I just type RFC and
click enter it automatically add the
default template for me and this is
possible because I added the VS code
extension called react redux snippet
tool. So this one okay so make sure to
install this VS code extension also is
it will be best if you also add this
Telvin CSS intellisense um extension as
well. So which help us to write the
Telvin CSS classes much faster. Once you
add this header tsx, we have to make
sure that this particular header will be
throughout the application, right? So,
we want to keep it inside the um root
layout. Obviously, we want to keep this
layout.tsx file on the server side. So,
we'll create a new file called
provider.tsx.
And we'll keep this file on the client
side.
Now once you add the provider we have to
make sure you will render this children
through this provider. So I will copy
this and simply we'll paste it here
and then I will render this children.
Now inside the layout I will wrap this
children inside the provider so that it
will render through this provider. Okay.
Now obviously if you go back to our
application you will see no changes
right but now inside the provider.tsx
now we can add the header
that's because all our pages are going
to render through this children and
header will be constant throughout the
application. Okay now if I save this one
you will see this header text that is
nothing but this header component is
rendering. Now inside the header first
we want to show a logo
right then we want to show
the menu options
and then get started button. So these
three section we want to show. So first
in order to uh show the logo I will just
use some logo placeholder. So just
search logo placeholder something like
this and it you can copy the SVG file
from it. So you can search whichever you
want. Okay. So in this case I will use
this particular logo or maybe
let's search a little bit
uh we'll use this one. Okay. So just
copy this SVG. Once you copy we'll go to
the public. We'll create a logo SVG file
and simply
paste this and then save it. Once you
save, you can use that directly inside
the image. So we'll add this image from
the next / image. It help us to optimize
our image. Then provide the file name.
Now you don't need to provide a complete
path. We'll give the alt name. We give
the width and height and then save it.
Now once you save, you will see this
logo is rendering on the screen. How
beautiful.
Along with that one, we also want to
give the application name.
So we'll wrap this image inside the D.
So we'll add H2 tag. And here we'll say
AI trip planner. For this one, we'll add
a class name. We'll say font bold and
text to Excel.
Something like this. See? And then let's
bring everything in one line. So we'll
say flex gap to let's say two. And then
item to be in the center. Perfect.
Uh I will just remove this content.
Okay. So you will not get confused.
Perfect. Now this is our logo. After
that we want to add a menu options. So I
will define this menu option over here.
We'll say constant
menu options
and then we'll say name as home
and obviously we want give the path for
that one.
Then name which will say pricing. the
path
we'll say pricing
and then the last I will say
contact us
and the path for that one we'll say
contact us as a path now this option
once you define you can just iterate
those options
so over here I will add a div then we'll
say menu option dot map we'll say menu
index and the arrow function
Inside the S2 tag, we'll say menu dot
name and then save it. Obviously, make
sure to wrap this in a link tag. Now,
once you wrap this in a link tag is
similar to anchor tag, you need to
provide an H reference. Okay, on the
click where it should go. So, provide
the H reference and inside this we'll
say menu.path.
Now, let's save this one. We'll go back
and if you see these are the three
option now displaying on the screen. Now
let's bring everything in one line. So
we'll say class name flex gap to five
and item to be in the center.
I will give gap more gap. And for this
H2 tag, we'll give font not font but
we'll say text larger. Once you hover on
this one, we want to also scale this to
105. And for smooth animation, we'll say
transition all. So if you click hover on
this one, you will see that change.
Perfect. Now let's bring everything in
one line. But before that I also I'm
also going to add a button.
Oops. Sorry.
And here we'll say get started.
Perfect. Now I want to bring everything
in one line. So for this parent div
we'll say flex. Then we'll say justify
between and make sure to provide item to
be in the center. See? Then for this div
we'll so we'll give a padding to four
something like this and now everything
will be in the center I'll show you our
on this one the color get changed
now currently the primary color is kind
of black color and we want to change it
to this our logo's color right now in
order to change the your shadian
component primary color simply go to the
global CSS file inside this if you
scroll down under the root you will see
this primary color and this is provided
ated with this okch color format.
Obviously, I also don't know what is
this color format is but you can provide
your hex color as well. But uh this
particular shadian variable does not uh
support the hex anymore. So you in order
to convert your hex code to this that
particular format simply go to this site
called oklsch.com
here paste your hex code and then you
can copy this particular color format
and simply paste it here and then save
it. Once you save we'll go back and boom
you will see that change. How cool. Now
our primary color changed to that
particular logo's color. How easy it is
right? So make sure to do that also for
this um menu option. Whenever you hover
on this one, I also want to change text
color to primary. See something like
this. How beautiful. So make sure to add
this all the small detail which give
your application more attractiveness.
Next part is to add this hero section
where we have this content then this
input box and then the suggestion
options. Okay, obviously we also have
this hero section. So let's go back.
We'll I will close this header and then
I will add a new component under this
component folder and we can call it as a
hero tsx. Let's add a default template.
Once you add this hero component
obviously we want to show it on the home
screen. So inside this page tsx I will
import this hero component save it and
then we'll go back over here you will
see this hero uh component is loading
perfect now let's go to this hero
component first thing inside the class
name
um I will give margin top to let's say
24 also we'll make it flex item to be in
the center and then justify between if
needed But right now I will just make
item to be in the center.
Then we want to show a content first.
Then input box
then suggestion list
and then video section.
Okay. Everything will be in the hero
section. Now for the content we'll
simply add a div. Inside this div we'll
add an H1 tag or H2 tag what doesn't
matter. And inside this we'll say hey
I am your
personal
trip planner.
Now for this trip planner text I'm going
to wrap this
inside the span tag.
something like this and then for this
pan I will add a text to be primary.
Okay. Now for this H1 tag we'll say text
excel on medium screen we'll say text is
of 5 XL
font bold and then save it. If I go back
this is how it look like. Obviously we
want to bring this in the center of the
screen. So we'll class name flex and
we'll say
item to be in the center justify
let's
basically instead of this one what we
can do we can provide a maximum width to
3 excel okay and then we'll also make
sure to wid is full and take to be in
the center
let's save this one and uh I don't know
why it's not coming in the center of the
screen
and here as well we'll make justify
center perfect now once you done this
one done with this I will also make sure
to wrap this everything inside the div
okay not only this content and then
we'll add a p tag inside that we'll say
tell me what you want and
I will handle the rest Okay. So like uh
flights,
hotels,
trip planning
all in seconds.
So some text like this obviously uh once
you add this I'm also going to add space
Y
to six. to some space and for this P tag
I will add a class name
um text larger
something like this see
then we want to add an input box okay
now make sure our input box will look
like this uh inside that we have this
text area from the shadian and button at
the corner so in order to add that text
area I will go to the shadian
go to the text area component. Make sure
to copy this. And then we want to import
that. So I'll paste it here. So this
text area component will get add.
Then we'll define a div. Inside the div,
we'll add one more div. Inside this
we'll say text area component.
Okay. And then inside the placeholder
we'll add a create a trip for
Paris from New York. So this is just a
uh placeholder. Okay. So this is how it
look like. See
now obviously we also want to add a
button. So for this text area I want I
don't want that particular border.
Right? So here first we'll say width to
be full. Then I will also provide an
height to 28. I want a transparent
background. And then we'll say border
none.
Okay. So if you see but when you click
on this one we also don't want that
particular border line. So here we'll
say focus
uh visible
then oop sorry the ring I don't want
that ring. So we'll say ring to zero.
See? Perfect.
Uh also we'll add a shadow
none.
Okay. So you'll not see any shadow. And
we don't want this particular resizable
things. So we'll say resize none. See
now it's gone. Perfect. Now for this
particular div you can add border. Then
we'll make round it to let's say 2 XL.
And then we want to add padding to four.
See? And now we have this beautiful
border as well. You can add the shadow
to this particular um text input box or
you can remove it either way. Next thing
we want to add a button. So we'll say
button. Inside this button um you can
provide a size
icon and in that we can add a send icon
button from the lucid react. Now once
you install the shad this button also
get in uh the icon library also get
installed. So this is the icon library
currently we are using. Okay, you don't
need to install manually because it's
auto install once you install the shad
cen components. So once we have this u
icon you can even provide height and
width for that particular icon and then
save it. We want this icon on the right
side. Right? So simply for this button
we'll add a class name. We'll make
absolute.
Then we'll add a bottom to let's say six
and right because we want a right side.
So we'll say right to six.
Let's save this one. And it's going at
the bottom. That's because we need to
provide or mark this particular div as a
relative. So we'll make this relative.
And now it is inside this particular
text input box only. How beautiful,
right? So that's how you need to add
this input box. How easy we added.
Right? Next is the suggestion list. Now
we need to provide the suggestion list
first. So at the top
we want to add a suggestion list. So
we'll add a constant suggestions.
And inside this we'll add a title. Let's
add a first title. Let's say create new
trip. For that one we also going to add
an icon. So we'll say globe to icon. To
this one we'll add a class name. And
let's make text blue.
400
and along with that one just provide the
height and width over here. Okay, same
thing you have to do and add few more
options. Now once you added these all
the suggestion you just need to iterate
those. So inside the div we'll say
suggestion dot map inside this we'll say
suggestion comma index and then arrow
function.
Then inside this we'll add a div
and simply add this suggestion dot icon
first. Then inside the h2 tag we're
going to show suggestion dot title and
then save it. For this do let's add a
key as a index. And then you will see
this suggestion. Beautiful. Now for this
do let add a class name because we want
to add some style. So we'll make flex
item to be in the center. Gap to two.
Then we want to add a border. We'll make
rounded
full and then save it. Make sure to give
some padding. So we'll give padding to
two. Perfect. And then we want to bring
everything one line. So for this div
we'll add a flex gap to five.
Perfect. Um, also for this H2 tag, we'll
add a class name text to access.
And then we have this. Let's make it
small. I think that's much better. See?
And now our suggestion is ready. Now,
whenever you hover on this one, we want
to change the cursor. So, we'll say
cursor
pointer. Then
this is how it look like. Um when you
hover on this one we want to change
background color. So on hover we'll say
background to primary and on hover you
have to make sure text should be white.
See something like this right? Um I
don't know whether we want to change
this icon to white. I think let's do
that too. So over here we'll say on
hover um
we'll change this to white.
And let's see how it looks.
I don't think so that's affecting
anything. Uh we'll keep as it is.
Okay. And when you hover I think that's
look much better. See
now next thing as you know that we want
to add this hero section. Right now, in
order to add this video section, sorry,
the video section I wanted to say uh you
can use the one uh L UI component called
magic. Sorry, that not this one. It's
magic UI. Okay. Now, magic UI is based
on chat. So, you don't need to install
anything. But inside the component, you
will find a bunch of different
components. Okay. You can explore more.
But inside this component section, you
will find this hero video dialogue. Just
click on this one and this is what we
want. Once you click on it, it will open
the dialogue in order to play that
video. How cool. And that is inside your
application only. Now, in order to use
it, make sure to select the CLI. Copy
this npm command. And if you see this
command is in from the shadian only,
right? And then once you install this,
you can use any code. So this is how it
comes. I will go to the code and or you
can even see the usage how it actually
works. I will copy this usage. I will go
to this video section. Simply paste this
section. Make sure to import that. And
then you have to replace this thumbnail
source. Okay.
Need to use thumbnail source. So you can
copy this thumbnail source. I'm proing
inside this uh documentation. Just paste
it. Save it. And if I go back, boom, you
will see this beautiful video section.
Once you click it, it will open the
dummy one. Right now, we don't have that
YouTube URL ready, but once we finish
this application, you can provide that.
Now, next thing, make sure uh just
before this, I'm going to add an H2 tag.
And inside this, we'll say not sure
where to start. And inside the span tag
or we'll say strong tag. Basically,
we'll say see how it works. And then I'm
going to add
down arrow or we'll say arrow down.
Now for this H2 tag, we'll add a class
name. We'll say margin Y to 7, margin
top to 40, and we'll make flex gap to
two. Save it. I want in the center of
the screen. So we'll say text to be in
the center.
I think that's fine. I don't know why
it's not coming in the center
but maybe because
so here we can make flex column and now
it's come to the center but this
text input getting broken. So just
remove that
then and you can keep like this only. If
you want really in the center what you
can do
you can wrap this inside the div
and then you can provide a class name
flex item to be in the center justify
center
and make flex column that is very
important. Okay. And now beautifully it
look showing this um video section as
well. So that's how guys uh our hero
section is now ready. Okay. So until
this point if you have any question any
doubt let me know in the comment
section. The next thing we want to add
is this
corrosal. Okay. Which is a popular
destination that we want to add and it's
very easy. So for that one uh go to this
UI. certainity.com similar like this
magic UI this particular UI component
library also u use the chaten only go to
the components over here you'll find a
bunch of different components and for
our case we're going to use this apple
carts corroser okay now if you see this
is how it looks obviously you can change
this content which however you want and
then simply in order to use it go to the
CLI copy this npm command go back to
your application
and simply
we'll paste it here. So we'll clear this
paste it so that you can use. Now make
sure I will close all of this tab and
here I will create a new component for
that one and we can call it as a popular
city list.tsx.
Let's add a default template or let's
simply copy this example code. So this
is the uh code we want. So we'll go to
the code, copy everything, paste it
here. Now we'll replace this
uh component name to we'll say popular
city list and then save it. Once you
save, make sure you need to add inside
the page.tsx file. So we'll say popular
city list component. Once you save,
we'll go back to our application and
boom. If you see how beautiful it's
looking now, we have these beautiful
components as well. Now in order to
replace with our own um destination all
I already added this list. Okay, simply
copy this data information and we'll go
back inside the popular list. Here we
have demi content but inside this data
you can replace with your own data. So I
will paste it here. Okay. And then over
here you can obviously edit it. So we
have category, title, source and
content. Now if I go back, refresh the
screen. Oh, I think I forgot to save it.
And boom. If you see, we have this
beautiful destination,
right? And that's how you can add this
corrosal into your application.
I'm going to make some small update. I
don't want this particular text this
much bigger. So I will make it 3XL.
And then um we give the uh padding I
think so padding y so here I will make
just to five
and uh not five we'll keep as it is
we'll say padding top to 20
or we'll say padding y actually um the
this particular distance is too much so
maybe because of this corrosal
but for Now we'll keep as it is. Okay.
And then save it. You can just rename
this to we'll say popular
destination to visit.
Okay. And then we have all of these
destination. Perfect. Now if you have
any question, any doubt on this
particular uh landing screen, let me
know in the comment section.
Now it's time to understand the workflow
of our application so that we can
implement each of the feature step by
step. Once user come to our application
and want to create a new trip, we'll
check if user is already sign in or sign
up to our application or not. If user is
new user and not sign in or sign up,
then we are navigating user to the login
and sign up screen. And once user is
sign up or login depends on that one we
are going to save user information to
our database and for that one we are
going to use a convex database. Convex
is a real-time database and it's very
easy to integrate and easy to use as
well. After that uh if user is
successfully authenticated to our
application we are going to check if
user is a free user and has any
subscription. It means user is paid or
free user. If user is a free user means
user did not subscribe to our any
pricing model then we're going to check
uh users daily usage limit. We are going
to give user two to three credits where
he can uh generate two to three trips in
a day and that particular logic going to
handle with the help of this arjet. ARJ
is a model where it help us to restrict
user in order to limit uh our AI trip
generation. There are lot of different
feature that we are going to show and we
are going to implement with the help of
ARJet. If user is a free credit and user
has a free credit lift then obviously we
are going to navigate user to this uh
create new trip planner application
where user can create a new trip with
the help of AI or obviously if the user
is a paid user means user is a subscribe
to our any pricing model then user have
option to uh navigate to this trip
planner. So this is the basic workflow
initial workflow for our application.
Once user on this particular um screen
where user have option to create a new
trip then there are a lot of different
feature that we are going to implement
later on but for now in order to
implement all of this feature we have to
go step by step. So very first thing
that we need to add is the login signup
screen. So for that one I'm going to use
a clerk. Clerk is one of the best
authentication service provider in the
market. Not only that but we are also
going to use clerk for our billing.
Clerk provide the subscription billing
model. You don't need to integrate any
payment gateway. Clerk will take care of
everything. Just you need to add one
single line of code which is the pricing
table component and then boom it will
give you the all the pricing table which
you want and with the help of stripey it
also integrate the payment gateway
directly to your application. How easy
it is and that's the reason we are going
to use clerk for our application. Clerk
is so powerful that it also protect your
application from unauthorized user. It
has a different different pre-built UI
component. So you don't need to build
everything from the scratch. And the
most important thing it provide a lot of
different feature like multiffactor
authentication, session management,
email, SMS, onetime passcode, a magic
link or social sign in signup as well.
Everything is packed under one uh
provider. So that's why uh make sure to
go to the clerk.com create a new account
if you don't have and then navigate to
the dashboard.
Once you are on the dashboard here you
have option to create a new application.
Give the application name.
Then you have option to enable different
signin like email magically uh
authentication or Google Facebook and
there are many more. Simply
uh click create application. On the
right hand side you will see the UI
component how it actually look once you
integrate that and then I will create
this application. Once the application
is created you have option to select any
framework which you want. Obviously in
this case we are building an NJS
application. So I will select the neckj
copy this clerk neckj npm command in
order to install into your uh project.
So inside the terminal just paste this.
So it will install the clerk inside the
neck.js.
Then you need to copy this environment
keys. So we'll copy those and then we'll
create a new envu file. Inside this
we'll paste this both the keys.
Then we'll copy this middleware.ts. Now
middleware is very powerful feature
inside the NexJS application and clerk
will you clerk is using that one in
order to protect your pages from
unauthorized user. So obviously copy
this middleware.ts
file obviously we'll create a file first
inside the root directory and then we'll
copy all the content as it is and then
save it. Then we have to make sure that
our application is need to be wrapped
inside this clerk provider. Okay. So
what we'll do, we'll go to the lay sorry
the layout.ts file. So we'll close all
of this tab
and inside the layout.tsx we'll wrap our
application
inside the clerk provider
something like this
and make sure it is cler provider is
importing from the cler/ neckjs. and
then you can run your application. Now
if I go back and run our application,
you will not see any changes. Right now
we did not implement our own custom
signin and signup page. So click the
link in the description so you'll jump
onto this clerk authentication. Here you
can continue to the NexJS guide.
On this one you have to add custom
signin and signup page. So this is the
route at which you need to create this
signin page. So I will copy this
complete route as it is. Then we'll go
back to our app folder. Inside that
we'll create a new folder start with
this circular basis called O. And inside
that will click on this plus sign file
icon. Enter it and it automatically
create you the folders and file. So you
don't need to create the folder or file
one by one. Then copy this content and
simply paste it here. Same thing you
have to do for the signup screen as
well. But before that uh make sure that
you will make the sign in as a public
route. So I will copy this middleware
now this code and I will replace the
current middle file content with this
new one.
Okay. So it basically make the route as
a public and it avoid that if the route
is public you don't need an
authentication. Right? Similar way you
have to implement. Make sure to save
that. Next you need to copy this all
these uh lines inside the env file
and again you need to add a custom
signup page as well. So same thing we'll
copy this. You can click the link in the
description about the clerk. So you will
get the documentation link inside this
art folder. We'll add this file and then
we'll copy this content and we'll paste
it here.
Then make sure inside the middleware you
will add this
as a public route.
Okay. And you need to add this
environment variables as well.
And that's all. Now if I go back to our
application, let's say local 3000. And
then if you see it's redirecting me to a
sign-in screen. Now remember that our
landing screen need to be a public
right. So you don't need an uh
authentication for our landing screen to
uh visit right. So for that one what
we'll do we'll go to the middleware
and we'll tell that okay along with the
sign in and signup script this home
screen is also an public route. Now if I
go to the local 3000 see I'm able to
access it right but if I go to this any
other route it asks me to sign in
correct now I will just redesign this
particular page sign in and sign up page
and it's very easy so um simply we'll go
to the sign in page tsx file
inside the div we'll add this and we'll
then say sign in
for this div we'll add a class name
we make it
flex item to be in the center justify
between and height to screen
and we'll say width to full oh sorry uh
this need to be justify center
something like this see okay same thing
I'm going to add for a signup screen as
And if I user want to sign up, he will
navigate to the signup screen as well.
Okay. So I will refresh this. We'll go
to the sign up.
So make sure oops sorry. So this need to
be wrapped in a circular braces.
And now I can able to see sign of screen
as well. Beautiful. Right? So make sure
to implement in such a way that user can
see this sign in and signup screen. Now
make sure on the click of get started
you have two option either you can
navigate to sign in or signup screen or
you can show a popup inside your uh home
screen directly. Let me show you how. So
we'll close all of this tab for now and
then go to the header. Inside that we
have this get started button and here
we're going to wrap this button inside
this signin button component from the
clerk next. See something like this and
then save it. Now if I click on this get
started it navigate to the signin page
right but as I say we can show a popup.
So here you have option called mode and
inside that you can say a model. Once
you say model, click get started and
boom, it open a popup for sign in and
sign up screen. See how cool, right? So
this is the second way that you can
implement it. Next, once you enter the
information and click this send button,
you have to make sure that user is sign
in or not. And depends on that one, you
should navigate to the uh new screen. So
for that what you can do inside your
hero.tsx tsx file
I'm going to add constant here we'll say
user
and then we'll use this use us user hook
from the clerk now once you import this
hook make sure you have to mark this
component on the client side now once
you have the user it means you have the
all the user information which is login
and then
on the click of send button we'll check
if user is sign in or not. Right? So
basically
I will add on click method
and we'll say on
send. So I will call this on send
button. Sorry. So we'll create this
method
constant on send
and this method will check if not user
then we'll return nothing and then we
want to navigate to this sign-in screen.
So basically in order to navigate you
need to add the router.
Okay. So make sure to add this router
and then we'll say router dot push
and we want to navigate to the new
screen which is the
obviously uh we'll say sign in. Okay
otherwise
uh we'll navigate
to create trip planner web screen
or web page. Okay. So let's save this
one now.
If I click button say it navigate to
sign in because user is not signed into
our application. Now let's sign in. So
you have two option. You can either sign
in with the email and password or you
can sign in with the Google.
I will select the account
and then you will see that I am able to
sign in to my account. Now boom. Right
now if I type anything and click on this
button see I should able to navigate it.
Right now obviously it's not showing me
sign in and we don't have any logic to
navigate to the tip planner web page.
But for now I hope you understand how
easily we added this Gmail password or
Gmail and email password authentication
into our application. Obviously there
are lot of feature the clerk will
provide for you and you can explore it
by clicking the link in the description
so that you can check all the
documentation and the all the features
as well. Later on we are also going to
add a clerk billing model so that you
learn how easily we can add a payment
gateway and subscription model based uh
feature into our app.
Now next we will learn how we can save
this new user login or sign up to our
database.
Now it's time to save the user into our
database and for that one we are going
to use a convex. Convex is a open-source
reactive database for the developers. It
provide a lot of different features like
realtime update, type safety, framework
integration along with the chrome job to
schedule uh some uh background jobs or
even you can have option to store some
files like um convex provide you the
file storage as well.
Uh convex is available to a different
framework. So it's very easy even though
if you switch from one framework to
other convex uh can help you to do that
as well. So click the link in the
description. So we'll jump onto the
convex and their documentation. Simply
login. Once you log to the convex,
you will jump onto this dashboard
project. Here you have option to create
a new project. Give the project name. So
here we'll say AI
trip planner and simply click create. If
you see I already have a lot of project
created with the convex. Convex also
provide you the development and uh
production mode as well. So it will be
easy to switch between the development
and the production mode.
Then on the left hand side you will see
some of the features like function file
schedule logs and many other option.
Now once you created the database
simply jump onto the convex
documentation. I will put the link in
the description. Select the correct
framework and here you need to
initialize the convex. Very first thing
that you need to install the convex. So
we'll copy this command. Go back to your
project.
Inside here I will paste this. So it
will install the convex for us.
And once the convex is installed, you
can run the convex development. So over
here you can use this npx convex dev.
Now we already created the project. So
make sure you will select this choose
existing project and then you can simply
select the project which you just
created. So in this case we created this
AI trip planner. So we'll select that
one and boom. Now your convex function
is ready and running locally. Now once
you run this particular um mpm command
you will see inside this env.local file
get created and inside this you have
this convex deployment key and then the
convex public convex url as well. Okay.
Along with this, you'll see the new
folder get added called convex. Inside
here, these are some uh some files under
under this under underscore generated
folder. You don't need to worry about
this one right now. Okay. Now, we'll
head back to the documentation again and
you need to wrap your application inside
this convex provider. So, we'll copy
this convex provider something like
this. Okay. We'll go back to our app.
So uh we'll create this file called
convex client provider. So simply inside
this app we create this convex client
provider.tsx file. Inside this we'll add
a default template and then make sure to
uh render the children. So we'll simply
copy everything as it is
something something like this. Okay. So
you don't need to export because we are
already exporting. Make sure to import
this convex provider. And here uh we
also need to add this convex URL. You
need to initialize this. So we'll copy
at this top. Okay. Now make sure to
import this convex react client.
Uh we have to add react node. I think
that's all we needed. Now here we are
already rendering the children, right?
So what we can do? We will render
through this provider
something like this and inside the
layout.tsx file where we are rendering
from the provider instead of this now
we'll render it from the convex client
provider
and then save it. Now you have to make
sure your application running smoothly
and don't have any issue. Right now if
you see your application has some issue
it's saying that uh you need to define
that in a use client. So inside the
convex client provider mark this
component as a use client
and boom now if we don't have any error.
Okay and that's all you need to do. Now
the next step is you need to create the
table inside the convex database and in
order to create a table convex use a
schema structure. Now once we when we
say the schema it nothing but that you
need to define the table and the column
name. So in order to do it simply go to
the convex and inside the convex folder
we need to create a schema tsx file or
you can just say ts
over here um in order to refer that how
to create a convex table and all you can
simply go to the documentation
inside the documentation
uh you can go to the database and then
just go to the schema section here you
will you will see how to define a schema
for any table. Okay. And let's implement
it. So here we say export default
I will just
and make sure to define the schema. So
we'll say define
sorry
define schema. Inside this you need to
provide a table name. So we'll say user
table.
And inside the do you you need to define
as define table
and then just provide a column name.
Okay. Now if you want to provide an id
you can provide the ID but convex is
automatically adding a unique ID for
each of the record. So you don't need to
define that one but we will define a
name. So name is of type uh string or
var. So here you need to define a value.
Make sure to inputting from the convex
slash value dot
here we'll say string
then image URL
which is again of type string
uh then the email of type string here we
say subscription
now subscription again of type string
and we are provide uh you can even
provide the credits if you want. Okay,
it's completely optional thing. If later
on if we needed you can easily update
that and then simply save it. Once you
save, you can just see the convex
function. You don't have any error and
it's showing currently the convex
function is ready. Now if I go back to
our app and refresh this uh database,
you'll see the new table get added
called convex table. Currently we don't
have any record. But if I click on add
here you will see all these fields that
you can add it. How cool right now if
any of the field if you want to make it
optional you just need to wrap it like v
dot optional
currently obviously we want to make this
subscription as optional field. So you
can simply wrap this and now that
particular column is now optional. Okay.
Inside this
schema you can see the current schema.
Okay. So you can easily check whatever
you added inside the schema file. And
that's how you can add a table. Once the
table is ready, let's insert a record.
So we'll go to the app inside the
provider.tsx file
over here. Uh first we'll write a method
called constant create new
user as a method.
And inside this we'll first check if
users is already exist or not.
So either you can directly define or
write a um method over here or you can
create an API endpoint in order to
insert a new record. Simply we need to
check or we need to make sure to uh call
or save you new user if not exist. Okay.
So in order to do that obviously we need
to write a convex API endpoint. So go to
the convex inside this we'll create
user.ts
file and inside this user.ts file we'll
simply create a mutation because we want
to insert a record. So here we say
export constant create new user is equal
to mutation and if you see this mutation
is importing from the generated server
from the convex only and then uh we need
to accept the arguments first okay which
are the field you want to add it so
first we'll say name of type string make
sure you are importing this v
then email of type v dot string string
and then image URL of type v dot string.
Once we have these three value here
we'll we need to define an handler.
We'll say async and inside this we'll
have ctx,
arguments and then error function.
Here you need to write a logic in order
to save the record. So here we'll check
if user already exist. So first we need
to check if it already exists or not. So
we'll say constant user is equal to
await
ctx
dot db dot query because we want to
fetch the record. Here you need to
provide a table name. You can see this
suggestion. So table name will be the
user table.
Then we have to add a filter. It means
the wear clause. Here we'll say query.
So query dot
equal to and then Q dot fill is email
matches with our arguments
I don't okay so this need to be
arguments so here we'll say arguments
dot email if that matches then we have
to collect that means we have to select
those all the record now here we'll
check if
user
of zero
we'll say user dotlength if the length
is greater than zero or maybe we can say
if length is equal to equal to zero it
means we don't have any record it means
we need to insert the record so we'll
say constant user
data and whichever the field you want to
insert you can just define that so here
we'll say arguments dot name for email
we'll say arguments dot dot email and
then
image URL arguments dot image URL. So
these three field we want to add right
and then we will say if not then create
new user.
So over here you say constant result is
equal to await ctx dot db dot insert and
then the user table and we whatever the
field you want to add that field which
is nothing but the user data which we
already define. Once it is insert you
can return the user data as it is
something like this. Okay. But if you uh
user is already exist then you can
simply return that user information.
So we'll say user of zero. Okay. If user
is already exist as simple as that and
then save it. So that's how you need to
define the convex function. Okay. This
is very important because all your logic
are returning on the server side. Convex
is running on the server side. So don't
need to worry about that. And all your
logic is also running on the back end
side. Now once you have that inside the
create new user first you have to define
the uh this particular mutation. So
we'll say constant create user is equal
to use mutation. Inside this mut
mutation define that API endpoint. So
we'll say API dot user dot create new
user. Okay. And simply inside the create
new user you need to call it. So we'll
say constant
result is equal to
await
create new user. And obviously you need
to provide uh all the fields. Okay.
Oh, this need to be create user only and
inside this we need to provide the
arguments. Okay. email image URL and
name. Now in order to get those
argument, you can simply get it from the
use user hook. So here we have this use
user hook.
Uh make sure your provider is on the
client side. So we'll define use client.
And then once you define the user, now
make sure you'll pass this value like
email. So we'll say user oop sorry
user dot primary email address dot email
address then the image URL. So we'll say
user dot image URL and the name user dot
full name
here I will make this as a async and
here you can add a condition as well if
user okay because that's the reason it
give us this uh error as well sometimes
or you can add
some default value to it. Okay. Now this
particular method we need to call only
when the user information is uh
available and also whenever this
component get load. So inside the use
effect when whenever the user is
available we will execute this use
effect and then we'll also execute this
create new user method something like
this. See
oh so this need to be double question
mark. So if full name is not there it
will save it as a empty string. Okay and
then save everything. Now if I go back
to our application you will see already
it inserted the record into our
database. Now even though you refresh
many times it doesn't matter because uh
it only check whether the user is
already exist or not and depends on that
one it will save the information. So
that's how you need to create a new
user. Okay. Now before moving to the
next chapter make sure once the user is
sign in you have you can change this
button to let's say create new tree.
Okay. So what we can do we'll go to the
header first
and inside the header once the user is
sign in. So over here we need to check.
So we'll define a user is equal to use
user
and I will mark this component on the
client side
and then we'll if not user means user is
not sign in then it will show this sign
in button or get started button
otherwise we'll add a button
here make sure it's a turnary operator
and here we'll say create new trip.
Okay. Now we'll show this particular
button. See, and we obviously want to
navigate that. So we'll wrap this in a
link tag with a h reference.
Create trip and we'll say create trip as
a new route
and then save it. Okay, perfect. Right
now user is login. So you have option to
create a new trip. If I click on it,
obviously we don't have that particular
page or route. So that's the reason it's
showing 404 error. But uh make sure to
update this particular uh button logic.
Okay. So that's all uh I hope you
understand that this is very important
to set up a database because whatever
the information now we are going to uh
save it, we want to save inside the
convex database. It's very easy guys.
Very uh first time it might be seem
difficult to you but once you implement
it will be easy.
Once we have the user information and
user detail after sign in it is very
important to share that information
across the different of different
components so that you don't need to
fetch it every time and in order to do
that we are going to use a context.
context is very powerful react hook in
and it's not a just a hook but it's a
state management uh functionality inside
the react application. So in order to
create the contact simply we'll create a
new folder outside uh or maybe inside
the root directory and inside this we'll
create a user
detail context tsx file. Now in order to
create a context simply you need just
need to write export constant user
detail context is equal to create
context. Make sure you will import this
create context from the react. Now as
this is a simple one so I will I'm
giving the type any
then you need to wrap your application
inside this context provider. So go to
the app inside the provider.tsx file.
I'm simply going to add a user detail
context dotp provider to this provider
you need to pass the default value that
value are going to share across the
application. The interesting part about
this context that you can update this uh
state value from any components and it
automatically reflect to all the
components as well. Now in order to pass
the default u state first we'll define
that state. So we'll say user detail
comma set user detail is equal to use
state. Now uh I hope so you know this
use state hook. Okay which help us to
set the value and to get the value for
the specific uh variables. Okay. Now
once you define this over here we'll set
the user detail with the result and
here I will provide a type any because
uh we keep the context as type any only
and then you can simply pass this user
detail information to this context. Now
whichever component which you are going
or pages which you are going to render
through this particular children are can
access this user detail information. Now
later on you will get to know how we can
use this
also. Um in order to avoid writing the
complete context here I'm going to also
write one more method called constant
user
use user detail. So we'll say use user
detail
and inside that we simply return
use context and then user detail
context. Now you don't need to worry
about this for now. Okay, this is just a
simple way uh to use this use digital
context.
Now it's time to add a feature in order
to limit the access to our free trial
plan. As you know that this is SAS
application and we want to add a free
trial as well as paid subscription model
into this application. Inside the free
trial obviously user can create only one
trip per day. Okay. So he can plan only
one uh one trip and then we want to also
give the limited access to the certain
features. Obviously we are going to
reset this limit every day. It means
next day he can again create a new trip
but he has to wait a 24 hours in order
to generate a new trip plan. But in in
the case of paid user, you don't need to
wait it. You user can create unlimited
trip and he can access have all the
features. But the question is how can we
add this limit? Obviously if you try to
write a logic it will be very
complicated. But what if I told you that
we have this best feature that can help
us to add this um limit to our u free
trial. Okay. So that's where the arjet
comes uh and play very important role.
Arjet is the developer first security
platform for a web application. It offer
a protection rule for automated board
detection, rate limiting, email
validation, protect a signup form and
there are many other feature can uh you
can add with this help of arjet and it's
very easy to integrate it provide a very
light SDK which you can easily add it
and within a u few line of code you can
easily integrate it with the help of
arjet we are also going to add email
validation so that when you want to send
um the trip plan to your user, you can
send it to the email but before that
obviously we are going to add a
validation whether that email is correct
or not and the rate limiting which is
quite easy and quite interesting. So
that's what we are going to see. So
first thing first uh we'll go to the do
uh documentation you can check the uh
link or click click the link in the
description. So you'll jump onto the
specific website and the documentation.
Here you need to select the correct
framework. So in our case we are using
NJS. So make sure to select the NJS. Uh
it also provide a tutorial. So you can
go ahead and watch if you want. Now
first thing we need to install the
arjet. So we'll copy this npm command.
We'll go back to our application.
I will close all of this tab for now.
And inside the new terminal we'll simply
add this arjet.
The next thing we are going to set the
key. Obviously we need to add this arjet
key and we need to obtain it from the
arj account. So uh before that I will
just paste this key over here. Okay. And
then we'll create an arj account. Now
interesting part is free to use. Okay.
So you have the free trial. So you can
use it. Um, you can add up to five rules
and no expiration. So, it's up to you.
You can even go with the starter plan if
you want to add a multiple sites.
And I will simply log in with my
account. Once you log in, you will jump
onto this uh home screen where you have
option to add a new site. Give the site
name. So, in our case, we'll say AI trip
planner. We'll create this site and then
you'll get this arjet key. Just copy it
and paste it here.
Once you copy it, we'll go back to the
documentation again and then you can
simply add the rule. Now in this
particular example, you will see uh it
help us to protect your application from
SQL injection which is very important.
Then you can even uh detect the board
and token bucket which help us to limit
or rate limiting features and there are
many others. But if you want to uh use
or integrate specific feature go to this
features and just click that example. So
if I click quick started and scroll down
you will see this example. Let's copy
this example as it is for now and then
we have to add it inside the arjet/
route.ts.
So I will go to this API first. So
inside the app we need to create an API
folder and inside this API folder we'll
create arjet folder and then inside this
we have route.ts file then copy the
content as it is and simply paste it.
Now let me walk through this code. It's
very interesting as we initialize this
arjet and passes this arjet key. Okay
which we already generated and save it
inside our env.lo file. Then we need to
define the rule. Now currently we said
it's a in a live mode and we define the
characteristic as well where you can
pass a user ID as a unique ID. Okay.
Then you can refill the rate. Okay. So
after 10 second it will refill with the
five tokens and each time it will deduct
five tokens from the account. Okay. And
that's I'm going to tell you how. But uh
currently it just have the 10 seconds of
interval. Okay. So after every 10
seconds it will fill with the five
tokens. And the maximum capacity of that
particular bucket is just 10 tokens.
Okay. So obviously it will not store
more than 10 tokens. Then whenever you
make a request you just need to add this
particular line which will protect your
application or protect our request. Uh
to that request you have to pass a user
ID. Okay. So it will be a unique user ID
for for this example it uses this user 1
2 3 and then uh for every request it
will detect five tokens. You can change
this to two it's up to you. Okay. And
then we'll check if the is decision is
denied. It means there are too many
request otherwise it will return the
hello world on a successful request.
Okay. Now once you save it let's test
this out. So simply what you need to do
just go to the local host once you run
application I will go to this local host
/ ai/jet
as our application is already running so
I will go to this and you will see we'll
get the hello world say if I refresh it
again again I got it but if you refresh
it again it's saying too many request
and then the maximum capacity remaining
one the reset the window size and
everything if I refresh it after say 10
second it again fill it but if If I
refresh it back to back see I'm not
getting right because it will add the
tokens every after 10 seconds. Okay. And
now you got the result. Now that's how
you can limit your API request as well.
Okay. Now instead of 10 seconds
obviously you can add for a 24 hours
duration. You just need to convert uh 24
hours to seconds and you can add that
interval. So basically for 24 hours I
will say 86 400.
Okay. So it will now refresh it every
after
uh 24 hours and the maximum capacity
just 10 and refill rate is five. Okay.
So that you can easily handle this one.
Later on you going to learn how easily
we can protect each request with the
help of this arg.
And we also going to implement the email
val validation later on in this
particular project. But for now I hope
you understand. Now you can even access
this rate limit for each of the user and
you can see the analytics inside your
arj dashboard. Over here you will see
that the rate limit is uh trigger and
whenever it allow it's saying it's
allowed. See how cool right? You can see
this analytics as well. How many times
it get denied? how many times it allow
everything you can see inside your arj
dashboard and that's why it quite easy
for a developers to protect it and you
don't need to write a bunch of code to
limit the API access
now the next thing is uh we want to
navigate user to the create new trip
screen on this screen we are going to
divide the screen into two sections one
for the chat box where user can enter
the information in order to generate u
the trip planner and on the right hand
side we are going to show eternary and
the map. Obviously we need to show a
complete trip information uh the hotel
list the places to visit daybyday and
everything timeline basis and also want
to give an option to show a map.
We are going to show a 3D map so user
can interact directly with that
particular map and we are going to also
show all the location on that map. Then
on the chat box section we are it's kind
of question answer format chart box. But
the interesting thing about this that we
are going to add a generative UI to
select some option. For example, if user
want to select uh the um how many people
are going right or budgets. So where we
are obviously giving option to select
from the UI. You user don't need to type
it. It automatically give us that
option. So that's how we are going to
add generative UI feature to our app. So
let's go back and let's create a new
route called create new trip.
So inside the app folder
we are going to create a new route
called create new
trip as a new route. Inside this we'll
create a page tx file and then we'll add
a default template.
I will rename this to create new tree
and then save it. Now once user is
logged in to our application
and on the click of create new trip
button we want to navigate to this
particular screen. So let's go to the
header component where we have this
create new trip and here we already have
this create trip option. So I will add
it as a create new trip and then save
it. Now once I click on create new trip
it should navigate to this create new
trip. If you see something like this.
Okay. So this is very important. Same
thing you have to do once user click on
send button. So on send we want to
navigate it. So over here we'll say
router dot push/cre
new trip.
So on the click of this button as well
it's navigate to this create new trip.
Now let's divide this screen into two
section.
So we'll go to this over here. We'll add
a class name. We'll give grid grid
column one when the screen size is
smaller. And when the screen size is
medium, we'll give grid column 2. We'll
also give gap to five.
Then uh let's add some padding if you
want. So we'll give padding x to 10 or
let's give complete padding to 10 only.
And inside this we'll add two section.
One for the chat box
and other for the map and trip plan to
display
something like this. See so one for chat
box and one for the map and trip it. Now
next thing for each of these we are
going to create a separate component. So
we are going to create a new folder
called underscore component under this
create new trip and all the component
related to this create new trip we're
going to keep inside this folder. I
think we need to rename this to
components
and inside this we'll say chatbox tsx.
Let's add a default template and then
save it. Now make sure to import this
chatbox component.
So you will see this chat box.
Now inside here uh obviously we want to
add the text area section at the bottom
inside the chat box. So first thing
first we'll add a section two section
basically. So this one for the display
messages
and other section
uh for user input.
Okay. Now for this particular display
section uh I'm going to add some dummy
message. Okay. So here we'll say due. Uh
inside the due we'll add another due.
Over here we'll add a class name flex
justify and margin top to two. And for
this do we'll simply add a maximum width
with a class name maximum width large.
Then background
primary
text white padding X to four padding Y
to two and rounded
large.
Okay. Um and inside here you can write
user message for example. Okay. Same
thing I'm going to do it one more time
but and here we'll say AI agent message
or AI message and in this case instead
of justify in we'll say justify start.
Now if I go back here this is how it
looks. Uh obviously for this AI agent
message we want to give a gray color. So
we'll say grade 100 and text black.
Something like this. See? Okay. Now once
you have all the message list you can
just start displaying it. But for this
particular uh section we'll add a class
name and we'll make it flex one and
overflow y auto.
So you can able to scroll it. Okay. So
we'll say overflow y auto and padding to
four. So this is the message list. Now
at the bottom where you want to add a
user input. we want to add similar input
that we added inside the hero section.
So I will just copy that particular
uh input. So inside the hero we have
this input box. I will copy as it did
and we'll paste it here. Make sure to
import this text area button component
and then this send icon.
So everything is look correct. Okay. So
on send method we need to call it.
So this onsen method we are attach we
already attached to that send button
right. Uh so I think everything is
correct. So here we have an header
issue. It's weird.
Okay. So basically uh if you see we have
that error that we we are using a
function. So our hero need to be or not
hero but chat box need to be on the
client side. So at the top make sure to
add that and if you refresh it now if
you see it don't have any error. So
currently we have this beautiful input
boxes but it's coming at the top and we
want this at the bottom. So for that
one, for this particular div, you can
add a height. Let's say 90 vertical
height. And we'll make it flex flex
column. And that's all we needed.
Something like this. See, instead of
this one, we'll say 87 vertical height
or maybe 85.
Perfect. Okay. So here you have option
to enter the um input on the click of
send it will send the message and then
it will go to the AI. So that's how you
need to create this UI. It's simple
right on the right hand side obviously
we'll implement the map and trim planner
once we have all the information in
order to display it.
Now after implementing the UI for the
chat box, it's time to connect our
application to the AI model so that you
can ask the question and AI will return
the answer for us. But in order to uh
plan the trip there are couple of things
that we need to keep in mind. The very
first thing that obviously you um we
need to get the source and destination
for the trip from the user. After this
we need to get a group size whether it's
a solo trip, couple trip, family trip,
all the friends. Then we need to get a
budget whether it's a low, medium, high,
trip duration, how many days user want
to uh make this trip and if there are
any special requirements or travel
interest everything uh when you can get
it from the uh users and obviously AI
will uh our AI need to be asked this
question one by one and that's the
reason I created this beautiful prompt
which will help us to get this uh ask
this question to the user one by one. So
make sure that user of this AI will not
ask the question um or multiple question
at once so that user can enter each
questions answer one by one and in order
to add a generative UI made sure that
our response will be in the form of
JSON. Okay. And obviously in the JSON
format we have the response and the UI
uh whether it is a budget UI or we want
to show or group size UI we want to show
everything I already mentioned inside
this prompt. Okay. So once we have this
prompt we can use this one. I will also
share this prompt with you. You will
find the link in the uh description for
this documentation where you will find
all of these flowchart and um diagrams.
Now uh let's go back and very first
thing that we need to do is to create an
endpoint for our AI model. So I will go
to this API. Inside this API we'll
create new folder called AI model.
Inside this we'll create a route.tsx
file and then simply add
a post request. So here we'll say a sync
function as this is a post request. So
we'll say post
and then next request. Now to this post
request we need to get a messages list.
Okay. Obviously this messages list we
need to send to the AI model each time
so that AI will know what all
information he already has. Right. So
we'll say request.json
and then save it. Now in order to use AI
model there are bunch of different AI
model you will find on the internet like
Gemini open edge chat GPT uh deep sync
and many others but I'm going to use a
free AI model which you will find on the
open router.ai.
Open router will give you all the AI
model at one place. Many of them are
free to use. So if I go to this model
section and if you see now this new
model came which is a free model.
Obviously you can just switch this
pricing to free and boom you'll find all
of these free model which you can use
like deep sync R1 model or Mistral
Google Gemini model and many others.
Okay but uh it's up to you how you want
to go. I will use the chat GPD's uh AI
model like 4.0 mini. Okay, I think that
is sufficient for us. Once you click on
this, go to the API section and inside
this we can create an API key. Now if
you don't have an account, make sure to
create a new account. I'll go to this
create API key and then we'll select
create API key. Give the API key name.
So here we'll say AI trip planner.
Then you can limit the credit as well
and simply click create. Once you have
this API key, make sure to copy it
because otherwise you will lose it. it
will not display it again and then
inside your env or maybe env.lo you can
simply paste it. So here we say open
router API key is equal to and paste
this key and then your application name
will display over here. Okay, as simple
as that.
Next I will go back to that particular
model and if you scroll down you'll find
with the help of open um go make sure to
select TypeScript and with the help of
open router HDK you can easily make an
call but if you want to use open AI HDK
instead of open router select this
framework documentation if you get this
page not found select return home and
over here you'll see the TypeScript
option where you can use the open AI SDK
now in order to use this open AI SDK.
First thing you need to install the open
AI. So I will simply add npm I open AI
and make sure to in uh install this.
Once you install simply copy this first
few lines of code which initialize this
open AI see now you can even export this
one so that you can use it in some other
API routes. uh we don't need this
default header. So I will remove that
and instead of this API key I'm going to
use our API key from this env file.
So we'll go to this env file open router
API key something like this and make
sure to pass it. Okay, now you have the
open AI initialize and then you just
simply need to call this method in order
to get the response.
Okay, as simple as that. Now for the
model, make sure to update the model
which you are looking. So in this case,
you want to use this model. So you will
see this copy button. Make sure to copy
that model name and then simply paste
here and then save it. Okay. Now under
the messages here, you can you need to
pass all the messages. Okay. But before
that I'm going to add a system prompt
that is very important. So inside the
role I will pass it as a system and then
for the content I'm going to pass a
prompt. Now I already have prompt inside
the eraser doc. Simply copy this prompt
as it is and we can paste it at the top.
So we'll say constant
prompt is equal to and then paste this
prompt.
Okay. Once you have this prompt you this
prompt you need to pass to this system
and then for the user role you can
simply say dot dot dot messages because
we want to send all the messages list
then you'll get the response. You can
get this response over here inside the
message is equal to
completion dot choice dot message.
Okay. And then in return
we can simply add next response dot
JSON. And here we'll say JSON dotpass
messages dot contain because you will
get in the form of string might be. So
make sure to pass. If the content is not
there I'll pass it as empty. Okay. Now I
also make or wrap this line of some few
all this line of code inside the try
catch block.
So in case it fails, it will return the
empty response.
So right now I will pass it as error e
only and then save it. Okay. And that's
how our initial AI model is ready. Okay.
So over here make sure it's not string.
It's a prompt that we need to pass.
Okay. And if I go back, obviously
nothing will get changed. Now, whenever
you enter something and on the click of
this send button, we need to make sure
to call this particular API endpoint.
So, what I will do, I will go to this
chat box inside here we are on send
method and then we need to make an API
call. Now in order to make an HTTP API
call you need to add an AXIOS okay AIOS
HTTP client library which help us to
call an API endpoint. So over here now
we'll say constant result is equal to
await axios dot get
or not get it's supposed to be post and
then we'll say / ai ai model and inside
the body we need to pass a messages
right right now we don't have messages
list so we'll define a state
which hold all the messages
now Um you can even provide the type for
that messages. Okay. So I will add a
type
message message
and in that one we have role as a string
and content as a string
and here we'll say messages of array
list and initially it will be empty.
Then
whenever user enters something we need
to get and save it in a state called set
user input
and which is of type string. So inside
this text area
maybe we can add on change method which
will emit the event and then we'll set
the messages with the event dot target
dot value
and default obviously we going to pass a
default value called user input as well.
So if there is a no value uh we'll pass
an empty string. I don't know why we are
getting this error.
Oh, sorry. So, this need to be
an user input, not messages. So, that's
the reason we got this error.
Okay. And then save it. Perfect.
Now, on the send, we have to make sure
first thing first, we need to set the
user input
uh as a empty one. Okay, you can say
null. Then we want to add that message
inside this messages list. Okay, so uh
we're going to simply add constant new
message
is equal to uh we'll define a message
type first and then we'll say role as
user and then content
as user input. Okay. So this is
important so that you can pass this.
Now obviously we have uh error that user
input need to be there. So if the user
input is not there
will return nothing.
Okay. So this need to be a not user
input dot trim.
So it will return nothing otherwise it
will go to this page and then we have
this user input with a new message. And
then over here we can set the messages
saying uh add a previous message.
And then we have the previous message
with new message
make sure to wrap
something like this. Okay. Now once we
have the messages just pass this me uh
over here actually we need to pass uh
the messages list first. Okay. So we'll
say all the messages
comma the new message. Now you might
have a question why we are doing like
this because when we update this message
state it's not updating immediately
right. So that's the reason I kept this
new message as a different constant and
then I'm passing the all the previous
messages with a new message. As we are
using await, you need to make this as a
async.
And then once we have the result, you
can set the messages
with the previous over here. We'll say
previous colon messages.
And then inside the arrow function,
we'll add previous message. Make sure is
a three dot is a se uh
spread operator. Okay. And then we'll
say role as assistant
and then content as result
dot data dot response. Okay, because
we'll get the response um if you see our
schema schema contain the response,
right? So that's that field I just
mentioned over here. And then save it.
Later on we might need to update this
but for now I think we are okay and then
save everything
over here I will just console the result
dot data in order to check whether we
are getting the result or not so let's
head back obviously we are not iterating
the list but inside the inspect panel we
can verify it
now here we'll say hi first we'll pass
this and we are waiting right now if you
see we did not get any response from the
AI model.
So also make sure to check
the terminal
if you have any error or if we miss
something. So basically we have an U
response. So if you see we have the
content and then inside the content we
have this UI as a source but it's not in
the correct format. So right now we are
getting the content as a string and
that's what we don't want it. So
basically you can mention over here
saying response format and then we have
to provide a type with this JSON object.
Okay. And then save it. Now I will say
hi. We'll send this one. Go to the
inspect panel inside the console. Now
we'll get an object. Okay. Let's try
this again maybe.
And boom. If you see now we have the
response and the UI as well. It
mentioned which UI you need to render.
But obviously for some of the uh field
we are going to show a generative UI as
well. But for now I hope you understand.
Now once you have the response and uh
all the information from the AI simply
we have to iterate those information.
Okay. Now in order to iterate inside the
section
I'm going to add the or we just going to
reiterate these messages comma map here
we say message comma index and the arrow
function message need to be type message
and then we'll add this both the div.
Obviously we don't need to show both the
div. Okay but before that what we can do
we can add a condition. So we say
message
dot ro is equal to equal is equal to
equal to user then we want to show
uh only this first div okay otherwise
we'll show this second div which is then
ai agent view message right now the user
message we need to replace with the
message dot content and this one also we
need to the message dot content
uh we can provide the key as a index
at the both the place and once you save
this one let's refresh this over here
we'll say hi send the message
and boom if you see we got the response
how cool so you can just now start
chatting so for example we'll say okay I
want to traveling from the Charlotte and
then AI will ask the next question then
now we will Okay. New York.
Boom. See how cool it is. So that's how
you need to um
uh attach and integrate the AI model.
Now next couple of things that we need
to update. For example, the loading when
you send and response, we need to show
some kind of loading indicator. Right?
Second, we need to replace this
placeholder. So first I will replace
this placeholder because that's quick
thing.
So we'll say start typing here.
And uh in order to add a loading
indicator that's quite easy. You need to
maintain a loading state
and initially it will be false. Once you
start asking question we'll set the
loading as a true and once it is
finished we'll set the loading as a
false. Now whenever there is a loading
we can simply show that indicator. So
over here inside the div right inside
the content basically we can add a
condition
if loading
then we can show a loader icon
otherwise you can show the message
content. For this loader icon I will add
this animate spin. So it will spin it
and then save it. Now let's try this
out. So I say hi
and somehow it doesn't work. Let me
refresh this.
Oh, so that's might be not working as
expected.
Basically instead of showing this
loading over here, I will just undo
everything. Okay. And what we can do we
can simply add the loading indicator
after these messages every message.
Okay. So simply I will copy this due
because in place of that D we need to
show uh we don't need this index and
instead of the message content we'll
show a loading indicator. So we'll add a
loader icon
and to this loader icon you can animate
that using animate spin teleps class and
we want to show this div only when there
is a loading when the loading is true.
Okay now once you save we'll say hi send
it and boom if you see we have this
beautiful loading indicator
and then you will start asking question
see how easy it is. So that's how guys
you need to uh add these details.
Now whenever there is a empty state
right so once user land on this one it's
showing a blank and that's not look
good. So you can replace that with an
empty state. So basically I will add a
new component. We'll say empty state
or empty box state we'll say box
state.tsx.
We'll add a default template and then
save it. Now whenever the message length
is empty, so we'll say messages
dotlength
is equal to equal to zero. Then only we
want to show this empty state box.
See something like this. And inside this
empty box state you can add some
heading. So we'll say
start planning new trip
using AI
and obviously you can't wrap this with a
strong tag
and I will add a class anime sorry uh
text primary
for this H2 tag I will add font bold
text
excel
and text align in the center.
Perfect. Um we'll give some margin top
and this text you can just add 3xl
large. Okay. Um you can add some head uh
sub description as well. So I will just
paste it. I already have. And then once
you save, we'll go back to verify how it
looks.
Uh maybe you can add a class name text
to be in the center. Then text gray
and margin top to two.
Perfect. And also you can give the
option to select uh some information.
Okay. But I think that's a easy way if
you don't want to add too much things
into your uh chart area.
You can simply bring this those option
that you added inside your hero. So I
will just go to this hero.tsx file.
These are the suggestion option we have.
So I will copy that or we can simply
export this. So you don't need to copy.
And then
this is the suggestion list. Right? I
will save this one. We'll go to our
empty state box
and simply paste it here. Now make sure
you import you can import this
suggestion because you already exported
it right. And if I save this one this is
how it look like but we want in a
vertical format. So don't if you make
this flex make it flex column
and I will not make rounded full. I will
say rounded excel and we'll give more
padding. I will add Excel as a text.
Perfect. Excel is too much. Let's make
it large and padding to three. Let's
see.
I think that's much better.
And here you can select those option as
well. Now instead of making the
background primary, I will just make
border
primary.
See? And don't want to make this text
white. I will make it as a primary as
well.
Something like this. I think that's look
much better. See,
now once you click on any of these
option, we have to make sure uh that
particular option you will pass it. So
basically uh you can add on click method
to this particular div and you need to
pass back to the chat box. So we'll say
on click
on select option and then you need to
pass that option. So we'll say
suggestion dot title. Now this on select
option
I will pass and type any and then inside
the empty box state we'll
think we need to get that
and we'll say on send method. So inside
the onsign method we need to call but uh
we need to make sure
we'll set that input. So over here we
have the value of type string
and along with to make that onsend call
we also need to set it as a user input
with this value v. Okay. And then save
it and let's test this out. So I will
say create a new trip. See it's coming
over here.
Right? And once you send this, you can
uh AI will start uh working on your
request as simple as that. So that's how
you need to uh implement it so that uh
you will not see that uh empty box and
here or not empty thing but you can see
some content when you jump initially on
this particular page.
Now it's time to display the generative
UI where if you see this mockup along
with the AI's response we are also going
to show an UI component which help us to
directly select the option. Now this
component obviously we need to build it
but AI will tell us that which component
need to be rendered for that particular
message and that's why in our um prompt
we added that particular
um line if I scroll down little bit up
inside our prompt where you'll find that
uh the generative UI these are some
types that we are going to build it okay
and also So under this UI field, it will
return that particular type. So first
thing first, I will just update to small
F for now.
And then let's close all of this tab.
And first thing first, we'll go to our
uh create new trip chat box. And inside
here, we're going to add a new field
inside this message called UI. Okay?
because we also need to get that UI
string. So that's the reason I'm adding
this. Then make sure you will set that.
So over here we'll say UI with
result dot data. So we'll say result dot
data dot UI so that we can easily
uh use that in order to render that
particular UI. Now in order to render
the UI we say constant render generative
UI as a new method and this will accept
the UI of type string
and depends on which UI for example
let's say we want to render the budget
UI right and that's what AI response
return to us then we have to show a
budget UI component right same thing if
the UI compi is equal equal to
group size then we have to render
uh group size UI component
something like this. Okay. Now the
question is obviously we need to build
this particular components and this
method we need to call. So this need to
be a generative
render. This is just failing mistake.
So once you create this method, you need
to render this method over here. And
make sure to pass message dot UI.
Oops. Message.
Make sure it's not empty. So I'll pass
an empty string. And over here as well,
we'll say undefined. I don't know. I
think we don't need to show undefined
uh obviously but over here we need to
return something right so that's the
reason we is throwing an error now let's
implement for the group size component
so what we can do we can go back over
here we'll create a new component called
group size
UI dot tsx
then we'll add a default template. Now
inside our eraser do I already added the
list of group sizer we can use it. So I
will just copy that and then I will
paste it over here
so that we can easily iterate it. So
we'll add we'll just iterate that. So
we'll say selected travel list dot map
here we'll say item comma index and the
arrow function inside this we'll add a
div
and first we'll say item dot icon that's
a simple emoji icon that we are going to
show and then we have item dot title
here we'll say key as a index then for
this due we'll add a class name we'll
say padding to three we'll add a border
we'll make a rounded corner to 2 XL
background to white on hover.
I want to add a border to be primary
and we'll make cursor
pointer as well. Okay, I think that's
all we needed
and then save it.
Now this group size UI over here, I will
just return this particular component.
Make sure to import this component and
then save it. Now if I go back, I will
just refresh this once here. We'll say I
want to travel from
Charlotte
to New York. Okay. And I will send this
one.
And boom. If you see, we have beautiful
UI now rendering on the screen along
with the question from the AI response.
Right? Obviously we will just uh add
some styling. So over here I will mark
it as grid grid column four or we'll
make two and on medium screen size we'll
make it four. Then we'll give gap to
let's say two item to be in the center
margin top to one and then save it.
Boom. See how beautiful. Now once you
select any of this option obviously we
have to make sure that we will pass back
this uh user selected response to the
chat box and then we need to call this
on send method. So for this one
uh let me bring this down. Here we'll
add on click method and to this onclick
method we'll say unselected option and
we'll call this okay over here we'll say
item dot title plus along with this one
I'm going to add how many number of
people are there right so that
particular count I'm going to say same
people and title as well and obviously
make sure to pass it you can pass type
any and inside the chat box I will
accept that. So
I will get this on selected option
and then simply you can call set user
input. Now make sure to accept that
particular value
so that you can set it and also call on
send method. Okay. And then save it. Now
if you select any of this option and
boom if you see we got the user input
response as soon as user select any of
this option and then after that AI
returning are asking us the next
question same way now you have to build
this UI component for the budget uh as
well so let's go back to our app and
let's create a new component for budget
UIT tsx Over
here we'll add a default template. Then
I'm going to get these particular budget
options which is available inside the
eraser doc. And once you add simply you
can iterate iterate those in the same
way.
So I will simply copy this same
structure as it is
and instead of this one I'm going to add
this selected budget option.
then make sure to return the same uh
method. Okay. And instead of this title
now we'll pass as description
and save it. Now if I go back to our
application
uh okay so make sure inside the chat box
you will add this. Okay.
So same return statement but different
component now. So here we will say
budget UI and boom. Right now if you
want to add more uh styling to this one
you can add it and let me show you how
you can do it. So for example for this
div
uh you just want to add
some kind of background. So we'll add
this as a div. Then inside the class
name we'll say text is of 3 XL. Then
padding to three and rounded
full.
Then we have the H2 tag. For this one,
we'll say text large
and font
semi bold margin top to two. And also we
can add a description. We'll say item
dot description. For this description, I
will add text smaller and text gray 500.
I think we can add some color
combination as well. Okay. So, we
already have I'm already providing the
colors. So, I will add that.
So, maybe over here
we can add the colors. So, let me put it
inside the curly braces with this tag.
So we can dynamically add a color.
So we'll say item dot color. See
something like this. But we have to make
sure it will be in the center.
So for this div we'll say flex flex
column item to be in the center and text
to be in the center.
See
uh obviously you don't need to provide
this uh obviously make sure it's a three
now
perfect and now we have this different
UI from the previous one right so it's
up to you how you want to provide okay
and give the better look each time
next uh obviously once I select any of
these right if you see it's
and and then it now AI will ask the new
question. So guys that's how you have to
do and add the general UI for each of
this question.
Now I will pause the video and I will do
it for the uh number of days. Okay. And
I will implement that. Now here I also
added the number selection that how many
days user want to travel where user have
option to select these days and then and
once after this we have this final
things where we are showing that your
plan is getting uh generating in the
background and then we are show we are
going to show this beautiful uh message
or loading message uh only inside this
final view I'm going to add class name
with a margin in top to two and also
we'll provide a width full okay
something like this and once we have the
uh trip information then user can view
this particular trip on the right hand
side and then we'll enable this button
as well so that he can able to view the
trip okay so this is how we are going to
generate uh the UI in the runtime with
the help of generative UI tech okay so
if you any question any doubt let me
know in the comment section before going
uh to the next chapter let's test this
out one more time okay so here I will
say hello
I want to travel from
New York
to Mumbai okay and I will send this
message now obviously we only provide
the source and destination so obviously
AI will not ask this question again and
again that is smart that's how smart it
is now we are try with. So I will try
alone. Okay. And uh what your budget so
I will select moderate.
And then it will ask how many days you
are planning. When it ask me how many
days. So I'm planning for 7 days. Okay.
And then it will ask any other question
if I any. And now if you see now it's
saying that your uh inform uh with that
current information um the trip is now
generating. Okay, it takes some time
obviously but whenever we have uh this
final step right that's why we have the
UI component UI field with the value
final then we have to make an API call
in order to generate the final uh result
that is very important. Okay, that's
what we are going to see next. But until
this point I hope you have understand
everything. If you have any question any
doubt let me know in the comment section
because there are lot of different
feature that we are going to add in this
particular uh project.
Now it's time to generate the final
itenary of our tree depends on user
provided information with the help of
AI. Now once user uh reaches at this
place where UI is a final and currently
if you see we are getting this generated
UI because we set it whenever the UI
field is mentioned as a final right. So
in that case we have to send another API
call in order to generate the final uh
trip details. So to do that we are going
to simply check whether the last message
contains the UI field as a final or not.
Okay. So we'll go back to our
application
and inside this we have this chart box
and inside the chat box I'm going to
use the use effect. Now this use effect
will execute whenever the messages
uh is updated. Okay. And once the
message are updated then we say constant
last message is equal to messages of
messages dotlength minus one. So it will
contain the last message whichever last
message there. And then we'll say if
last message dot UI is equal to equal to
final. Okay, then only we'll set is
final as a new attribute or new state.
Okay, so what we can do? We can just
mention that state. So over here we say
is final comm, set is final is equal to
use state.
Initially it will be false. And over
here once there is it's final then we'll
set it as a true. Okay. And once we set
it as a true
we are going to call on send method as
well. So this method now we have the on
send correct but in this case we are
going to send is final as a parameter
over here. Okay. Obviously initially it
will be false. Now let's go to this AI
model
uh under this API and then we are going
to accept that
is final. Okay. Now whenever there is is
final is true then we need to update
this prompt. We need to change this
prompt so that uh it will generate the
final
uh trip information. So to do that I
already have this particular prompt
ready. Okay. Now this prompt will
generate the all the information which
you need the trip planning plan the
hotel information the eternary day wise
and everything. Okay. This is a schema
and this is the prompt. So I will just
copy this as it is and then I will paste
it inside the route just below this one.
So this is how it look like. So now we
have this final prompt and this final
prompt we wanted to
show. So over here we'll say is final.
If it's final is true then we'll u pass
as a final prompt. Otherwise we'll pass
the simple prompt. Okay.
And I think that's all we needed for
now. And now if I go to the chat box uh
wherever there is is final you don't
need to set the message. So make sure
that
okay. So if is final is not true then
only we are setting the message
otherwise we will not set the message.
Okay but I will just console
over here
so that we'll get to know whether we are
getting the correct data or not. Okay
let's save it for now and let's test
this out. So we'll go back to our
application
and we'll refresh the screen. Now before
test this one just make sure to add one
quick change. Whenever you set it as a
final also set the user input with some
value will say okay great okay because
if you see inside our on send method the
user input need to be there say this one
right so that's the reason it is very
important that you will set some user
input and uh that is uh important okay
now let's test this out so we'll say
create a new trip Okay. And then we'll
simply say we want to Mumbai to Goa
trip.
Okay. So it will ask uh
with whom you are traveling with then
budget
and I will uh set the date as well. And
if you see it start generating.
So only thing that it's uh if you see
it's not make any call yet. Okay.
Because uh maybe it let me check the
issue. So once we set the final we'll
set the user input and then we'll click
on on send button. So that's good. Um
let's make sure that you are getting a
final one right. So that's what we
needed.
So I think we need to test this again.
So that's weird.
Maybe we can just hide this one. Okay.
And uh then we'll test this out. So
right now I will just say okay.
And now if you see it start generating
and inside the payload you will see is
finally is true. So it once the loading
is completed you will see that output as
well. Okay. See now we got the trip plan
and inside that we have hotel
information we have it turnary
information the all the details see okay
so that's how we need to do it I think
um you can test this out again okay and
hopefully it will works so only thing
that when you update the user input
right it's not updating immediately and
that's the reason uh it's not going
inside this ons so sometimes it happens
So the another option is to fix it. I
will just commented this on send and I
move this to an use effect. When this
use effect will execute whenever there
is final is true and the user input is
there then we have this on send method.
Okay. So now if I test this out here we
say um
Mumbai
to Kova 3 days. Okay. Now once I ask it
will not ask me then again the how many
days right so we'll say that I want to
travel with the friends with a moderate
budget and then if you see it start
generating as well okay now inside the
console we can just test this out right
now it's still loading because it's a
big chunk of data that we are expecting
to get it so that's why it's taking time
and boom if you see we got the trip plan
information how cool right now whenever
uh you we we got the information we want
to enable this view trip button. Okay.
So simply
um over here we are going to save this
trip information first. So we'll say
constant
trip detail
comma set trip detail is equal to use
state. Okay. And uh obviously we need to
define the type for this one and make
sure once you get the data. So over here
we'll say is final if it's oh sorry
we'll say inside the if
uh is final is true. I will just move
this block of code
just below this one. Okay. So we'll say
is final is true.
Then we'll set the trip detail
with the result dot data dot. And if you
see our information inside the trip
plan. So I will save it inside the trip
plan.
Okay. So let's move this up. Something
like this.
And whenever the trip detail is there
then we want to enable the button.
So simply what we can do
uh okay so the button is inside the
final UI right. So over here we'll say
disable this button only when the trip
detail is not there. Okay. If trip
detail is not there then disable it and
we'll go to the final. over here we'll
say uh trip detail
or we'll say disable
I think that's what we route right so
disable correct and then we'll pass this
disable
whenever the disable is uh true then
only it will disable that particular
button but once we have the uh trip
information then it will not disable
perfect now uh one last important thing
uh because we already saving it. We need
to define a type that is very important.
So I will define a type over here. We'll
say trip info
and inside the trip info we need to
write a budget destination everything.
So we'll say budget is of type string.
Destination is of type string. Then we
have the duration group size.
So make sure to copy everything as it
is. That is important.
Then we have origin.
Okay. And then we have hotels and
itinerary.
So right now hotel contain the list of
array. Right. So for now I will give the
type any. And then last we have the
itinary
that is of type any only.
Okay. And this strip information
I will set it here
something like this. Okay. And then save
it.
So I hope you understand this particular
um functionality that is very important
in order um to go to the next chapter
because once we have this all the
details then we are going to display it
on the screen.
Once you create this trip, it's very
important to save it to our database so
that next time whenever uh user want to
fetch the trip details, he can fetch it
from his dashboard. Okay. So to do that
simply uh we need to create a table
inside the convex. So we'll go back to
our application and inside the convex
schema file we'll add it. So go to the
convex schema.ts.
Inside this we'll create
trip detail as a new table. So we'll say
trip detail table. Then we'll say define
table.
And inside this we need to define it. So
first thing we want to add a trip ID
which will be the unique ID. So we'll
say v dot string. Then the trip detail
is of type JSON. we say v dot uh I don't
think so we have JSON but you can put it
as a any and then the user ID right now
the user ID we already have inside our
context we just need to pass it so over
here we'll say B dot string
instead of string we need to pass an ID
because this is id and then you need to
refer it so we need to refer with the
table name which is
user
table
I think something like this okay because
this table name need to be here I think
that's all we needed and then save this
one once you save obviously uh the
created by and everything will be there
but make sure the user table is now
added uh to your convex see perfect now
let's go back
to the uh we'll create a new convex
function actually in order to save it.
So we here we'll say trip
detail.ts TS file and inside this trip
detail. TS similar like a users right we
need to create a mutation. So we'll say
export constant trip I will say uh
create trip detail
is equal to mutation.
Inside this mutation we need to accept
arguments like trip id
which is of type string. Then the user
ID of type
make sure to input V of type ID
and here we'll say user table
and then last we want to accept the trip
detail information
which is of type any.
Now once you add we need to add a
handler
uh handler is of type async. So I will
just verify that. Yeah that's correct.
And inside that we have ctx
comma arguments and the error function.
Then we'll need to save it. So we'll say
constant result is equal to await ctx
dot db dot insert.
The table name is um trip detail table
and then we need to add the value.
So if you see the the same way that we
added the user you need to add the trip
detail information. So first thing trip
detail. So we'll get it from the
arguments dot trip details. Then the
trip ID again from the arguments dot
trip id and then user ID which is also
from the arguments dot user ID something
like this. Okay. And then save it. Once
you save you can return the data if you
want. Okay. Or you can leave it as it
is.
Now our trip detail convex function is
ready.
Now I will go to our chart box. inside
this chat box we need to
uh initialize that mutation. So we'll
say constant
save trip detail is equal to use
mutation and then we'll say API dot trip
detail dot create trip detail and this
save trip detail we need to call so we
already have is final right inside this
we'll say save trip detail or we'll
something write something like this is
equal to await save trip detail and
inside is we need to pass a trip detail
information. This this trip detail
information you can get it from this
result. The trip ID you can get the trip
ID from the or obviously we need to
generate this one. And then we have the
user ID. Uh user ID you can get it from
the context. So we'll define a user
detail context over here. So we say
constant
user detail
user detail comma set user detail is
equal to use user detail. See this
particular hook we can directly use it.
You don't need to mention the context
and then the what which context you want
to use. Okay. From here you can directly
use that and then we'll say user detail
dot ID because the field is saved as a
underscore id. Okay, here you don't need
to mention the result. You can uh left
it as it is and then save this one. So
this will also save our trip. Okay, if
you want to notify user with the toast
message that trip is saved, then you can
mention that one as well.
Now in order to pass a unique trip ID, I
will search for this UU ID V4. Okay, not
this one.
Uh just search UID V4 package. Okay, so
it will jump onto this package. You just
need to install. So I will copy this
and inside the new terminal. Make sure
to install that. Once it installed you
can directly use it with the help of
this UU ID v4 function.
So maybe we'll say constant trip id is
equal to uid v4. Make sure to import
this statement and it will generate a
unique global identification number.
And now just pass this trip ID.
Okay. And then save it. As simple as
that.
Now obviously you can test this out. So
I will create a new trip.
Now I will just say Mumbai Tune I want
to travel. So with the family then
moderate budget
confirm 3 days.
So I think there is some problem. Uh
let's see what's the issue.
I don't see any issue over here.
It was still working. So that's the
reason. Okay. And now if you see the
trip is generating. So we have this
final and we'll wait to finish this.
Once it finished, we got the trip
information. I will just make sure
inside the trip details. You will see
the new record get added with the ID.
The trip detail obviously which contain
a complete JSON. Then we have the trip
ID as well. the user ID uh obviously
which is connected to that particular
user. Okay. So that's how guys you need
to save the trip information to your
database. Now with the help of this uh
trip id you can easily fetch the trip
information directly.
So you don't need to uh f uh do
anything. Also just wanted to uh tell
you that this view trip button is now
enabled. Okay. And obviously uh on the
click of that one we can show that
particular trip.
Now it's time to display the trip
information. Now we want to display in
some modern way that it looks much
attractive. Now in order to do that
first what we can do we will just copy
some dummy information. So from this uh
network tab we'll check this one. So
we'll say uh make it 2 days. I will just
getting the trip detail information.
Right now if you see it generating this
trip detail information this we are
going to save as a dummy data in order
to display it. And once our UI is ready
then we can simply uh uh replace it with
actual information. So I will copy this
response as it is. We'll go back to our
page. And inside this one, we are going
to create a new component.
We'll name it as a iternary
tsx. And then we'll add a default
template. Now this itenary we need to
add it inside the page.tsx file.
Something like this. And then save it.
Now first make sure that is displaying
on the screen. See something like this.
Right? And on this side we want to
display that trip information.
Now inside the itinary
I'm going to add that demi data. So
we'll say trip data is equal to and
paste this. Make sure we don't want this
trip plan as a field. So we'll remove
that
and we'll only keep what we need. Right?
Obviously it contains all the
information. So this is the first step
that we wanted to display it. Right?
Next thing
uh we'll close this one. We want a UI
for it. So for that one I'm going to use
this assert assertinity UI uh which is
based on shad. So you don't need to
worry about this. Simply go to the
components and then scroll it to the
component called timeline. Now this
timeline component will give you this
particular uh UI component. See how cool
right now obviously we will replace this
particular information with a day one
day two and on the right hand side we
can show an actual information the place
information and that's how we are going
to use this particular component. So in
order to install go to the CLI, copy
this npm and then simply install it
using this command prompt.
Once it is installed,
it will available inside your component
folder under the UI timeline.tsx file
where you can customize completely.
Okay. And now we'll copy this example as
it is. Inside this example if you see we
have the data and I will copy everything
and then inside the timeline we will
just simply passing this data. So in
same way I'm going to replace this
return with this information. Make sure
to import this timeline
statement
at the top. I will close this and then
save it. Once you save and if I head
back to our application, boom, you will
see this beautiful change, right?
Obviously, there are lot of things that
we need to customize it before
displaying all the data.
Now, first thing first, um obviously we
don't want this ugly scroller, right? We
just want to make sure that uh it will
not scroll complete screen. So, similar
like the chart box. So if I go to the
chat box if you see the maximum height
which is height 8 85 vertical height
same height we are going to give it to
this itonary. So over here I will say
height to 85 vertical height. Now if you
see if I refresh this screen
it's still scrolling right. So maybe we
can say overflow
auto and then save it. And now if you
see it's scrolling only that particular
part. Cool, right? I will just make sure
to 83. I think that's much better. See
now it's completely fixed.
Now next after this uh we need to update
all of this content this particular
empty space and lot of other things. Now
for that one I will go to this timeline
component. Inside the timeline component
it has a dummy data. See this one.
Obviously we need to replace this data
with an actual information. So over here
we will just uh say something like your
trip itinary
from and then we want to add a source to
destination is ready. Okay something
like this. So over here we we want the
information from this trip data because
inside the trip data we have the
destination and the origin right now in
order to pass this trip data we can pass
this complete trip data to the timeline.
So over here we'll say trip data and
then pass this trip data. Obviously
inside the timeline
you need to accept this trip data.
Sorry. Over here you need to accept it
and you can provide a type or make sure
it's a trip data
and the the type will be trip info and
then save it. Perfect. Right now next
over here we'll say trip data dot
uh origin and here we'll say trip data
dot source sorry destination. And if I
save this one, you'll see this change.
Your trip itary from Mumbai to India.
Okay. So, oh this need to be an
destination.
Yeah. See your trip it from Mumbai to
India to Goa is ready. Now you can even
wrap this in a strong tag
and change the color. So I will change
this to primary.
And same thing I'm going to do for the
destination as well.
Here you can customize completely
everything you can customize in this one
right and this is how it look like. Next
thing instead of this P I am going to
replace with the some uh uh user
selected options. So over here I will
add a D. I will add a calendar and then
inside here I'm going to add the
duration. So we'll say trip data dot
duration
and this is how it looks. We want
everything in one line. So I will add
flex gap of two item to be in the
center.
Perfect. Same thing I'm going to copy it
few more times. Secondly after this I
want to add a budget.
Here we can add a wallet icon
and here I will say budget. Then group
size and here we'll say people or I
don't know users.
I will just get that per perfect icon
for it.
So we want many users. So maybe users we
can say users.
And if I save this one, this is how it
look like. Obviously, we want everything
in one line. So, we'll say class name
flex gap to five item to be in the
center. And boom. How cool it's looking,
right? Perfect. So, that's how you can
modify it. You can add more text if you
want. You can add more styling as well.
Now, again, uh we want to we don't want
that much space at the top. So, we can
remove that space as well. So here
instead of padding Y to 20 we can give
padding Y to let's say seven. So it will
move up. Then we don't want this empty
space as well.
So after this we can scroll down
and I will just make sure that there is
no margin or padding from the top. So
over here if you see there is padding
top to 40. I'll make this to 10.
And now it's move up. Okay. Also there
is a lot of width between these uh two
section. So that also we can replace it.
So in order to replace that particular
width so instead of this width full
we'll say width 40%.
I think that's much better. See perfect
right? So that's how you can update your
timeline. Now our timeline design is
almost ready. Now we need to replace
this uh demi or um default data with our
demi data and then later on we will
update this dummy trip data with an
actual information whenever the new trip
is generated. Now let's uh display the
list of hotel first. Okay. And I will
also change this size of this particular
text. So inside the timeline
if I go to the title
here we can make to excel
I think let's refresh it and see I don't
think so there is any change okay so
maybe over here we make it 3 excel I
think this is much better perfect
next I will go to the iternary and here
now we need to map our trip data with
this particular format where we need to
provide a title which is nothing but
this particular left side uh title and
then the content whichever the content
you want to display on the right hand
side in any format okay so first thing
first uh
I will just remove everything so we
don't want this one right we'll just
keep this title and the content for the
reference
and u first we need to show and hotels
so basically Then in the title we will
say
recommended
hotels. Okay. And uh after this if I
save this one let's go back. I don't
know why it's gone but now it show
recommended hotels. Perfect. And inside
the content
I will just clean everything.
And inside here we'll say
trip data dot
hotels
dot map
and then we'll say hotel, index and the
arrow function. Right now we don't have
a type called hotel. Okay. So you can
mention that type. You can mention
inside the
our chat box only because that's where
we define the type for the t info. So
over here we'll say export
type
hotels.
Here we will say hotel only.
So here I added for the hotels activity
and day plan and then I'm going to
replace this with the
uh we can say day plan I don't know or
we can call it as a iternary
instead of day plan and then I have
going to replace this with an itturnary
and here need to be an hotel.
Now hotel need to be if you see the
hotels need to be a list right. So I
will make sure that's a list only
and then save it. Now if I head back to
our itinary in order to map this one
we'll say simply say trip data hotel
here. Here here you can provide a type
and then you can map it one by one. So
over here we'll simply say a div or you
can just iterate those. Inside the div I
will show an image first. So image
source tag for now I'm going to use a
placeholder image. Okay, which I already
have in my public folder. Here we'll say
uh place image for now. And for width I
will add 400 height to let's say 200 and
then save it.
key as a index. Now if I save this one
here you will see the place image that's
where that it's not showing maybe it's a
JP image.
Perfect.
Uh then I want to show some information.
So we'll say inside the height sorry H
s3 tag we'll say hotel dot um
hotel name
and that's how the hotel name cames over
here we'll say font
semi bold
um then we can add text large
perfect after this I want to show and
hotel address.
So we'll say hotel dot address
inside the class name we'll make this
text gray 500
text excess
and we can keep the text as it is that
also good
and if you want to show a rating you can
also show a rating along with their
budget. So over here you can add hotel
dot price per night.
Over here we can add
wallet icon
and let's see how it looks. Then let's
bring everything in one line
and you can change this color as well.
So we'll say text gray or we can make it
green
something like this. See
after this
if you want to add a rating for the
hotel because we already have that
rating. So I will add a star icon. Then
I will say hotel dot rating.
And I will change this color to yellow
500.
Let's bring everything in one line. So
we'll make it flex
gap to two.
And we can bring this
together if you want.
So basically
you can say flex justify between item to
be in the center.
So this is how it look like. Perfect.
And if you want you can add a
description as well. So hotel has the
description. So we'll say hotel dot uh
description over here. We'll get class
name and we'll clamp the line to two.
We'll make a text gray 400
something like this. Or let's keep
make it 500.
Now for this div I will add a class
name. We'll make it flex flex column and
gap to one.
So some spacing between all of these. Uh
for the image I'm going to add some
styling. So over here we'll add a class
name.
Uh we'll add rounded corner. So we'll
say rounded to
Excel.
Then you can add little bit of shadow
and object cover. Okay. Can add margin
bottom to two. Let's see how it looks.
And we want those in uh in the form of
grid. So we can show two items in one
row. So we'll say grid grid column one
when the screen size is smaller on the
medium screen you can make it grid
column two. So something like this. See
perfect. Now another problem with this
one right uh this charts box is quite
bigger. So you can even change the size
as well. So in order to change instead
of giving a two column I will assign
three column over here. And then for
this itonary I will give the two column
and one remaining column to the chat
box. Okay. And then you will see the
change. See. So that's how also you can
u modify it. Okay. It's up to you how
you want to uh show it.
Now after this this is how it look like.
You can add some more space. It's
description is optional actually. Even
though you did not add it that's
completely fine. only thing that we want
to add a button and we'll say uh
view details. So we can say view just
we'll say view we'll say font not font
but we can add a variant if you needed
so I will add a variant outline
perfect and inside the class name we'll
give margin top to one
uh we give the gap two here I will make
gap four some more gap okay now if you
want
Now this is just a hotel recommendation.
Now as you know that we are just testing
this out. So that's the reason I want to
remember this one. Okay. You might have
question without any uh chart with the
AI how we are getting because it's a
dummy one dummy data. Right now the next
part is we want to show itterary right.
So if I go back to our application and
over here if you scroll a little bit
down after the hotels we have the
itonary uh day by day and inside that
again we have the activity list.
Now in order to display that one we have
to add the spread operator. So here
we'll say dot dot dot trip data dot
itinary
dot map. Inside here we'll say day data
and the arrow function.
Now over here we'll add a title first
and for the title we'll simply say
uh day
and inside the dollar we'll say
what this need to be
and we'll say day data
dot day. Okay. So it will give you the
first day, second day, something like
this. Then the content that we need to
show. So inside the content
we'll add a div. And over here we'll add
a p tag.
Inside this we need to mention that best
time
and then we'll say day data dot best
time to visit
uh day right because this field will be
we already have now if I save this one
until this point uh okay so we have an
issue so inside the trip data if you see
uh maybe the format is not the correct
one after save if you see we have the
day one and then we have the day two as
as well right perfect uh then next part
I don't know why this is showing okay to
be frank uh this particular error uh
we'll fix that in a moment but before
that now let's show the activity list so
over here we'll say data dot activities
dot map and inside here we'll say
activity
oops sorry
activity, comma, index, and the arrow
function. Then inside here we'll add a
div.
Uh inside this div we'll add a key as a
index and then we want to add a place
name here. First we'll add a image that
will be good option. So inside the image
I will add a source tag. For now I will
add a placeholder.
Then width we'll say 400. Height to 200.
All tag as let's give the
activity dot place name.
And inside the class name we'll say
object cover
and rounded to Excel.
If I save this one and let's see how it
looks. Perfect. See then for this
particular div I'm going to add
a class name or not here but we can
maybe
wrap this inside the div
so that we can make it grid grid column
one on the medium screen size we can
make grid column two with a gap of four
something like this see beautiful right
so So that's how we can display after
this u place image. Obviously we are
going to replace this place image with
an actual image of that particular place
later on. But now let's add an H2 tag
with an activity place name
place name. Uh for this one I will add a
class name font semibold
and text larger.
Then
inside the P tag, we'll add some details
about this place. So we'll say activity
dot place details. Uh for this one, I
will add a class name
text gray
500
and I will clamp the line to two only.
After this, we'll add a ticket pricing
if there is any ticket pricing. So
inside the H2 tag we'll add activity dot
ticket pricing
and over here
we'll add a ticket icon as well
and let's see how it looks. See now
let's bring this in one line flex gap of
two
and also we'll change the color to let's
say 500.
I will change the color. So let's say
blue
for ticketing.
And if you want you can add light clamp
to one. Okay, you don't want too much to
display.
Then
after this we can add the
travel time for that location.
So we'll say activity dot
time travel for um each location. Maybe
that's the correct one. Over here I will
add a clock icon
and inside the class name
we say flex text
uh orange maybe I will give and then
gap to two.
Perfect.
And here we can show the best time to
travel as well.
So I don't know which icon uh should I
use over here.
Maybe
you can use timer icon. And here we will
set activity time best time to visit. So
maybe if you did not show uh the about
time that's also fine. So instead of
this one I will say activity
best time to visit instead of this one.
Okay. And let's see how it looks. I
think this is much better. Uh you can
add a line clamp to one.
Okay. Somehow it's not get applied.
Okay. But we can leave as it is. That's
fine.
And I think that's all we needed. You
can add a button to view it. So we'll
say button.
I will add a size small.
And uh I will also add a variant to
let's say outline.
And inside this we'll say view.
Let's add a class name. We'll say width
to full margin top to two.
Perfect. Where user can view that
particular location.
Over here we'll say
link open. I don't know how we can
show that. So over here
I will use this external link tag
external link icon. Okay, I think this
is much better. See,
and that's how we have this day one and
then day two information. How cool it
is, right? So that's how guys you need
to display the result. Now on the click
of this view, obviously we want to
navigate it. Now on the click of this
view we want to navigate to the Google
uh page where the detail will found. So
for that one I already have this link
which you can use it. Okay. Uh it's a
free just it will navigate to that
particular link. So I will wrap this
button inside the link tag
then h reference and then I will just
hardcoded this link
obviously. Uh oh that's weird. We don't
want this unwanted text. And instead of
this place name obviously we'll replace
with our activity dot
place name something like this. Okay.
Also make sure to wrap it this button
inside the link tag.
Remove this unwanted text
and I will just make sure here we will
add https
and then google.com the place name and I
will open this link in a new tab. So
we'll say inside the target blank. Now
if I go back click on this view button
let me refresh the screen once
and if I click on this view button see
it navigate to that particular place.
How cool right same thing if I go to
this BA beach. If I click on this one
you will see this BA beach and that's
where the Google map also redirect you.
Okay same thing you have to do it. So I
will copy this link for the uh hotel
placeholder. So for hotel we have this
button
and then I will wrap this link tag but
instead of this hotel we'll say hotel
dot hotel name.
Okay now once we added hotel name. Okay.
So over here
we need to add a class name with width
to be full.
And if I click on this one, it jump to
that hotel. See the bucket list hotel.
The bucket list hotel Goa. Okay. So
that's how you need to navigate. Now one
more important thing that we need to
update that we are going to replace
these all the um items into a separate
components right independent components
because it will be easy for us later on
as well. So first for the hotels we are
going to remove all of these bunch of
code and we'll keep it in separate
component. So here we'll say hotel
card item dot tsx let's add a default
template for that and from the itinary
I will cut it everything from here I
will go to the card item I will paste it
and then we don't need to provide an
index over here make sure to import the
image tag
and here we need to accept the hotel of
type hotel.
Now, if you did not exported this hotel
type, okay, so from the chat box, make
sure to export this hotel type.
Okay. And now if I go back to this hotel
card item, either you can import this
otherwise uh you can direct define
props. Here I will say hotel
as a hotel and then I will pass it as a
props. Okay. So it destruct this hotel
and now you see we don't have any error.
Make sure to import this link tag and
then button as well. Let's save
everything. Uh okay. Make sure to import
this wallet icon and star icon as well.
I think that's all. And then we will
simply replace this with a hotel card
item and pass the hotel information as
hotel. Let's save this one. Refresh it.
And then you'll not see any change.
Okay. Now later on I will tell you why
it is important. But for now I hope this
understand. Same thing we need to do for
the trip information.
Inside the trip information
we just need to replace this activity
info. So this particular card. So I will
cut it from here. I will create a
separate component for that and we'll
call it as a place card item dot tsx.
Add a default template and then simply
replace it. Now over here obviously we
need an image tag. So add it. Remove
this index.
Oh, we need an image tag from the next
last image. the link tag
then the ic all the icons we need to
import
the external link icon as well and the
last is button then we need to accept
the activity
right and we'll define a prop for this
one so we'll say type props is equal to
activity
and is of type activity right now you
have to make sure From the chat box the
activity is exported right so that you
can use that particular type.
Oh so inside this one
from the chat box and then simply show
the props. Okay something like this. I
think that's all. uh now go to the
itonary and here I will add that
particular component and then simply
pass the activity as activity
let's save it all the pages and now if I
refresh you will not see any change but
now we have different component for each
of these card item
now in it's time to replace the
placeholder image with an actual Google
place photo and it's very
straightforward First in order to
generate this Google place photo you
need to search the place detail with the
help of Google place API and then from
that Google place detail information you
will get the place ID that place ID
information we need to pass to the
Google place photo URL. Now just follow
the step-by-step guide that help us to
get the Google place photo. Now very
first thing uh there is a documentation
about the how to do it. So first we need
to search the that particular place
right with the help of this text search
and this is the endpoint that we need to
uh send it or make an call. So I will
copy this endpoint
and let's close all of this tab for now
and we'll go to this API here. We'll say
Google place detail as an endpoint. Here
I will add route.tsx file. Let's add a
default template. not default template
but over here we need to make an post
API call.
So I will say post
request next request something like
this. Okay. Now once we have this uh
we'll simply
call an method. So we need to add
constant
base URL and then we'll keep this base
URL. Now we also need to send some
configuration. So we'll say constant
config. Inside this configuration we
need to send an headers
and inside the header we have the
content
type. Here make sure it's an
application/json
then x
dash google api key that you need to
pass.
Now all of this you can even find this
on uh over here right. So if you see
this Google API key we need to par field
mask and all the information.
So that's what I'm writing. So over here
we just need to add the environment key.
So I will say next not next but here
we'll say Google
place API key. Okay. Now we'll replace
this key in a moment but I will just add
it over here and then we need to add
this XG Google field mask
and inside this we need to provide which
things you need it. So we'll say places
dot
photos then we need a display name. So
we'll say places dot display name and
then places
do id. Okay. So once we have all of this
config ready now simply
we'll make an API call. So we'll say
export
uh result is equal to await
exos dot post then we'll pass we'll send
this base URL then we need to pass the
information okay uh to this place so
over here we'll say text query and for
this one we need to pass a place name so
we'll say place name. Now we need to get
this place name from the body of so
we'll say place name is equal to aait
request dot
JSON. Okay. And that place name we are
going to pass and along with this one we
need to pass the configuration. So
whichever configuration we have that
configuration we need to pass and then
save it. Once we have the result
we'll return this result. So we'll say
result dot data.
Make sure we'll pass this inside the
next response dot JSON.
Now I will also make sure that I will
wrap everything in a try catch block. So
over here
I will add try catch block
with an exception E and here we'll say
return
next response dot JSON
E with an error E. Perfect. Here we'll
say error. So that's how you need to uh
said the post API call for your Google
Play API. Now in order to generate the
API key simply you have to go to the
uh Google cloud console. Inside the
Google cloud console here you have
option to create an API key. But before
that make sure you will search on this
Google place API right. So make sure you
will enable this places API new and make
sure to you you might have enable
button. Make sure to click on enable. In
my case it's already enabled. So I don't
need to do anything right. Uh also if it
doesn't work make sure you'll also
enable this place API which is old one
but make sure to enable that too. Once
you enable you can create an API key
and once you created that API key I will
copy that API key. Then we'll go back to
our env file. Just paste it here. And
for the security purpose, um I will just
rename this to AI trip planner place API
key. You can add a resting to your
website only. Okay. Right now I will
keep as it is and then I will save this
one.
Once you save uh you can ready to use
this API key because that we already
added. Now I will go to the
hotel card item. Okay. And instead of
this placeholder now we want it to show
but we need to make an call to this
particular place Google place API
endpoint.
So to make an call right so here we'll
say constant
get Google place detail
something like this. And uh inside here
we'll say constant result is equal to
await exos dot post / API/ Google
I will get that API endpoint which is
Google place detail Google
place detail
and uh that's all we have and inside
this we'll say place name as
hotel dot hotel name.
You can even pass more attribute if you
want to get an exact result. Make sure
it's a sync. And here I will just
console the result. So we say result dot
data. Now this particular method we need
to call inside the use effect whenever
this component get load and when the
hotel information is available. So here
we have hotel and then I will call if
hotel is there
then get Google place data something
like this and then save it. Now if I go
back to our application,
go to the inspect panel,
go to the console here, I will refresh
this screen
and we obviously we are getting error
because we need to make sure this
component is on the client side
and refresh it. Now if I refresh this
screen then you will see we got the
place information. Inside this we have
three different uh info. So I will just
extend this
and if you see we happy homes Goa happy
home there are lot of different option
cames out and for each of them you will
see the photos right and here we have
the uh
and from this one we just need this name
in order to pass to the Google uh photo
URL uh with this information right but
along with that one you'll see more uh
things over here like Google Maps URI,
their width, height and all of this
info. Now sometimes you might get a
three different results. See inside this
in this case we got places with the
arrow of three. So in order to avoid
that and to get only one place you can
pass the address as well and which will
uh limit and we'll get an exact result.
So now let's gohead back and once we
know that we are getting result over
here. Now we are going to update
the things. So over here we'll get the
place uh reference name I will say is
equal to result dot data. From the
result dot data we got the places. So
we'll say places of zero. Then we have
the photos. Then we'll say photos dot
and then we just need our first element.
And from there we'll get a name. So
we'll say photo of zero dot name. Okay.
So like this we'll get the photo
reference name. Now after that once we
get this one I will go to the
documentation and click on this place
photo doc over here. it will explain how
to get the
photo. Okay, because this particular URL
we need to render in order to display
it. So basically we'll copy everything
as it is. Okay, so this example we'll
copy. We'll go back to our application.
I will say constant photo reference URL
is equal to and then I will paste this
URL. This particular key nothing but
the environment variable key. we'll say
process dot environment dot and we'll
paste this key
variable. Okay. Then instead of this
place name
now we'll add a place reference name. So
we'll say place reference name. And then
for media you can provide a maximum
height and width. So we'll say max
height pixel is equal to 1,000 and max
width
pixel is equal to 1,000 and and then we
have this key. Now this photo reference
URL we need to write
okay because we are doing everything on
the server side. So you don't need to
worry and on the card item now we'll get
only that particular result. Now if I
head back, let's refresh the screen. Now
we are expecting just a URL. Now if I
open this URL, boom, it opened that
place information. If I open this one,
you'll get that place info. How cool? It
means it's working perfectly fine. Now
simply once we have that URL, we'll save
in a state. So we'll say constant
photo URL comma set
photo URL is equal to use state
which is of type string
and then here we'll say set photo URL
with the result of data and then here
we'll say if photo URL is there then
show photo URL otherwise show
placeholder
okay and uh also I'm going to write if
result
dot data dot e if there is any error
then return nothing and then save it.
Right now uh we have an error. So
obviously this particular endpoint we
need to set. So this particular host
name we need to add to our next
doconfig.js because we are trying to
render from the third party URL. So
simply go to the next doconfig.ts file.
Inside this we'll say images then we'll
say domains and then we'll white list
this particular domain. Once you add
this domain make sure to refresh your
application manually. It will not
refresh automatically. And then here we
go. And boom. If you see now the actual
image is now rendering. Perfect. Right
now same thing you have to implement. So
I will copy everything as it is and I
will implement for the place card item.
Once you add I will I need to make this
as a client. Then make sure to import
the use state and the use effect. Here
we have this activity right. So once we
have this activity info then only we'll
make a call. Uh obviously make sure once
we have the activity we need to send a
place name and along with that one
you can add
the activity dot place uh address okay
so which is helpful to get an exact
details now once you add I will refresh
this screen and okay so still I'm
waiting for this one uh let me see
what's the issue do.
So we'll go to the inspect panel. I
don't know why it's not rendering. So
we'll go to the console. I don't think
so. It's get call.
Okay. So that's because we did not set
the value. So over here we forgot to add
a photo URL. Then show photo URL
otherwise placeholder image. And boom.
If you see all the images from the um
that particular tree. Sounds good,
right? So that's how guys you need to
add it. Uh let me know if you have any
question any doubt because this is the
easiest way that you will find on the
internet that how to do it. Okay. And
most important the Google Play API is
free. You might need uh to add a card
credential sometime depends on the
country
but if you search on Google Play API
pricing.
So you will find let me go to this
pricing and billing section. Here you
will get some uh free credits every
time. Okay, so you don't need to worry
about this. Uh if you see it's
completely for zero dollar. You don't
need to pay any amount. Okay, and you
can use for a small business for your
development purpose as well. Uh same
thing if I go to the places you will see
everything for the $0.
Now it's time to uh render the actual
result on the right hand side. Right now
we are showing the demi data, right? in
order to make sure our UI is working
perfectly fine. But whenever user
generate the final response, we want to
display on this particular component.
Now there are couple of way that you can
do it. You can pass your generated trip
data from one component to other and so
on. But the best approach we can do it
that with the help of context and we
already use the context. So we'll create
a new context called trip detail context
dot tsx. Whenever later on we want to um
fetch the user already created trip info
that time also trip detail context quite
helpful over here we'll say export
constant trip detail context is equal to
create context and make sure it's from
the react you can mention the type any
and here I will put it as a null and
then save it now inside your provider so
we'll go to the provider tsx I will wrap
this So we'll say um
trip detail context dotp provider. Here
we need to pass a default value and make
sure to wrap this children inside this
provider. Now let's define the state. So
here we'll say trip detail, set trip
detail
and then we'll pass this trip detail as
a default state.
and then save it. Now you can also uh
add the shortcut for this one. So we say
use trip detail is equal to arrow
function and simply return use context
trip detail context.
Now let's close everything and go to the
uh chatbox component. That's where we
are generating the final trip. So first
I will use that context. So we'll say
trip detail, comma set
trip detail is equal to use trip detail
something like this. Right? So already
we are using this trip detail uh state
over here. So what we can do
uh I will replace this to trip info
instead of detail inside the context. So
inside the provider
instead of div detail info I will say
and here while passing make sure you'll
update this to trip detail info.
So this trip detail info. Okay. And now
I will say trip detail info and trip
detail info. Perfect.
And this need to be set trip detail
info. Now once you set this whenever we
get the detail information about the
trip we'll set the trip detail info with
the result dot data dot trip plan. As
simple as that. And then save it. Right
now I will go to the
our component and inside this eternary
we'll use this context again. So I will
copy it from here. Go to the iternary
and here I will use that something like
this. Okay. Make sure to import it and I
will just comment this
over here.
Uh we have this trip data. You can
replace this with the trip detail info
if you want.
But if you see for the trip detail info
obviously at many places we have to
provide a type right because we are
using a typescript. So best way to do
that instead of providing type for each
of them you can add a type to your
context itself. So if I go to the trip
detail context so inside this we'll
provide a type for it. So we'll say
constant or we'll say type
trip context type is equal to and then
we'll say trip
info as trip info we already have and
then set trip
detail info actually. So here we'll say
trip
detail info. Okay, then here we'll say
react dot
dispatch and then react dot set state
action with the trip info
and then here now you can provide a type
as a trip detail context type and it
might be an undefined so you can pass it
as undefined
here as well I will pass it as undefined
by default okay now let's save it. Let's
go to
uh provider because that's where we also
need to update. So inside the provider,
we have this trip detail info. Now I
will replace this with the trip info
and we also have an error over here. I
think we need to pass some dummy data.
So over here I will also pass a null
because we can keep a null as well,
right? And once you pass over here along
with the trip info I will pass it as a
null and here as well we'll pass it as a
null and then save it. Now if you see we
don't have any error inside the context
and the provider. Now inside the chat
box we have to make sure that the it
will return these two value. So I will
just update the provider as well.
And here inside the trip detail context
I will export it. So I can use this
context type inside the provider when we
return this. So over here we are
returning right. So
we'll add this particular type
and uh
and undefined. So over here I don't know
why we are getting this error.
So right now I just ignoring this error
because it's saying that you're also
trying to save it as a undefined. So
just ignore that thing. And uh I think
that's all we needed. And over here I'm
setting this value. Now let's go to the
itonary. And over here let's add ts
ignore. And here we have trip detail.
And after adding this one I will say
trip data, set trip data is equal to use
state is it? And I will pass it as a
null by default. But I will add a type
trip info
and null. Okay. Now this trip data I'm
going to pass everywhere.
Something like this. Now also along with
this one
uh we need to add one more condition to
verify whether the trip data is actually
there or not.
So basically here we'll add a condition.
If trip data is there then it will
render this trip data otherwise it will
pass an empty value. And now if you see
we don't have any more error right so
make sure to follow the step-by-step
guide if you face any issue you can
always refer the source code anytime
okay and I think that's all we needed
let's go back to our application
and as you are using the uh hook so I
will make this component on the client
side
so we have still have error so it's
saying the trip data is not defined okay
that makes sense because inside the
timeline we need to pass now this trip
data.
Uh I think I I forgot one more thing
that whenever
we have the trip detail info context
then we need to update. So here we'll
say trip detail info and I will say trip
detail info is there then we have to set
the trip data with trip detail info.
Okay, that is very important. Right now
if you see we don't have anything and
that that's why it's not showing any
value whenever there is no trip data.
Okay, it doesn't make sense to show this
timeline. Okay now right now if you see
it's completely empty obviously we are
going to replace this with a different
value but for now I hope you understand
up to until this point. So here we will
say uh create
trip from Charlotte to New York for 3
days. So I will pass this one. Now AI
will generating it. So it will ask who
is traveling. I will say couple.
We'll say moderate.
And then it start generating the uh trip
for us. And boom. If you see the trip is
generated as soon as uh it's there and
wow if you see all the details the
images also generated and now all the
images are directly from the Google
place API and that's a 3 days it turnary
right every day you got all the details
along with the hotel information depends
on your budget and here you will see all
the basic info that you selected
previously how easy it is now
interesting part if I click on this on a
view map it will navigate to the Google
map and if you see it jump to that
particular specific location where you
can learn or access more details.
Uh not only that but in advance um if
you want to add affiliate link to these
hotels you can add that too which make
you the real money along with that your
pricing and subscription model. Now
whenever there is a blank space we want
to show some image over here some travel
image right. So basically
over here we already have this trip
data. So I will add a question mark and
then
if the trip data is not there we'll add
an image
source over here. I already have this
travel.png file u inside my public
folder. So I'm going to use that local
image. All tag I will say travel width I
will say 800
height to let's say
800 and then inside the class name we
will say width full height
to full then object cover and rounded to
3x okay let's save it if I refresh the
screen now you will see that particular
image on on the blank screen. Boom. See
how cool. Also, on the top of that, I
want to add a text. So, I will wrap this
in a do tag.
Inside this, we'll add an S2 tag. Here,
we'll say getting to know you to build
perfect
trip here.
And then below that I'm going to add or
maybe we can add an arrow over here.
Left arrow or arrow left I think.
Perfect. Now this particular heading I
want to keep on the top. So I will say
absolute. We'll say bottom to 10.
Let's save this one. Okay. So it's
coming over here.
I will just move this and I will put it
on the top of this image.
And uh I will say 40. Not 40. Let's say
20. I will say text 3XL
text color to white.
I think that's much better. And then
we'll say left
to 20.
Perfect. Okay. So it's just showing this
direction that okay you can start from
here. Uh just last uh minute change that
I want to make inside the chart box.
Okay I'm just trying out that what if
you wrap this particular UI inside the
border. Okay. So over here we'll say
border rounded to 2 Excel
and we'll obviously give some padding to
five. I think this is much better. Or
instead of border you can add a
background. Let's say secondary.
I think secondary is too dark. Let's say
gray
50.
I think I will just add a border. That
would be good. And with the shadow.
Okay, perfect. And obviously on the
right hand side we have this image.
Now it's time to limit the free user to
just create only one trip each day. As
you know that we already integrated the
arjet into our application. Now it's
time to use that in a real time. So
we'll head back to our application. Over
here we already have the arjet API
endpoint and we also tested this get
request which is the example that how it
actually works. Now basically we need
this particular line in order to verify
whether you uh uh the access is need to
be denied or not and depends on that one
we are going to send a response. So
basically let's copy this line
and this AJ I'm going to export it so
that we can use it in any of the uh
file. Now go to the AI model route.tsx.
I will just collapse this prompt because
we don't need it for now. And at the top
we are going to check. So first I will
add this line of code here. Make sure to
import this AJ. Now instead of this user
ID we are going to use a user email the
login user email which you can get it on
the server side using this await current
user from the clerk neckjs and that's
how easy it is with the clerk once you
have the user you just need to pass user
dot
so over here this need to be an user dot
so pass user ID as user dot primary
email address dot email address okay so
So you have to pass this field called
user id.
Uh over here if it's empty then
obviously we have passed empty string
and then requested to five. So obviously
every time the five token uh it will
check whether the five token is
remaining or not for that particular
user. Then next thing we need to check
if access denied. So this line of code
we're going to use. Now after this one
we need just console the decision to
check all the fields that is available.
So over here we'll say decision save it
and we'll check this out. So I will
refresh the screen. When you make any
API call it will return the decision for
us. And if you see inside the decision,
so let me go up here. We have the
decision. Inside the result, we have
this information, right? Then we have
the IP. Then we have the conclusion.
Then we have the reason inside the
reason we have the remaining field. And
that's what we needed. So I will just
say if decision dot remaining
or we can say decision dot reason first
dot remaining
and then decision dot remaining. So it
will give us a count. So if it's equal
to equal to zero okay means there is a
no uh token left then we are going to
return next response
dot JSON inside this we'll say uh
response as
your
daily limit
reach or we say
no
free credit remaining
and the UI will be limit
as simple as that and then save it okay
and also inside the decision we have to
make sure whenever is final is true then
only we'll request five otherwise
will only pass as a zero
okay and I think I don't we don't need
to do anything let's refresh this and
let's take this out so I said create new
trip. So it's generating. That's weird.
Okay. Now if you see it's saying no free
credit remaining because we don't have
any more credit. But if I increase this
capacity to 10 for example, right? And
let's try this out.
Okay. So maybe I need to increase little
more because I already
um use many times
and now it if you see it start working
as expected. Now it only limit it or it
will only deduct whenever there is a
final when once you generate the final
output then only limit that uh and
deduct that particular amount. Okay. So
that's how you can add the arjet rate
limiting feature so that um your API is
secured from an uh free users.
Now it's time to add a pricing table
into our app. Obviously, if you see this
is how we want to add a pricing table.
Integrating the payment gateway is a big
headache, but it's no longer because
clerk providing you the billing feature
and within just one line of code you can
add this pricing table. How beautifully
looking, right? And that's what we are
going to integrate in this particular
chapter. So simply go to the clerk and
obviously you can go to the dashboard on
in which under the configuration you'll
find brand new option called billing.
Click on the setting section and here
first thing you need to create a plan if
you don't have any plan. Now I will say
create plan and under this plan section
we don't want to show a free plan. So I
will just hide this one. So you can open
that and simply say public vable to
false and then save it. But we want to
add some paid plan as well. So I will
add a new plan over here. And then give
the plan name. So here we'll say
monthly.
Then you can set the base price how much
you want, right? So I will say 9.99. And
you can even give the annual discount.
So let's say on annual discount the
pricing will be just $7.99.
And here you can add a feature, right?
for example unlimited
trip planner
then I will add this feature and same
way you can add a multiple feature by
providing a name and the value once you
add all the feature simply save this one
and then we'll go back currently we are
under the development mode right so it
clerk itself use a testing credential in
order to test it But once you move this
to a production, make sure to connect
your actual stripe account because clerk
use a stripe payment gateway in order to
uh receive a payments. Now once you done
with this plans just enable this billing
and then your billing is now enabled.
Now simply with this particular uh
component you can add your pricing
table. You can read the billing guide in
order to get more details. I will put
the link in the description so you can
go ahead and check this out. Now once we
create the plan here you will see how
easily and uh we can show this. So I
will copy this just pricing table
component. We'll go back or simply
create a new route under the route uh
app folder and we can say a pricing.
Inside this we'll create a page tsx file
and then we'll add a default template
saying pricing. over here. I will paste
this. Make sure to import this pricing
table and then save it. Now, inside the
header tsx, we already have this pricing
at route attached. So, we'll go back. I
will refresh this screen and then make
sure to click this pricing and boom. If
you see, we have this pricing uh table
is showing on the screen. Currently, we
only u add one plan, which is a monthly
plan, but you can add number of plan.
It's totally depends on you.
Next,
I will add some text over here. So, for
example, we'll say first I will give
margin top to 20 and then we'll say S2.
Let's
we'll just add some text over here. I
will add a class name font bold text 3
XL and margin Y to five.
And if I go back to our app over here,
boom, this is how it looks. Obviously,
we have to make this in the center of
the screen. So, we'll say text to be in
the center.
Okay. Now, we don't want to add a lot of
plans over here. Okay. Uh but that's the
reason we added the only the one single
plan. Now when you want to subscribe you
will find in in app only you can able to
uh go to the development mode. Here you
can make a payment and obviously you can
test this out with this uh test card as
well. Okay. And once you make the
payment you can manage this using a
profile section. Currently we don't have
profile section so we can add it at the
top. So basically inside your header.tsx
tsx.
I will wrap this in a do tag
maybe outside of this one
and then we'll simply say user button.
Now this user button component we are
importing from the clerk right and
automatically add all the UI all the
necessary UI for you. Here I will make
flex gap of file item to be in the
center. Now if I go back you will see
this profile icon. Just click on it and
then you will see this beautiful
drop-down option where you will find an
option called manage account. Click on
this manage account and then here we
have the new billing option. Click on
it. Currently you we are you are on the
free plan that's why it's saying zero
but under the statement you will see the
statement payment section everything but
you have option to add a new plan as
well see how easy it is right so with
the help of clerk you can easily add all
of these feature guys now once you have
the pricing model and uh all the details
right now it's time to check the limit
because currently we set the limit but
we have to check if the user is paid we
don't need to uh add that limit feature.
So in order to do that simply from the
documentation you will find how to do
it. So we'll check whether the user has
a premium access or not. So we'll copy
this line of code. Go to your uh AI
model route at the top. I will simply
paste this. Make sure to import this
has.
Obviously in order to import it you need
to write like this has
is equal to and you have to import from
the O actually await O and then we have
has now in the plan make sure to give
the plan ID. Now in order to get this
plan ID simply go to your plan in this
case is a monthly and if you check this
key that key you can pass. So I will
just copy this key and I will pass it
here. Okay. And now it will check if
user has the premium access or not along
with this. So this condition I will add
if premium access is not there. So I
will say not there then you can send
this particular message. Okay. Here I
will just console this so that you can
easily check this out.
So I will go to the create new trip.
Here I will say create new tree for me.
Inside the console
if I go to our console here we will say
has premium access to false right.
Perfect.
Now I will in order to test this right I
will just go to this arj route and
instead of this 30 I will again make
this five. So that obviously uh I will
get the message that no free credit
remaining. But if I subscribe to our
plan then obviously that limit will go
away. Now I will say subscribe I will
pay with the test card and once I make a
payment you will see this particular uh
table u pricing is activated. Now if I
go to this manage account under the
billing you will see the current
pricing. Perfect. Now let's create a new
trip. I will say create new trip. And
now in this case it allow me to create
it because I already subscribed to my
plan.
I hope you understand this particular
scenario. Right? That's how easy you can
uh manage it. I hope you understand this
pricing table. If you have any question,
any doubt let me know in the comment
section or you can also reach out to me
on my discord channel.
As you know that we already saving the
all the trip information for that
particular user into our database. So if
I go to the database here you will see
the trip detail, trip ID, user ID and
all the data. Now we need to create one
button over here instead of this create
new trip on this particular page and we
say my trip. On the click of that my
trip we are going to navigate to that
new screen on which we are going to show
the user uh generated trips. Okay. So,
first thing we have to check depends on
the route inside the header we need to
uh replace this particular button.
So, I will go to the header.
Inside this header tab, we'll get the
current route. So, we'll say constant
params is equal to use
or this need to be a path name actually.
So, we have instead of param we'll say
path. Okay. Now this particular hook is
very powerful. It will return us the
current URL. And let me show you how. So
if I save this one, refresh this screen
and if I go to the inspect panel, you
will see the /create new trip as a route
is rendering or it's displaying inside
the console. Now
um here we'll create a new method not
method but here we'll just use this path
actually in order to uh change this
create new trip. So over here we'll say
if path is equal to equal to / create
new tree
then we want to show a different button
otherwise so here we'll add a turnary
operator
otherwise show create new button so I
will just copy the same and we'll paste
it here and here I will say my trips
and I also want to navigate to my trips.
and then save it. Now if you see it's
showing a my trips but if I go to the
home screen then it will show the create
new trip. Okay so that is very important
to update this. Now on the click of my
trip obviously we should navigate to
this my trip screen. Currently we don't
have that particular route that's why
it's showing 404 error. So inside this
app we'll create my trips folder. Over
here we'll create a page.tsx tsx file
and simply add a default template saying
my trips and then save it.
So right now it's still executing and if
you see now we have the my trips list.
Over here we'll give a class name
padding x to 10 padding to 10. Then
we'll give on medium screen we'll give
padding x to 24 and on large screen
we'll give padding x
x2 48. Okay. So, some distance. Then we
want to add a text called my tricks.
For this one, we'll add some styling.
And if user don't have any trip that
condition also we need to handle. So I
will create constant my trips comma set
my trips is equal to use state
and over here we'll say
if not my trip so we'll say otherwise my
trips dotlength is equal to equal to
zero then simply we want to add a div
inside This do will say you
don't have any trip plan
created
and then below that we'll simply add a
button
create new trip.
Obviously I will wrap this in a link tag
with a h reference saying it will
navigate to the create new trip screen.
And I think that's all we needed. Then
over here we say padding to seven,
border
and rounded to 2 Excel
as we are using a state so we need to
mark this component on the client side.
Okay. So that's good. part over here I
will make it flex flex column item to be
in the center and justify content center
gap to five
and then we'll also give margin top to
six something like this right and on the
click of new trip it's navigating
perfect now we need to write a convex
function in order to fetch that
particular user information
so go to the convex folder inside that
we already have the trip detail Now in
this case we want to fetch it right so
we'll write we'll write a query so we'll
say export constant get
user trips
and here is equal to we'll say query
and obviously we need to pass an
argument in the argument you need to
pass a user ID which is of type ID and
then you need to provide a table name
which is user table
then pass an handler.
Inside the handler, we say async ctx,
arguments, and the arrow function. Here
we say constant result is equal to await
ctx dot db dot
query and then you need to provide a
table name. Here the table name is trip
trip detail filter dot
sorry u trip detail table and inside the
filter we need to add equal to
so here we'll say q dot
equal and then q dot fill the field name
is user id matches with our arguments
dot user ID and again select all that
records. So that's the reason we have to
say collect. Once you add this, we
simply return the result.
Okay. And then save it. As simple as
that. Now once you have uh once this
getting the user convex function is
ready, let's head back to our page.tsx
tsx file
and inside this we'll write a constant
get user
trips
and here we need to define a convex
first. So we'll initialize the convex is
equal to use convex.
Now we are using the convex because uh
we need to execute the query. So we'll
say constant result is equal to await
convex dot query and inside that we need
to pass a query. So we'll be it inside
the API dot trip detail dot get user
trips and then we need to pass an
argument. So in this case the argument
will be just a user id. Now in order to
get a user ID you already know that we
have this user detail
uh context.
From that you can get
the user ID. So we'll say use context
was not context user detail context
actually.
Oh my bad. Uh I will just undo
everything here. We just need to write
user detail
because that's the context we have to
use. U use detail. Use user detail
context. My bad. Okay. Then from it you
can get user detail
dot id. Okay, here I will make this as a
async. Then inside the console I will
just write a result and I will call this
method inside the use effect
whenever the user detail information is
available.
So here we will say get user trip.
Now once you save everything head back
to our application. I will go to the
inspect panel. Go to the console and
boom. If you see we got the nine
records. Okay. Now obviously this record
will be in ascending order. So here I
will add one more condition dot collect
dot. Here we already have I think we
have order by order. Here we need to add
descending.
Here you just need to provide whether
it's a descending or ascending. So we'll
say descending. Okay. So we don't need
to provide any other things. And most
important we are getting the result. Now
save this result in a state.
So
inside the page tsx we already have this
my trip section. We'll just set that. So
set user detail with the result. Okay,
you can define a type over here because
we only have the trip ID, trip detail
and UID. Now from it obviously we need
to iterate the trip detail in order to
display the each trip information.
So over here I will add a div. Inside
the div we'll say
trip.
Oh, so what is this? Uh my trips sorry.
So we'll say my trips
dot map here we'll say trip, index and
the arrow function.
Then we'll add a do
and inside this do obviously we need to
iterate this trip detail.
So let's uh show the origin and
destination. So over here we'll say H2
tag inside this we'll say trip dot uh I
think it's better we can provide a type
for this one. So here we'll say type
trip
is equal to and uh we mostly concerned
with
let me uh u trip id so here we'll say
trip
ID of type any then we have trip detail
so we'll say trip detail of type trip
info
and
underscore id if you want So underscore
id of type string. So these are the some
parameter we are fetching. Um I will set
this over here
so that we can directly use it. So here
we'll say trip dot trip detail dot
um origin or we'll say destination
first. Okay. Here for the key we provide
index. I will save this one. I just want
to see whether it's working or not.
Right now we got an error. So that's
where okay there is one small mistake
instead of the setting the user we have
to set my trips okay so make sure you
set the correct one and once you set my
trips if you see we got the list of all
the destination
so this is the destination so here I
will put a source as well so we'll say
trip dot trip detail dot
destination and over here we'll add
arrow So I want arrow on both the side.
Okay. So something like this.
Okay. And for this H2 tag we'll say
class name flex gap to two. I think
that's much better. Also we'll make font
semimedia bold and text to Excel.
Now just above this one we also want to
show an image. So we'll say image tag
with a source. Currently I will add a
placeholder.
Um so for a placeholder we'll say slash
dot slash placeholder dot jpg
and
for the alt tag we'll say trip dot trip
ID.
I think that's all we needed.
Make sure to provide a width and height.
Then inside the class name, I will make
a rounded corner. So rounded to Excel.
Then object
cover.
So we have an error. So we'll say what
is the issue.
Oh we don't need to provide this dot. So
that's the reason we have that error.
And if you see we have the placeholder
for each of them. Perfect. Now instead
of putting writing the code over here I
will create a new component under this
my trips
and under the components we'll create
uh my trip card
item dot tsx file. Let's add a default
templates. Save this one. I will cut
everything from here and I will paste it
inside this my trip card item. Obviously
here I will accept the trip as a data.
Okay.
And uh for the props I will say type
props
is equal to
here we will say trip and then we want
to export this type
so we can use it.
Perfect. And then we don't need to
provide a index over here. Make sure to
import the image and save it.
Uh, okay. I think we forgot this.
Importing this icon.
And now inside the page.tsx, you need to
add this my trip card item. And to this
one, you need to pass a trip. You can
add a key as a index if you want. And
then save it. And boom. Right now over
here, I will add a grid. grid column 2
on the smaller screen on medium screen
or maybe on large screen we'll say grid
column 3
gap to five
perfect I will also give margin top to
six
and that's how it looks like now
obviously we need to add lot of other
things um here we can write a text
something like H2. Here we'll say how
many how many days of trips. So we'll
say trip dot trip detail dot
duration
and and over here we'll say let's save
this and let's see what is the result 3
days
trip
with and then we need to write a budget.
So we'll say trip dot trip detail dot
budget. So 3-day trip with a moderate
budget
something like this. See okay and uh
I will add margin top to two text grade
500
and save it.
Then
you can add
padding to three. We'll add a shadow
rounded to 2 XL.
Here we'll add more padding.
Okay. So user can able to see it. Now
once you add all of this detail,
you can also show that particular image.
Okay. So in order to show you the image
you can use the same logic which we used
for other cards. Um just the things I'm
going to add margin top to two over
here. So some space now uh I will go to
the previous card. Let's say place card
item. I will copy everything as it is.
We'll go to the card item and we'll
paste it here. Now make sure to import
this all the hook first.
Now whenever the trip information is
there we want to execute this get Google
place import the exio as well and
for the place name we'll say trip
so I will remove everything dot trip
detail
dot
um you can add that
information from the itinary
of zero dot
activities
dot okay so from the activities I think
we need to get first activity and then
here we'll say place name okay so that's
how I think we can get the place
information of place name so that you
can
replace with this particular placeholder
with the image
And boom. If you see, we got the
eternary. How cool, right? So that's how
guys, you need to uh create this
alternate. Obviously, that's not look
good. So instead of this one, you can
just place a destination name. Okay. So
what we can do? So we'll say trip detail
dot destination.
And if I refresh this now, you'll see
the destination. I think that's much
better. Now, uh, another important thing
you need to do is to, uh, give the
specific height and width. So, here we
say width to full, height to 200 pixel.
Okay. So, everything will be in one
line. I think we can give 270.
I think that's much better. Say
and on the click of that itonary we want
to navigate to the new screen where we
can show or use existing uh timeline uh
structure where we are showing the
itinary or trip details.
Now once we have this my trip details
information right and on the click of
that we want to show all the details of
that particular trips. Obviously, we are
going to reuse the component. But before
that, let's create a new route. So, I
will close all of this tab for now.
Inside this app folder, we'll create
view trip. Inside this view trip, we
need to add a trip id that is very
important in order to fetch uh or view
the trip information dynamically. Okay.
And inside here, we'll create a page.tsx
file. Now let's add a default templates.
Here we say view trip
and then save it. Now in order to get
this trip id we'll say constant
trip id is equal to use params and
that's how you can get the trip
information. Make sure the this field
name will match with this folder name
which you gave. Okay. And whenever you
want to make a dynamic route, you can
start with the folder name with the
square bracket. Now once you have the
trip ID, obviously we need a convex
function in order to fetch that
particular trip information. So I will
go to the trip detail uh inside the
convex and here we'll say export
constant. Let's copy everything as it
is. Actually
only thing that we need to add get here
we say view trip
or get trip by id then
uh along with the user id we also want
the trip id
so which is of type string
and here we are filtering out right also
we need to add one more conditions. So
we'll say Q and Okay. And then the first
condition which is equal to and the
second condition. So let me bring this
down.
Second condition will be Q dot equal Q
dot fill
matches with this trip ID and our
arguments dot trip ID. If that matches
uh obviously we don't need order by over
here then we need to return only one
record because it will only return the
single record and that's how you can get
the t by ID. Now inside this first we'll
get the user
detail comma set user detail is equal to
use
uh user detail context and then we'll
create a method to get the trip by
get trip we'll say just and here we'll
say constant instead of before constant
let's define a convex X
and then we'll say constant result is
equal to await
convex
dot dot query pass the query. So API dot
trip detail dot get trip by id and then
we'll say user id as user detail
dot id and then the trip ID nothing but
the trip ID which we already have
here I will make as a async.
So if there is a note trip ID we'll pass
it as empty. Oh here we have an error.
So it's saying string is not assignable
of type string.
So over here we'll say to string maybe
that will help or
we can add it something like this. I
don't know why it happens but let's see.
And then inside the console we can write
the result. Okay. Now this particular
method we need to call inside the use
effect.
So over here um whenever the user detail
is available we're going to call this
method.
Perfect. And save it. Now in order to
test this first we need to
uh go to the
trip not but we'll go to the
my trip inside the card item. on the
click we want to navigate. So I will
just use a link tag.
I will replace this due to link tag and
in the ha reference
we'll navigate to slash
view trip slash and then trip id. So
we'll say trip dot
trip id. Okay, let's save this one and
let's test this out. So if I click on
this Mumbai to whatever. So if you see
it's navigate to this view trip. I think
we have incorrect name. So it need to be
a view trips. I will rename this to view
trip only.
And if I refresh this now we have uh the
view trip. We got an error. That's
because we need to make sure that
particular component on the client side
we use the hooks. So here I will make
this as a client side.
And if I refresh I will just make sure
And if you see we are we are on the view
trip. The most important thing if you
see this route right because inside this
URL only we are passing the uh trip id.
Now inside the inspect panel make sure
you are getting the result. See and we
have this particular result. Cool. Right
now once we have this result uh
I will make sure to go back first and
then we'll define a state inside this my
inside this view trip. So over here
we'll say constant
trip data comma set trip data is equal
to use state and the type is trip. So
make sure to import that
and over here we'll set the trip data
with the result. Okay. Now we already
have the component called itterary.
Right? So here we say itterary
make sure to import and then to this one
if I go to the iternary u uh we need to
just display that. Right? Now obviously
it will not display anything except this
empty value. Right. Uh but
we need to set the trip information. So
if I go to the itinary component, you
will get to know that we are using this
use trip detail context and that's where
we are setting the trip. So I will
go over here make sure to import this
use trip detail
and I will ignore this for now. And once
we have this trip detail info,
I will set this detail info with the
result dot trip detail. And boom. If you
see the result, how beautiful, right?
And we don't need to do anything.
Everything is here. Uh if I go back,
come to this new one. Let's say
Charlotte to bone. And boom. Perfect.
Right
now it's time to add a 3D map on our
application.
On this particular page, obviously we
are giving one option to see the view
trip details and other option to view
the places directly on the map which is
a completely interactive 3D global map.
That's what we are going to add with the
help of mapbox. Mapbox provide a best um
map which is the best alternative for
the Google map as well and Mapbox is
free to use. You can start with the free
trial and if once you reach certain
limit you can uh buy the with the extra
credits but uh for a development and for
a small business the mapbox is free to
use. Simply sign up to the mapbox. Once
you sign up uh you need to create an API
key. Sometimes it autogenerate for you.
So once the key is ready or token is
ready just copy that go back to your
application and then inside your envu
file just add this. So we'll say mapbox
API key is equal to and then paste this
here I will add next public because we
want to use on the client side. Then I
will head back to this mapbox
documentation. here it help us how to uh
install the SDK for the mapbox. So I
will put the link in the description so
you can also go ahead and check it out.
So inside the mapbox do documentation
under the get started here you need to
select the modular bundle and then copy
that go back to your application
and inside the terminal
make sure to install this mapbox. In
meantime, we can go to the
create new trip screen. Under the
component, we create global map.tsx
file.
And then I'm going to add a default
template and then save it. Now, this
global map we wanted to show on the
screen. There are a couple of way that
you can uh show the map. Either you can
add a tab or you can add a floating
button in order to switch between the
trip and the map. So we are going to use
a floating button. So basically in order
to add that button
we can first go to the page.tsx file.
Under this we have the iternary right.
So I will define one constant called
here we'll say uh active index comma set
active index is equal to use state and
initially it will be zero. Now whenever
the active index is zero
we need to show itterary otherwise we
will show a global map.
Okay. Now here this is turnary operator.
Make sure and once you save it right now
if you see the it's showing the iternary
but if I switch this to one then it will
show the map. See the global map. Okay.
Obviously we will add a button later on
but for now I will keep this active
index one so that we can test this
global map and we can implement it. Now
once the mapbox is installed
you need to add this CSS file. So you
can add simply inside the same component
and then you need to import this maxboxg
gl as well. Okay then this is the
example where you can initialize the
mapbox. So I will add this
initialization inside the use effect.
So we'll define the use effect over
here. We'll add this. Now obviously you
need to refer this mapbox token.
So we'll say process
dot environment
and then this mapbox environment key
something like this. Okay. Then inside
the container obviously we need to
define it. So I will define a reference
called constant map container.
Reference is equal to use reference
and by default I will provide it as a
null. Then inside uh the HTML side
obviously we wanted to show it. So I
will just add a reference to map
container reference. So it will
automatically render our map inside this
particular div. Also don't forget to
provide a style that is very important.
So here we'll provide a width. Let's say
95%.
Then the height I will add 85 vertical
height.
And if you want you can add a border
radius. Let's say 20. Okay. Now once you
define this inside this container you
have to refer that container reference
current something like this okay
and if it's not there I will pass it as
a empty now style you can put this style
URL this is the current uh street v12
style but you can create your own and uh
save this one go back to your
application right now if you see the map
is getting rendered how cool right at
least our map is rendered But we want
the map in some different way. We want
to show a complete global. So here I
will pass it as a projection. And here
inside the projection you can add a text
called globe. The zoom level. I will
change this to let's say 1.7. Save this
one. And then you will see the magic.
Make sure to refresh it. And boom. Now
we have this proper global where you can
easily manage it. You easily you can
change this. Not only that, but you can
easily zoom it as well with your keypad.
Cool, right? So that's what we wanted to
add within a few single line of code or
few lines of code. Obviously, we added
this um map box map which completely 3D
like structure. Okay. So I hope you
understand this how to do it. Obviously
what whenever the trip is generated, we
want to show the markers as well. Now
before moving to the next chapter, we
want to add the floating button at the
center. So I will go to this page.tsx
file
over here. I will add a button.
inside this button. Uh let me
add as a globe
global.
Okay. Yeah, this one. Maybe not this
one. Uh
global two icon. This one. Okay. And
obviously again I I I want to add a
condition
if active index is equal to equal to
zero then I want to show a plane
otherwise I will show the global.
Okay here this need to be a turnary
operator. Save this one. And if you see
this button is at the bottom. Obviously
we need to add a position as absolute.
Then we'll say bottom to let's say 20.
Then we want a lift
to let's say 25%, I don't know whether
it will work or not.
And I will make this as absolute
or not absolute u the relative.
Okay, let's make this 50.
I think this is much better. And instead
of bottom 20, I will make 10. I will add
a size
large. Perfect. Now on the click of this
one, we want to switch uh this one.
Okay. Uh the it turnary to map, map to
itary. So over here, I will add on click
method
and we'll set the map index or set
active index.
If it's zero
then we'll show one otherwise zero.
So obviously this condition need to be
if at index is equal equal to zero then
we'll show one other way zero. Now if I
click on this one see now if I check
again see okay so that's how we are
going to change it.
We can change the color let's say
background black.
I think this is much better. And on
hover we can add background gray.
Perfect. Okay. So that's how we need to
add it. So I hope you understand this
one. Okay. Uh on how you can add some
kind of toggle tip. Okay. So if I go to
the share CN
and go to the components we have tip or
talk I think tool tip we can say. So on
hover this is how the tool tip will look
like. Obviously in order to add it first
you need to install
the npm package from the shad cen and
then simply import the statements
and then you need to wrap your button
inside this tool tip.
And here we can add switch
between
map and
trip
and obviously uh
this class name maybe we need to now
attach to this tool tip.
Oh my bad. Um,
this button need to be here inside the
trigger. And for the content,
we'll add this text.
See?
And obviously, uh,
I think that's all we needed. And also
cut the class name to this button
trigger. And make sure to add a rounded
to Excel. And if you hover on this one,
you'll see the change. Perfect. For this
button um
where is this button? Yeah, over here I
will add a class name background black.
See, something like this. Obviously,
we'll change this hover effect as well.
Perfect. Okay, so that's how we are
going to add it.
Now it's time to show the places on the
map with the help of mapbox marker.
Marker is a concept where you can show
the location with the help of latitude
and the longitude and then it will show
that particular marker on the map. Now
obviously you need to create a trip and
at the final stage uh we will get the
data which we can show it. But u in the
testing for the testing purpose we are
going to use my trip section inside the
my trip I will go to this uh any of the
trip okay you can select any trip
literally and then once you select the
trip uh we can show map on the right
side okay so let's go to the my trip
first and in that one I'm going to
import this global map
so I will go to the view trip inside the
view
I will divide the screen. So we'll say
grid column span
uh five out of this column. Okay. So
over here we'll say grid grid column
span five. Out of the five column I'm
going to assign three column to this
iternary and two column for the map box.
So here we'll say global map and we'll
say glo column span three and then save
it. Once you save, if I go back to our
app, let refresh this screen.
You will see on the left hand side we
have this uh map and on the right hand
side we have the uh sorry itonary on the
left map on the right. Here make sure to
provide a column span two.
I will just refresh the screen so it
will display it on the screen. So it's
coming down. That's where Oh, so this
notable column span
to
perfect. Okay. So that's how a map is
showing on the screen. Now go to the
global map and here we are going to use
a trip detail contact context. Right. So
you already have this trip detail
context. You can get it from this detail
info. I will copy that and simply I'm
going to paste it here.
this trip detail from the trip detail
info
we can easily iterate those markers.
Okay. Now in order to add that first
we need to get all the places. Okay. So
over here we'll say trip detail info
dot.
So let's define the type for the
activity and for the index as well.
Now inside this you just need to add new
map mapbox
G gl dot marker
and by default I will provide a color as
a red.
Then we'll set the uh longitude and the
longitude. So we'll say set longitude
and latitude. So over here we'll say
place not or place activity.
So just a second uh over here we have
this I will say activity only in a
small.
So we say activity dot geiocoordinates
dot um longitude
and then activity dot geoccoordinate dot
longitude. Okay, sorry. Latitude.
Once you provide this one, we'll set the
popup. So, we'll set popup message.
Inside this pop-up, what on the click of
that particular marker what you want to
show that things you can show it. So,
here we'll say mapboxg dot popup
and then you can add the text whichever
text you want to uh show or you can even
add your own component. So for testing
purpose I will just add the text. So
here we will set set
text and then the activity dot place
name. Okay as a simple text. Once we
have that everything is ready here we
have to add it to. So we'll say add to
and then map and then save this one. Now
we'll go back. Here we have an error. So
the use trip detail is not defined. So
make sure to import this use trip detail
and uh if I scroll down I don't think so
uh the
location is is rendering over here. See
actually uh we are not iterating the
activity but we are iterating the
iternary. So basically
here we need to replace this with the
iternary and then we need to iterate
that one. So here we say eternary dot
map and then inside this we need to add
an activity
comma index
and the arrow function and inside this
now we'll add it.
So this need to be an array. Okay wait
um so this is of type number. So here
need to be an internact activities and
then map. Okay, I think that is correct.
Now, now if I go uh refresh this screen
and boom, if you see we have obviously
uh
we have lot of options. Okay, but let me
refresh it again.
So it's not showing it only showing this
uh
places but not the
marker and obviously here we forgot to
push the marker. So once we define the
marker we have to push this marker. So
make sure you define this markers. Okay.
And once you have that marker ready you
have to remove that later on. Okay. I
think that's all we needed. Uh let's
save this one. Let's test this out. So
if I refresh it, I think marker is
showing on the screen. And if you see we
have this marker. Perfect. Now obviously
you need to zoom it in order to see
because that is everything is coming
from the one location, right? So it's
hard to see but once you zoom you can
see each location and on the click of
this you can see the detail as well. Now
to uh programmatically zoom when the
marker is set you can easily set that
too. So
uh if you scroll down a little bit after
this pushing you can set the map
reference dot current
dot fly 2 and then you have to provide
the center coordinates. Okay then you
have to provide a zoom level. So here
we'll say let's say 7 and then essential
we can set it true. Now zoom level you
can adjust depends on how zoom how much
zoom you want. Now for the coordinates
you can set the coordinates. So
basically uh
can get the coordinates
is equal to um activity dot
geoccoordinates dot longitude and then
activity dot geoccoordinates dot
latitude and then simply pass this
coordinate over here.
But don't forget to provide that this is
a number. So here we'll say number
as number,
number.
So let's save. Let's go back, refresh
the screen, and then you will see the
result. Boom. How cool, right?
Obviously, you can do more zoom. It's up
to you how much zoom you want. And now
if you see, it's more zoom. Perfect. So
that's how guys you need to add the map
box with all the features. Obviously if
you want to learn more about the mapbox
you want to more add a more feature you
can put the comment uh in the comment
section so that I can create a uh
completely new project which is
completely based on the map only.
Now it's time to deploy our application
on the cloud so that you can share this
project app with your friends and
family.
Obviously in order to deploy it on the
server uh we are going to use versel but
along with that one we are going to push
all our code to the GitHub and then we
are going to connect GitHub to the
versel. So next time whenever you want
to make some changes you just need to
push to the GitHub and Versel will
automatically get triggered whenever the
new changes are updated. So first thing
first we'll go to the GitHub. If you
don't have account make sure to create a
new account. Then I will create a new
repo. Give the repo name. So here we'll
say AI trip planner app
and then you can select the visibility
and simply create the repo. Once you
create the repo over here you'll find
some command. Right now first thing you
need to set this origin. So I will copy
this. Then inside the new terminal
I will initialize the g first.
Then we'll uh set the remote origin. Now
it is very important to build your
application locally. So just type a
command npm run build. So it will build
your application locally and if there is
any error any issue make sure to fix
that uh before deploying this
application. So if you see right now we
don't have any error but many times uh
your application run smoothly but in the
deployment it fails. So that uh you can
fix it by while running this npm run
build command before deploying it on the
cloud. Now once it is ready you have
option to add this all the changes. So
just we will say get add space dot. Okay
it means all the file are now in stage
mode. Here if you see it's changed to
state. Now you have option to write a
commit message over here and then simply
say commit. So uh we we can say
something like initial
commit and then simply say commit. So
obviously here uh I think in my case is
not configured. So I will just commit it
from here
and then once it commit you need to push
your changes. If you are pushing this
first time to this repo you have to push
with this command. Okay. And later on
you can just type command get push while
pushing the changes. Now right now uh
it's getting push.
Once it push we'll go back to our
application. Refresh this repo and boom
you will see just now we push these
changes. Right now the next step is go
to the versel and if you don't have an
account create a new account with the
versel add a new project and then here
you need to uh connect with your github
repo. Okay. Once you connected, you will
see your project name at the uh top
right. Make sure to click import. Then
you project name will appear over here.
Everything will be as it is. Now you
don't need to make any changes right
now. Okay. But as we are using a convex,
convex need a little bit configuration.
So I will go to the convex and here
we'll say convex versal deployment
and I will go to this deployment se once
you're on this documentation you will
find this build command that you need to
override okay and then you need to
provide this deployment key as well so
quite straightforward so I will copy
this key then we'll go back to this
versel and here we'll say build and
output setting just need to override
this build command and then we'll paste
this build command. Okay, then inside
the environment variable if you follow
this convex I will go to this convex
dashboard first and from the convex
dashboard you need to get this
production deployment key. So I will go
to this production make sure to select
you can even select from here okay then
go to the setting and here we have the
production key which we need to
generate. So we'll say generate
production key. We'll say prod. Save
this one. And then we got this key. Just
copy this key.
And you need to paste it here. Make sure
the variable environment variable name
should match with this one. Okay. So and
obviously you need to deploy it. But
before that make sure from the
environment file and from
environment.local local file you'll copy
all the environment keys and then you'll
paste it here. Okay. So just copy
everything automatically it will assign
all this value. Same thing you need to
do with this local file. We'll copy it
and then we'll paste it here.
Once you add all the keys and updated
this build command just click deploy and
within a few seconds it will start
deployment.
So this variable is duplicate one as
this is a dev. So I will remove this key
because we already entered right and the
empty one as well. And then I will
deploy these changes. Oh so I think we
have duplicate one. So I will just
remove the duplicate. And after removing
this duplicate key because I pasted
uh double time. So that's the reason.
And now if you see the deployment is
about to start. And here we go. Right
now it is building the log installing
all the dependency. You can obviously
check the logs. Then it will uh start
deployment and will assign the domain
for you. If there is any error, any
issue, you can just check this out
inside the deployment logs. Fix that
one. push your changes and it
automatically trigger the versel
deployment for you. So we'll wait to
finish these changes and finish this
deployment
and boom if you see our application is
now deployed without any issue. Now
simply go to the or continue to the
dashboard and here we have the URL. I
will put the URL of this application
demo so that you can test this out. Over
here we have all the things inside the
pricing. Obviously you need to login
first on get started it will ask to
login and then everything will work
properly right and most important this
is completely responsive application so
depends on the screen size it
automatically takes the uh screen size
uh resolution and then design will
automatically get updated.
So guys that's all for this particular
uh project video. Also quick thing
before moving to the uh next video here
um I just move this ARJet export inside
the utils files and open AI inside the
export. So while building it suggested
me to ex uh keep it in different files
right it will not allow sometimes to
export directly from the router AI. So
that's the reason I kept inside this
util files. So make sure to update that
too. So guys that's all for this
particular video. I hope you enjoy this
project. If you have any question, any
doubt, let me know in the comment
section. You can also ask any question
on discord channel with a great
developers community there. And if you
did not subscribe to our channel, please
do subscribe. Uh press notification bell
icon so that you will not miss any
updates and press like button. Share
this video with your friends and family.
So guys, we'll see you in the next
video. Until then, happy coding.
Loading video analysis...