Introduction
In this article, we will walk through the development of an advanced parking application called Auto Space. This application incorporates several modern technologies such as React, Next.js, GraphQL, and 3D mapping to deliver a top-notch user experience. We'll cover everything from the architecture of the application to the implementation of various features such as booking slots and managing parking locations.
Overview of Auto Space
Auto Space is a full-fledged parking application that enables users to efficiently find and book parking slots. The application includes a customer-facing UI, a manager interface, and supports valet service functionality. In this section, we will go over the basic structure of our monorepo setup featuring multiple applications within a single repository.
Monorepo Structure
The Auto Space application is organized as a monorepo featuring multiple applications:
- Frontend Applications: Customer-facing, Manager, Admin, and Valet apps.
- Backend APIs: RESTful and GraphQL APIs to handle various functionalities.
Technology Stack
- Frontend: React, Next.js, Tailwind CSS, TypeScript.
- Backend: Node.js, NestJS, Prisma, PostgreSQL.
- Mapping: Mapbox API for 3D mapping and location services.
- Payment Processing: Stripe API for managing payments.
Building the Customer-Facing Application
In this section, we will implement the customer-facing application that allows users to search for available parking slots and make bookings.
Setting Up the Project
First, we will set up the project using create-next-app
, enabling TypeScript and Tailwind CSS:
npx create-next-app@latest autospace --typescript --tailwind
Configuring Tailwind CSS
Tailwind CSS is a utility-first CSS framework that allows us to build custom designs quickly. Configure Tailwind CSS in the tailwind.config.js
:
tailwind.config.js
module.exports = {
content: ["./src/**/*.{js,ts,jsx,tsx}", "./public/index.html"],
theme: {
extend: {},
},
plugins: [],
}
Implementing the Search Feature
The primary feature of the customer application is to search for garages. We will create a search form component that allows the user to select dates, times, and filter for types of vehicles. Here’s a simplified version of our search form:
const SearchForm = () => {
// State variables
const [startDate, setStartDate] = useState("");
const [endDate, setEndDate] = useState("");
// Function to handle search submission
const handleSearch = (e) => {
e.preventDefault();
// Perform search query
};
return (
<form onSubmit={handleSearch}>
<input type="date" value={startDate} onChange={(e) => setStartDate(e.target.value)} required />
<input type="date" value={endDate} onChange={(e) => setEndDate(e.target.value)} required />
<button type="submit">Search</button>
</form>
);
};
Creating the Map Component
The map component will display available parking locations using Mapbox GL. To set this up, let’s create a Map component that triggers API calls to fetch garage data based on user input:
import { useEffect } from "react";
import MapGL from "react-map-gl";
const MapComponent = ({ setBounds }) => {
const [viewport, setViewport] = useState({
latitude: 37.7577,
longitude: -122.4376,
zoom: 8,
});
useEffect(() => {
setBounds(viewport);
}, [viewport]);
return (
<MapGL
{...viewport}
onViewportChange={setViewport}
/>
);
};
Booking Slots
When a user decides to book a parking slot, we will handle that through another function that interacts with our backend API. We’ll incorporate validations and display success messages based on user actions.
Summary
In this section, we have set up a customer-facing application for Auto Space with a search form, map component, and basic functionalities necessary to reserve a parking slot. As we progress through this project, we will continue to build out advanced features such as user authentication, garage management, and payment integration with Stripe. Keep an eye out for more detailed guides covering these aspects in subsequent sections!
Conclusion
The Auto Space application offers a powerful solution for parking management. This guide has introduced you to building a 3D parking app with features tailored for customers, managers, and administrators. The knowledge gained in this guide can be applied to various real-world applications in future developments. For instance, if you're interested in enhancing your skills in building user interfaces, check out our guide on Implementing Your Own Design System in Next.js.
Stay tuned for next sections, where we'll dive deeper into backend integration and UI enhancements, and explore related topics such as Unlocking Microservices in the Browser with Single-SPA for more complex application architectures. Additionally, if you're looking to showcase your work, consider Building a Modern Frontend Developer Portfolio Using Next.js, Tailwind CSS, and Sentry.
hello everyone today we are going to build Auto space it's a parking application we are going this is again
this is a monor repo we are going to have four frontend applications this is a customer facing application I have
hosted it on autospace docar tech.com and we have a cool 3D scene here we will build this from scratch using 3js it's
interactive and we have uh this is a manager application you can see from here and also we have this School logo
here okay like Vehicles parking in a parking slot and then we have the an application for this is the application
for the wallets this is the application for the admin and I could not host more than
three application in verel from the same GitHub repository so I chose to not host the admin console online and this this
application has two apis you're going to build this frd API I'm using swagger UI and you can we can actually interact
with the with the backend this actually backend okay we can actually interact with the database using this this GPI
interface and predominantly we going to use the graph c one so that's what we are using in the
applications so I here I'm using App Explorer I love I like this interface Bas it's much simpler than actually
typing the queries ourselves so these are the stuff we going to build let's have a simple
demo I I have already logged in with my Google account we can log in with credentials and Google in this projects
I'm already log in with the Google account and I'm going to search for garages so I have some sample garages uh
created here we have three kinds of filters Happening Here one is the Geo query actually when I move
here you will have additional things right this basically whatever comes inside that lat long rectangle the bound
we're going to do that location Geo query second one is the date query which is we going to meticulously keep track
of the number of slots each garage has and when already if there are no slots available in this particular interval
then we won't display that garage itself so that's a second filter that's a date filter third one is you can we can do
this these additional filters like types that's we we have we support four types of vehicles we also support the
price per hour okay no parking slots um in that interval and also we have Cent cashing
when I do 10 again we won't actually do the query the same thing happens for
everything else you can also reset it we do some advanced stuff using react hook form here so once we are s happy with
the date maybe I'm going to book for tomorrow and when I select the start date start time now currently the start
time is is later than the end time right and you will get this error message here automatically it pops up so
tomorrow 6:59 to 7:59 so now the dates are fine also we
have this cool icons that appears based on the time we select and also this Arrow specifies the
passage of time from to okay so I ended up giving a okay let's do a booking so I'm going to search for a car
slot and these are the slots okay so let's do this um so imagine I have I need a parking near the
Central Park I pick this you also have this caral here I used AI playground for generating
these pictures I have to select the type and also remember this start time this is
actually another form but we we get the time started start time and end time from the search
form let's enter the vehicle name phone number and we can also request for valet
drivers okay I when I enable that so that is the garage location and I can request a
driver from from some other location for example the parking slot the booking starts at 6:00
659 right so at 659 I cannot come here but I want some guy or yeah some person a driver near
this Empire State Building okay and we automatically calculate the
charge for pick up and drop off you may select a different location for the drop off okay so what happens is that the
plan is 7 at 659 I'll be here and the next day 125 1259 I need my vehicle to be
delivered at the airport okay and we calculate the charges for
that so we have this is like 18 hours of parking 15 hours per $150 per hour we have the
pickup charge drop off charge and this is the total amount so let's go book that
booking this is a stripe interface but you can see that we have a really good um listing of uh charges starting from
the parking valet pickup charge wallet charge drop off so let's do the booking okay so I have entered my card
details let's proceed to pay once the payment is successful automatically the we will be redirected
to the URL / bookings page and you can see the booking there and this is actually a link on clicking this this
will actually open Google Maps with a with that location okay that's the location of our
garage also you can see the timeline of the booking here
okay let's log in with our valet account also we have I use reuse the same 3D scene here but this is not
interactable we have some rotating camera going on I'm going to log in with my valet
account okay okay I'm logged in now okay so you can see the two
assignments in the valet valet interface one we have a pickup at 12:29 a.m. on on May 23 so that is going to happen at at
this point and this is the starting point this is the end point the B is the garage so this is from the pickup
location to the garage this is also a link on clicking this it will open the Google Map
along with the Lo along with the directions okay that's the directions and uh the driver can follow
that so I'm going to accept this assignment once accepted this thing will disappear from
the pickup so that not not anybody else can access that now in the my trips that is showing up and also it is displaying
a secret code now from the customer they can match the secret codes and
uh the wallet can pick up and when the wallet picks up the status changes and uh the card still exists here until the
use until the wallot checks in I'm going to go here the manager has to open the bookings for the particular garage that
this this is the garage this is the vehicle that is same code right also they can see the timeline of of of the
happenings also we have we can search for the car number here now the manager is going to check
in once check in that card will automatically move to the out page you can now see the updated a
timeline and when we refresh now in the my trips page that card will disappear basically that
assignment is done for the wallet now I'm going to go and accept the drop request okay this is this this starts
from the garage that is near the that it's a static map okay that's that's the garage location
and the the the user requested to drop the vehicle in that airport I'm going to that that's 11 km
and I have to be there at 629 so I'm going to I'm going to accept the request and that disappears from the
common valot assignments now that starts to appear in my drop
page again there is a secret code now the valet is assigned for the for this assignment now the wallet
reaches the manager or or whoever in the gate they check out the vehicle now it goes to the
resol and now when the wallet refreshes the drop button enables the valot takes a vehicle goes to the location
and they match the passcode and they drop and the action is successful the the card moves out from the drop now the
customer now there they don't have any ongoing parking bookings for the customer but in the past they can have a
look at started with the booked State ballot assigned Pi picked up checked in assign for checked out checked out and U
valet returned okay let's create a new garage from the manager interface so can click
on the new garage I I have created some data there the display name for the garage and a
description also uh AI wrote a note in the description which says we promise not to judge you if you cannot parallel
park okay yeah that's so kind of you also we have this address I don't know where that address
go inside in the New York City I'm going to be just play somewhere else actually yep so you can take you can actually
technically take this address get the lat long and then you can automatically place that
but that's an improvement you can do I'm going to place it here because that's what that's where I did not see a
parking slot lot fine and I'm going to get some pictures for this or some real pictures
from some amazing people like John Matty Chu okay that's a shout
out I'm going to have a few pictures and the next one for from eigor misnik these are very
helpful pictures thanks ran iic let's get the pictures these are the three pictures I just downloaded from
unsplash.com open that you can also reset and um re re reimport the
pictures so this happens without before uploading actually on you happy with the
form okay so I I have not created the slots actually so I'm going to generate like five slots
we are also getting the height width the size of the garage so that people can actually use filter filter them so I
have U let's create six plots for car and also I'm going to have a few for four slots for heavy so that is a bit
costlier 40 okay $30 per hour for a heavy one this is a huge parking slot at that is
uh 15 into 30 fine so that's those are the two
garage two types of slots we are going to create here on once you're happy I'm going to
submit first the images will get uploaded we are using cloudinary and then the garage is successfully
created and the form is reset now we can go back here also we have page Nation this is
the newly created garage now you can add more slots okay maybe we
can introduce um bicycle slot bicycle slots number of slots 12 bicycle slots it's going to be um tiny Six and 2
ft width with some height so you can add more or maximum 10 okay yeah I for so it automatically updates
here and the the manager can view the garage here the bookings in the garage here and this is the admin
console and from the admin console you can so that's a newly created garage and
the admin can verify the garage okay now from the search page let's have a look at
the newly created garage kep it here okay so that is the newly created garage the carousel
works and these are the four three types of U three types of slots we have the cycle can set the start time end time we
can set the ve vehicle number I don't know if cyes have vehicle numbers but yeah so you give uh you can
technically get help for your cycle parking as well by collecting this pick up and drop off locations and you can
book the book it and we already saw this flow earlier and we have other stuff like the managers can um can manage
valets we have like two valets right now they can create more with the license ID and so on the admin
can manage the garages and also manage the admins right now this is the only admin
that is me okay so yeah that's it that's the demo let's get
[Music] started hello everyone let's get started I'm going to start with an empty
directory in the in the desktop and we want to create a directory called autospace and let's open that in vs
code let's create a new project with [Music] pnpm I okay with the name I'm going to
delete the uh main property because it's the root of the monor r we don't want we don't have anything to execute so we
don't want the main file Main property and I'm going to enable private so it's not
publishable let's delete the script that's okay now I'm going to create the pnpm workspace yaml
file and I'm going to place the specify the packages so whatever that goes inside
whatever projects we have inside the apps directory whatever projects we have inside the lips directory are going to
be part of this monor repo let's create this um directories apps and lips and let's also create a dog
ignore that will have the env. nextt so these are build directories build dis. nextt and node mod obviously we don't
want to commit that in our git repository don't want to commit the gitv that's it now let's create the
projects I'm going to initialize a g repositor in the root then let's go inside the
apps and um let's run first I'm going to create a next application let's call it
web and also meanwhile let's also initialize the next application this is what we're going to use for the back end
we're going to create a rest API graph API in the same project I'm I'm going to call this
API so both of them are asking a few questions which package manager would you love to use how to use I'm going to
specify pnpm for the back end because that's what we are going to that's what we are using in the mono
repo and next next JS is also asking a few questions I'm going to enable typescript yes lint Tailwind SRC app
router and no for the for customizing the import alas now both our applications the API
is done the API then you go to the main file you can see that the by by by default it
runs in port number 3,000 I'm I'm okay with that so by default nextjs also runs in the port number 3,000 if 3,000 is not
available it will go to the next port number but instead of that I want to we we are also going to have multiple front
applications so I'm specifying 3,001 and when we create the front end for the manager admin valy we will
increment this port number so this is easy right for in the
development let's clean up the terminal let's allot some terminals specific specifically for the web
and the API so these two are for the API these two are for the web this is for the
root fine now a problem is the API files are not being tracked in the root G repository we initialized because when
we initialize the nest application it creates its own. kit it initializes it its G repository which I'm going to
delete you have to be careful about doing this okay this can ruin the project so
make sure you're inside the API directory and you're you just started right so I haven't even committed
anything so I'm going to delete the do kit and refresh the source control panel and you will see
the API file is getting tracked in the root G repository we initialized that's it now let's we we
have two applications let's do the initial commit before that I also want to uh
maintain a naming convention I'm going to have a spa at Auto space before the our applications and uh
packages libraries okay so yep so this ad com is an gas I have that adds everything and
commits automatically initial commit fine now let's create a sample
library inside the lib so I'm going to create a sample lib
oops let's create a directory called sample lib and inside
that I'm going to initialize pnpm project and before that we also need to
install this is for the root you can also rename that this is for the root this is for the
web yeah caps is better fine from the root we also need
typescript I'm going to install typescript as a depth dependency but we also have to specify this hyph W that's
workspace root flag a lot of times I accidentally install uh some dependencies from the
root instead of going inside and inside the library application so they have this U feature so I have to mindful
about this so I have to specify this hyphone W flag now the typescript is created I'm
going going to have a simple TS config a basic one we will actually extend this from inside our libraries also TS config
Json and so I created TS config at Json file and I'm going to have a few compiler options the target is going to
be yes next I'm going to have common jssm module because we have both the front end and back end code in the monor
repo so common JS works fine good and I'm also enabling the strict to true and I'm excluding the node J node
modules so that is the basic TS config now inside the sample lab I'm going to create one more Ts config that will
extend the root one with some more configurations DS config.js so I'm
extending the TS config.js on from the root I'm also adding the out directory which is going to be dist and the root
directory is going to be dot which is whatever inside this directory fine let's create our code now
I'm going to create a index.ts that is going to have a simple add function which gets two numbers and
it Returns the addition of that fine now we already have typ installed in the monor repo so I'm going
to have the build command which is just tsse okay and we Al we have also specified
the out directory and other configurations compar options extended them from the
base DS config now we can build this inside the sample lab I'm going to run pnpm
build that is going to run the tsse and we get our build disc folder okay this is a yes module
module JS JavaScript compiled code Also let's modify the disc the main to Target the dis /
index.js and also we have to add the autospace slash inside that that's the naming convention we are going with we
have our library ready I'm going to now install that as a dependency in both our web and API
project just like we do for any other dependencies fine now you can inside the API in the
node modules you can see the autospace SL sample lib now we install more dependencies like forms Network
libraries we will get everything inside this at autospace directory in the node modules we have our dependencies now in
the page let's clean up let's run the application first let's rename the St start Dev to
Dev because that's what we are using the back end is running the front [Music]
end fine that's the back end this is the front end we have both applications
running yeah let's also clean up the front end the next the page we don't want all these
things let's delete that let's also go to the globals file and I'm going to delete all the dark
mode stuff installed created by the nextjs this is the front end this is the back end now let's
[Music] consume now let's import our sample Library import the add
function and let's render that now we will get that number here okay similarly let's do the same
let's import maybe let's go to the app controller that's what we getting this message um hello world let's go to the
service file I'm going to import that because we installed it in both our applications and I'm going to return
Plus add going to have some number here and for the back end you have to actually refresh because that's an API
call and we get the response so that's how we have a library we build the library we import
that and we are using that Library okay so we have a basic monor report set up we have two applications
both we have one one Library we consume that Library now I'm going to have a a
validate script that's going to run the formatting linting type checking in the whole monor
repo let's do it let's start from installing the prettier also we have to specify that
hyph W that workspace root flag in the scripts I'm going to
have three scripts first we going to have the format script that we run the pr here that is this you're running that
I'm I'm I'm targeting all the TS TS6 JS js1 files inside the apps and lips and I'm ignoring whatever inside the kid
ignore that's the format and we can extend that with um hyph hyph check and hyph
hyph right this the check will only check the problems the whole monor repo based on
the prettier configuration so um njs already came with this preter RC I'm going to just drag that into the
root and I'm also going to enable semi to fals fine now we can run the format
check to see any formatting issues in the whole monor repo there are a lot of issues you can now run the
right actually when you go to this we have actually semicolons here right when I press
controls that will be fixed but here actually there is a problem with the es lint es L is uh struggling to work with
the prettier I'm going [Music] to turn that off turn that one
particular thing off about the Prett I'm going to inside the rules in the es land I'm
specifying the semi to false okay now yes is happy about it happy about not having
semicolons so you also need the prettier configure prettier extension so when you just control s automatically it will be
formatted you can do file available I'm going to just run the for format right script okay that will automatically fix
a lot of formatting issues you can see right all these things are formatted you can see the comma the
semicolons went away this uh mostly the semicolons also this double quotation I enabled single quotes
right fine that is format now on writing on doing the format WR or format check that checks the whole monor
repo fine the next one I'm going to use the pnpm
parallel this is recursive so it's going to recursively look inside all the applications packages the apps and lips
inside the monor repo and it runs a TSC command if it has okay I have to add it we already have lint so probably when I
add lint [Music] here okay now we have link command in
two two applications the njs the back end one has this link command we have the s l we have the s l configuration we
just added the pretti rule right similarly we have the link in the web also the front and the nextjs both
already came with these link commands so here I'm just running the link
recursively and also they are going to run in parallel so we get so it saves some time now look at this when I run
pnpm Lind it ran first you know apps SL API it started this
command so you can see the they they started in parall the API was done first and then the web was finished yes L the
linting link checking finished later for the web okay so I'm going to uh also add a
tsse command TSC we already have typescript right we enable typescript for both the front end
and back end so we can use this T TSC with a no emit flag fine similarly I'm going to have
the same command script in the print end also so this runs the TSC but it won't generate any compile JavaScript it just
checks for type type issues let's do the same for the sample lib also for building we we use a TSC
for type checking we use a TSC no emit
fine now from the root we can now also do the pmpm T now we are going to have three uh
projects run so you can see all three started in parallel the web one finished first the
sample lib finished second the API finished third that happened in parallel so we
have two command I mean okay yeah we have all three ready fine now let's create the validate
script I'm going to first run the format right and then I'm going to run the pnpm TSC and then we will run the pnpm
link this is is not parallel this is sequential we first fix all the automatically we will fix all the
formatting issues and then we will check the TSC and linting let's run the validate
script so it runs the formatting first and then it started yeah and then it ran the TSC commands throughout the Monaro
and then it did all the lint commands throughout the Monaro
fine now I'm going to do one more thing let's also add the build command Okay sometimes building while
building we we catch some issues this is going to Target all the build scripts right we already have them
in the what in the API we have the
build in the web we have build also in the sample lab we have the build
so when we run pnpm parallel recursive run build we're going to run build script in all the three applications we
have right now three projects now let's do the validate script it automattic it runs the format
right first it runs the TSC commands it runs the lint commands it runs the build commands
and I I really like the format you can clearly see what which command generated this
log the API one did not generate much Nest build and then it just done this is also the sample also simple
it run TC and it's done um next generated some log and it's done
finally so we have a really solid validate script now now I'm going to create a pre-commit
hook we can manually run this anytime Nothing Stops but I'm going to run this in a pre-commit hook so that nobody can
commit without satisfying these checks okay so I'm going to run the use the husy init package I'm using pnpm DLX
it is an equivalent of npx so I don't have to install P husky in it locally or I don't have to uh run any outdated
versions of H it PP PDX husky in it will set up husky in the whole monor repo and then we will install the dependencies
that it added in the package.json okay so it added this husy directory with some um hy. S I have no idea what
it is what all we have to do is go inside the pre-commit
file and add our pnpm validate script there now whenever we
commit it runs a validate command script and if it fails the commit is going to be is going to
fail and it also added um a prepare script in the package of Json it added husky it installed husky as a de
dependency that is it now let's commit the code before committing code let's have
an error okay that's a type error let's commit the code now so this Adcom alas will add
everything to the stage to the stage it will stage everything and then it commits the code so add validation
script this should fail actually it R solve the formatting first and when it reach the TSC it failed and it it
clearly shows where it failed and what error is how cool is that okay so wherever you
can have the error in the sample lib can have the error let's put the let let's put this
bug in the sample lab [Music]
okay oops okay num yeah so that's a type error now I'm trying to commit it again
fine now you are seeing that where the error happened
oh yeah find that yeah the error is here okay cannot assign num because it's a constant remove that now you can commit
the code okay we have a pretty good monor repo setup here we have applications
libraries consuming the libraries we have a really good validate script we have pre-commit hook setup
fine now let's create a local database I'm going to use um doer compose you have to make sure that you have Docker
desktop installed and running so I'm going to create a simple Docker compose file
inside the API I'm going to create this Docker hyph compost. yaml so we're going to have only one
service which is I'm going to call this autospace DB going to use the post image and use the port number 2000 maybe let's
change that to whatever port number you have to expose I'm having some simple
environment variables here post post password but when you are having working with dealing with a remote actual
production database you have to be really careful about these environment variables but this database is going to
run in my local computer so yeah and also we have one volume to persist the data fine now I have the doer desktop
where I installed and running now go inside the API I'm going to run the docker compose up hyph D for
detached something wrong oh okay fine yeah I have been testing so I already have
a container with the name same name I'm going to delete that let's run the docker compost once
again now you can see the auto space DB is is running fine I'm going to use Prisma
omm so let's install setup Prisma I'm going to install set Prisma as a Dev
dependency and you can use Prisma in it to initialize Prisma in this project which created a Prisma folder with a
schema file which is empty right now it will auto also create this EnV direct file with this database URL now let's
configure this database URL based on the dock the the environment variables we added in the doer compose it is post
post and password the username is post the pass the password is password the port number is
2010 and the data this is database name that is post class that is it we have the database schema
now I'm just checking if I can access the Prisma studio now okay so it has error because now we
don't have any model so it ask it is asking me to create any model it is also giving me a
sample let's create a basic database requirements that is required for the authentication we're going to
use next to for this and we going to actually manage all the user information in our database we're not going to use
any third party libraries so we use clerk the previous versions with previous videos
this video we're going to manage our own user information in our own database using next
Au so these are the models we have this user model with the uid we manage the created and updated
dates this this at default now you'll make sure that whenever a row created is created in the user model you will track
that datea automatically date time also this at updated make sure that whenever we update this
database will keep track of that date time and we have the name information now let's go to the admin
actually admin also needs the dates why not right so we have this U ID that's the ID
and uh this primary key has a foreign key is a foreign key to the user table as well okay so we cannot create an
admin with an user ID that does not have an entry in the user table okay now then we have this
credentials on Au provider in the credentials we keep track of the email ID and
password okay the password is going to be hashed it's we don't we don't save plain passwords in the database the
email has to be unique we also manage the dates the last table for Authentication
is au provider so right now we have we enable Google and credentials we can add more but that's what we are going doing
in this project this credential will need this credential entry for the user with the email hash
to password for the Google we we we cannot have the password hash right so for the Google this credential is not
going to be there but just the Au provider with the type of Google and this U is going to be the primary key
and the foreign key for the user table that is the minimum setup we have here for storing the
authentication information I have updated the schema file now we can do the database
migration pnpm Prisma migrate Dev okay this error happens because
okay as we can because I'm actually uh forgot to clean up the volume we deleted the existing service
right but I forgot to delete the volume so I'm going to reset that volume
okay I was just testing playing around so I'm okay with resetting that in
it okay so the the database migration happened and also it generated the Prisma client now we can open the Prisma
Studio that is going to open in Local Host 5555 we have four tables we can do
basic C operations [Music] here
okay yep so in this section we set up a local running Pro database we set up Prisma we did the migration now we are
our database is ready with the tables that are required for doing the authentication okay so we have our basic
monor repo setup ready we have our front end and backend applications created we have a local database running and we
have set up yeah so let's set up graphql in this section we will be creating a simple CR
operations through graph C that is going to interact with our post database so first let's start with installing the
dependencies we'll start with the core graph package and then the Apollo SL server we are going to use that as a
server and then the njs SL graphql to integrate the graphql with the njs and njs
slash Apollo to integrate the n JS with upo fine now let's go to the app module here we have to import the graph qu
module the installation is going on okay now we can install the import the graphql module so for in the for root
we're going to set up the app driver and so on so here we have to pass a type the driver
config here we have to pass few things like driver is going to be Apollo driver and I'm going
to enable introspection so uh the client sometimes need wants to that the client which is consuming the graphical API may
want to get the schema information so I'm enabling the introspection and I'm going to enable
GS add GS the field solve enhances so basically in the field resolver sometimes we may have to add o guards
where we will be creating that in the upcoming sections to protect field solvers we have to enable
this and uh let's also specify the schema generate generation the location is going to be the current
directory from the current directory we're going going inside the SRC and we'll be generating the schema SL
schema. gql file here whenever the njs file njs server runs it it looks for the whole uh app
module the graph modules inside it and it will generate a graph schema out of that typescript classes so that's why
this is a code first way of generating graphql API creating graph API and finally I'm going to
enable so by default the number scalar mode is is float I'm modifying that to integer so basically we are creating
typescript classes right so there we are going to specify a number the number property type and in graph we have both
integer and Float right so by default I want numbers to be converted into integers in the graph schema
file so we can switch between float and integer here but I'm going to go with the integer
so we have set up the graph C so next we have installed the NS config to use the environment variables so I'm installing
the ns/ config I'm importing the config module and uh we'll add that here to the root app modules
Imports we have one more thing okay we just installed a few dependencies and we have just added this code right we have
one more thing then cjson I'm going to add a plugin here so first let's start with the uh at
nj/ graph we will also come back here and we will add the NS Swagger for the rest API okay so we have to add
this there are some benefits okay so that's the ca plugin I'm adding here right the graph is ADD
as a plugin in the CLI so we have some benefits like annotate all input objects automatically I don't have to specify
all the fields with a field decorator with a field type and the nullable will be automatically be derived from this
question mark syntax and uh the type will be automatically derived from the type of
the property and the finally uh we have we can the comments will also be derived
and inserted in the schema so that's why I'm adding this fine we have we have set up
we have installed the required stuff now I'm going to generate a resource
okay we're going to create a mahle module it's going to ask for a module name the resource name let's give it
users because we already have a user table and we will just create a simple code operation for the user and we are
going going to do code first way of graphql so I'm selecting that would you like to generate code entry points
yes now this generated automatically see the SS ran and we we got this schema file
automatically because the server was running it was stuck in an error and when I generated what happened is in the
app module automatically it imported the user module the user module exists
here it comes with one entity comes with two dto for creating and updating the resware is going to
have three mutations for creating updating and removing and two queries for finding all finding one user the
service file is going to have all the business Logic the resolver file is like a router like it gets the request like
here you can see like three mutations and two request two query two queries right so we will have all the business
logic inside this surveys and we will just use that method we will try to keep keep this resolver file
light fine let's create a Prisma service so here I'm going to just copy this
um christma service file I'm going to create a u folder we will will delete you will delete these things I'm just
copying inside it okay we are just importing the Prisma client from the this is the generated
one whenever we do migration or whenever we do Prisma generate it will it will generate this types and we
are we just extending it and we are just calling the connect on module in it
okay now the Prisma module we can add the Prisma Service as a provider so later we will simplify these processes
right we will create a Prisma module we will make that a global module so that we don't have to keep inserting
injecting the services into the providers so I have to do this first and then inside the service I can now
import sorry inject the Prisma Service as a parameter of the Constructor now
we have to I missed to do one thing like U we have to first modify the dtos and the object type
let's have it as a have the schema fil side by side so only the uid is the required mandatory field right the name
is optional these are autogenerated everything else is optional so also I don't have to
annotate every field with the field the Creator the uid is string okay this is going to be Sim same same for all other
DS as well okay uid string update is also uid string
fine [Music] now okay I was in
the okay so there is a type error I have to pass the uid here and also okay ID is um string let's
just use string there now we can just use Prisma instance to create the user data and we can just pass the input
object and typescript is happy and let's do the find all user. find mini that's it okay now
I'm going to use the Appo Explorer okay studio. aap.com sandbox
Explorer and you specify the URL here which is Local Host 3000 SLG graph but it's giving me an error you can just
copy actually copy paste uh that given to see the problem to diagnos the
problem so is address correct is a server running connection
refused actually it's running the server is [Music]
running but when I try to access it in Cas I think it's a course error so in the main file I'm just going to
enable course okay now you can see the query is showing
up actually we will come back here for enabling course we will be actually specifying the actual exact Origins what
from from which Origins the API can be hit including our own um domain this playground The Local Host and so on but
right now it's this is sufficient for now for testing a crud in a graph qu you can see the query and mutations here you
have two queries for user users mutation create remove and update let's do the create one
because that's what we implemented I have to only pass the U ID from here let's say we have okay user
one okay now in the queries users we get back the user the the newly
created person let's do one more [Music] mutation let's do two more
mutations and we will come here you can fetch the data okay this is
a a light way of building graph C we don't have any sorting filtering capabilities yet right think about it
when you have there are a few problems so this entity is not directly connected to the schema we have the database
schema right what if I change this uid to ID this guy won't know but actually we will get error here okay so this
create user input will have the ID and this will have a different the Prisma will be expecting a different one but
that is not a reliable way right so the the the next section we will be using this
package okay this package I this is just a code General package it's not a dependency I wrote uh you can spe you
can generate a graph Q resource that is going to create a lot more DTS for filtering sorting finding
pagination and so on and everything is going to be derived from the Prisma types you can generate graphql resource
you can generate a rest resource this will be a lot more simpler and automatically it will
generate all these commonly used uh types Prisma service with a Prisma Global module common input types and all
decorators gods and so on so we will uh just start using this package to create our
resources and uh our graphic AP will be a lot more deeper and Rich compared to what we have
here so we have a really simple graph G setup here we have a query we have a we have one mutation ready I did not I did
I did not implement the remove user and update user because I'm going to delete that code
and we [Music] will use this generator instead okay
it's just a Coden I'm going to create this extensive code that has both the
graphql and rest modules okay actually this is one module with both the graph qu and rest rest
API in place and we will have this resolver for the graphel controller for the rest
we have DT for the rest AIS really in-depth DT for the graphql that has this find ARs with
pagination uh skip take cursor um wear filtering sorting even distinct okay all these things are there
we have this create update and everything is going to be imp is going to implement the types from the Prisma
so whatever we build in the the API will directly raying on the types that got generated from the
database so before we get started I'm going to clean up I'm going to
delete the code we created including the Prisma one okay so we have deleted the Prisma
code and the uses model and also Let's uh the user app module we have to delete
this and we have reset back to where we have where we were now we need to add a few more
dependencies first one the dependencies that we need for implementing the rest AP I'm not going to go too incremental
we saw a simple example how to create it using nestjs CLI generator uh we did not have all these
facilities right so so initially I was planning to go step by step first maybe we could have
created the graphql first and then we would have created the complete one but I'm going to directly create the
complete version with the graph and API so let's install the required dependencies go inside the
API we need the nestjs Swagger we need class validator and class transformer for creating the
validations okay so we also want to include one more package called sj/ GWT because this code is already is also
going to generate this next o decorator o Gods um we will come back to the we will
focus on that in an upcoming section so in order to satisfy the typescript I have to install njs
JWT nestjs JWT okay this package this is what we used
to sign and verify the JW tokens okay we have all our dependencies ready now let's create I'm going to use
this code gen I'm going to create a complete version for the user model and then
later we will create for other models as well now I'm going to just add for the user this will create automatically
create the common directory with all the O guards even Prisma service and module uh types file you will
see just won't ask any questions uh we are we rely on the flag actually so I'm also printing all these files and
folders got created inside the common we will come back to that I don't want to
[Music] overwhel so these are the common D the common D this is the D for the rest API
we have skip take their number this is a search value the order value actually we will you we will further
extend this base query dto inside the model we are searching but which field we are sorting this is s order but but
which field right there we will actually extend the um enum the fields of the particular
model and we will set that as the field the search field and the sort field this is the common DT for graph CU
we have all the the daytime filter string filter string list filter which is an array of which which will help us
to filter an array of string in filter float location filter we need this this project because we have Geo filtering of
garages and also page input so we have the Prisma service this is exactly what we had last time we have
Prisma module which is this is a global mod module we have to actually add this in the app module let's do it we have to
import the Prisma module now we can automatically inject this is a global module so we can automatically inject
Prisma service anywhere we want and we have a simple types here rle and uh get user type you will come back
to this when we deal with authentication that is all the common files common files
we have the users now let's U work with the graph CU now starting with the entity you can see that the the user
class is implementing something the restrict properties is a custom type utility so it gets the class
it gets the type so we get the user type from the Prisma client the user type has these scalar types youu already created
at name these objects these are the joints other tables actually credentials out provid and
admin so it restricts okay they can only have these properties and also along with the type okay key of T type of T
they cannot have anything else you'll see it in action so you can command period control dot you can implement the
interface okay when now you cannot remove a property this class the user class has
to be in sync with the database you cannot remove a class you cannot add an additional class okay types scpe won't
[Music] allow okay you cannot have anything this has to completely match the database
schema okay all these things and you may wonder that what happened to this admin out and
credentials these are field resolvers okay we will deal in the graphql use as field resolvers we will resolve these
fields fine now one drawback is we cannot do this the name is optional right in the schema the name is optional
but you cannot do this because of the design I came up with okay that is a short that's a shortcoming okay when I
was to um and I was trying to create this sync between the database and and
API this syntax we cannot use so for that we have to use the nullable field field decorator with the nullable
property called true fine now what if I want to have I want to Def from the
database schema for some reason if for example if we have a password here I don't want to include that here right so
in those cases you can use the omit utility type you can mention for example let's mention the name now you cannot
have name in your class see but I don't want to do that but this
is a pattern we will use throughout the application okay let's add the name let's also decorate that
fine okay let's move to the dto create D I'm using pick type from the next graphql so I'm going to pick pick the
uid first and the name the good thing is I mentioned the name as a nullable property right I will show you in the
generator graph schema in a bit that that will get transferred the nullability or nullness I don't know the
word that null [Music] Factor will get transferred to this
create user input object as well also when you want to you can also add more things here like age for some
reason if you want you can add Nothing Stops right this is the create user input dto the update I'm using I'm
extending the partial type of the par type of whatever we get in the create user input obviously you can add more
here I making the primary key mandatory the primary key is not User it's not ID it's U ID right also I'm I'm not like
doing this right oops U ID fine now I'm not doing this even the type I'm getting from the
user object that is from the Prisma client okay you a string so when the database changes when I CH when I go to
database and change the U to number I don't have to come back here and change so we modify the entity we we
pick the type from The Entity this is the entity okay the class I'm picking whatever we I want from for the for
creating the user also remember you can add more Fe add more Fields here for the update I'm getting the partial type of
the create user input and I have to specify the primary key okay that's all for create mutating
DS let's look at the queries dto the first one is the find many Argus arguments that has
all this is for this is for filtering this is for sorting this is for page ination actually we will use Skip and
take for pagination in this project but we are also going to export this as an API API as a product okay AP as a
service so you the clients can use a cursor also they can ask for distinct values in a query now you are having an
error here on hovering over it it's it says that uid is missing in the Type U string
is missing okay what's in the type this is auto generator right so I generated for majority of cases which is ID number
but in this case it's uid string let's update that now you go back here TPT is Happy
fine let's move on to the next one which is let's work on this uh wear input also one more thing I wanted to
say everything is optional right I don't want to I don't want to add this I don't want to add field nullable true to any
everything so that I'm creating this object first this class first and then I'm extending a partial type of that
okay so I don't have to declare I don't have to decorate that so this will be used in our um R
solver we will see that okay let's work on the user input type now the same Technique we are using here
also I don't want to Mark everything as nullable so I declare a a strict type and then I make everything
partial okay let's implement the Prisma user input these are the properties but I don't want everything
right so I'm going to ignore these three let's use the one it
okay fine so I I omitted this three so I cannot have that I don't want anyone even admin to filter or sort or actually
filter based on the credentials fine and also this is not understandable by the njs right they
cannot take this and convert that into graphql this is where the common dto come in place you
remember this file you have all the string filter in filter buold filter and so
on let's do it for the date filter as well and this is string nullable filter everything is nullable in a filter so I
just uh use the string filter and everything is nullable becomes nullable partial because of this partial type and
whenever we use in M we have to actually decorate it injs cannot sjs can understand what this is this is an input
type I don't have to decorate that but when whenever it comes to a enum we have to
manually explicitly decorate that field fine the we is done let's move on to the order by let's do the same thing
here and let's do the same thing I'm going to omit the credentials out provider and admin
fine now we have to remove this and there are like sometimes there are two types like order it makes the
nulls but I don't want this and whenever so it's an enum sort order is an enum so we have to decorate
it or else you are going to see an error maybe we'll see that error and come back
here okay that's it we started with the entity we we picked the type for the create
we made everything from the create user input into it into that aspatial type we went into the find ARS I I had to update
the cursor and we went into the where we implemented the thing I I modified this
right from the common dto also in the order by I um I just implemented it after
meting the unnecessary I mean the fields which we don't want to sort that's it let's go into the
resolver we have a couple of problems here and this problem is actually specific to this user model because I'm
getting this um this is a requesters user object okay this goes through this o guard and
we get this o object I named that user so I'm getting some conflict here here so
let's just rename that also you have to make sure that it's
uid same thing happens here I'm just fetching the information actually this itself makes sure that I'm just fing I'm
just making sure that whoever is trying to update the user is the owner of the property is the owner of the row right
I'm using this is the uid sent by the user the requester so I'm getting the user object and I'm comparing that this
is a requester okay this is not the user sent input this we get from the header of the request so I'm just making sure
that the requester has rights to update the row and also this is a bit interesting this checks the lower row
level permission if the request is an admin then the whole request will get just bypassed
okay that's the logic now I have fixed the code let's also go to the service we have a couple of problems because in the
generator code I'm I'm assuming that the U ID is ID is the primary key so I just have to modify it as you can see in
other uh models with the primary key of ID number this is not going to be a huge problem you don't have to modify a lot
of things like like I did in this model okay let's also go into the rest I have to I try to reuse the same
entity class okay but I had issues I'm still experimenting with it the decorators are
different last time I was using field with a nullable property remember but this time I have to use the is optional
from the class validator here also you can use the omit I mean using the
same utility type utility everything is same but I could not use the same
entity for the rest API here I have to use this right I could not use the same user entity I
created in the graphql here this did not work there so I had to create one more one more entity for
the rest API this is going to be simple simpler actually for the create user I'm
omitting Ty you can ask pck type but this pck type is coming from the njs Swagger not the njs graph
qu so I'm picking the uid and the name
fine and the query right so we we saw this base query D now I'm extending that I'm adding two more Fields one is sought
by the value is going to be coming from the user scalar Field in enum these are the fields that the database table has
the user table when we add more tables when you do the migration this Prisma Cent will get generated regenerated and
that new field will occupy here [Music] okay and that's and you will see in the
uh Swagger UI this will be an drop down okay you cannot pass anything else for the search by or sort by
it has to come from the fields that the table has Fine similarly in the U ID I'm doing
the same thing the partial type coming from the NJ Swagger and you have to specify the primary key which is U ID
let's go to the controller this is we are creating it I'm using the r level check here I'm
getting the dto object I'm using the Prisma instance to create that we'll come back to all these uh maybe
another section for Swagger decorators for find all this is interesting right if the skip
is valid if it's not null or undefined I'm creating this object and I'm spreading it if the skip is null
undefined if it's not defined by the user in the request then null will get I'm
destructuring the null I'm spreading the null if you spread null you get nothing okay so that's how we conditionally add
a property inside an object here we have to do certain things you have to change this ID to U ID and
the uid is string okay let's do that here also here also I have this user name conflict
let's modify that and then I have to modify this ID into U id
id U ID string I'm also renaming this user info it's going to be simpar in other
models I keep saying that fine I have worked with all all of these things now let's just have a let's just
restart the server there is a problem oh I did not actually add the user
module in the app module I added it now we still have an error is this about the sort order oh
JWT service oh okay so I installed the JWT right now I have to import that in the app router app
module Okay so so after we configure the config module I'm going to import the JWT module from the njs
JWT I'm making it Global and um okay let's all okay we are we also have to in the environment
variable we also have to declare this JWT secret okay I'm having a simple string here but in a production deployed
uh server you have to make sure that this is hard this is strong password Secret
also I'm going to actually have a U library to store this max age because we also have to have this in the front end
where we are signing the JWT we need the same Max H but for now I'm going to have it
here and this max age is exess is in seconds so I'm just making that this one day 24
hours maybe let's quickly have a to-do move move this to util Li library library fine I have
added the JWT model because that this jwd model is being used in the earth
guard okay J service we use the GW service to verify the token fine now let's
see what error we get next JS is still not happy it says cannot determine an input type
object make sure is your class is decorator with an appropriate
decorator okay so this error is really tricky it does not say okay fine fine fine so it says the error happens for
the uid okay it does not say which class name or which file name the error just says cannot determine a
graph input type object for the uid so when you get this error in an sjs you just copy that search for
that and uh look for the class names this can be understood right this can understood by the
sjs the string string filter can be understood string is understood everything is fine
except this one this does not know what is this so that's what is saying that the object
cannot be assigned to this uid now let's add that okay I added that now the aror
should say something about the create a do okay cannot determine a graphical input type object for the Creator ad
when you search for that everything is uh NS can understand what a date is what this date time filter is it's just input
type you cannot understand this so I have to decorate that okay so let's just decorate over
everything for the whole sort by arguments now the NJ is running let's open the I'm going to use
this studio. gra.com that's what I using that's what we used in the previous section right okay this time
it's different okay this time it's personal we we still have the same queries we still have the same mutations
but look at this how cool is that we have filtering sorting
capabilities we have we have page let's let's start from the page Nation okay we have all these users
now fine okay let's uh start with the mut with the mutation so that we we get more data
let's check the create user mutation getting everything back we also have this oh create
user what happened to the what happened to the name this is user
4 can I pass the name something is wrong
okay maybe I should refresh it fine I think now you will get okay yeah now you get both
the there was some cash issue going on now we have both the maybe I'm going to give my
[Music] name no token provider wow okay we have not implemented the authentication yet
so uh user resolver I'm going to just comment these parts out so that we can test this okay I got that got
created let's just have uh some uses created fine we have some uses now let's check the okay let's
let's enable the authenticated authentication again let's PCH all the uses okay we have all these users along
with the users we we created now let's just the pagination skip zero take two that is
going to give us these two if I skip two we get other two if I if I skip four we get the last two okay so similarly
you can um you can use everything in one go actually pation filing sorting everything in one go but I'm going to go
step by step let's sort let's sort by name ascending so let start with the K
yes and then it's um null okay it started with the D and then we also we can also check the descending
it starts with the null first and then yes KD fine we can also sort with the uid okay so it starts with
the yeah it's descending so it's the user 4 user 3 3 2 1 yes and D fine that's
starting let's quickly do the filtering okay filter by we can also have an array okay I'm going to just
filter by so look at this all these things can be used okay I'm not really worried about the performance now but
look at the power like look at the depth we can go while filtering not just this when we include
more models you can you can do nested filtering nested sorting in multiple levels
so I'm just using uh contains here again just not completely we're not worried a lot
about the performance but oh okay nothing has user we also have to we can specify the
mode to insensitive oh that's still error oh okay so it's U ID uid has a user you can filter that okay what if
uid has car so that's name fine okay you can filter based on
insensitive sensitive okay so that's the graph Q uh in the upcoming sections we will
okay let's also set up the Swagger okay so we have our our graph C API working with just one module which
is the use of one we will build more later but before that let's work on the rest API so this is what we have when we
open the API the njs project the homepage I'm going to set up the Swagger let's open
the main file so before we start listening I'm going to create this config the import
the document Builder from The Nest Swagger so we can set the
title for the document I'm going to call this Auto space [Music]
pipe and I'm going to have this is this is how we create the document that's the P that page and I'm going to set up a
description it says the autospace API looking for the graph API this is the homepage is going to have the rest with
the Swagger UI which is interactive we will see I'm asking looking for the graph API go
to/ API SL graph you might also have to use need to use the this will open so right now when I have when I go
this we have a graph playground okay but we don't get to choose that those fields okay I really love using this
interface this is easier I don't have to type much so I'm saying that I'm go to SL
graphql you might also need to use them and the link goes to the studio. graphql the end point we are actually
passing the end point here which is this and also document so whatever we pass here will come
here okay so automatically on clicking it the URL will be populated the document will be the query will be
populated you will see in in in a bit that's it for a greater experience apple apple
Explorer then I'm going to set a version1 add barer o and then build it okay that's the
document config now I'm going to create a document using that config okay we need the Swagger module from the njs
Swagger I'm creating a document I'm passing the app and the config we get the document
back now I have to use the Swagger module to set up the app and the document in the homepage that is it
now when I when you when I open the port number 3,000 you will see a different interface
okay aut of space this is the head this is the doc this is the description but I don't know why this
is oh okay I'm having this as a h okay you can have more on clicking this
it will open a new tab with this Apollo I mean yeah graph playground you may need to
use a Explorer I'm clicking this it will open a new tab the URL will automatically be populated the
user we have the query okay users can just click it and can can interact with that now we
have this is interactable actually let's let's get the get all users write
out execute this comes from our database okay
[Music] now okay what happened to the parameters okay that that is because I
did not add the nest Swagger as a plugin okay I've added it let's restart the njs
server now let's go back to our UI okay now we get the
parameters let's get all the users now you can specify all these things okay this is okay I have to try
it out now and you have to select the field which you have to sort by I'm giving it a uid I'm going to go
everything in one go everything by uid maybe search by
name okay search by uid probably search string is going to be user take skip okay
02 order by string I'm going to order everything by descending let's try it so it gets two items it's descending
by U ID okay and also it is looking for the term user in the uid if I take these
two you will get every every entry that has the word user in the uid because in the
controller I actually in the users controller I okay I'm really sorry like uh yeah
there are a few issues here I did not implement the search [Music]
here okay I just followed the same technique here I am if the search by is true then I am including the we
condition I'm passing the key here and the value the value is going to be inside the contains this is opinionator
right the graphql API was much more versatile the the the client can actually specify what kind of filter
they they they want to do but here I'm giving a opinionated contains I'm passing the search value here and they
making insensitive every search is going to be insensitive by default now we can come back
here let's do something else car okay we don't have that okay so user okay so we have four items the uid
with user and it's also insensitive right okay let's maybe sort by the
name descending now we get the name starting with a null in the beginning and then we
will go to the K search by name String car now you will get one value with the
name Kik okay this is RIS API let's let also post uh a user uh this is the request
body [Music] um
ganguli okay I think okay this has to be this has to stop actually we are going to get um unauthorized okay no token
provided we are I'm going to disable the all authenticated kPa bar also this also
this let's do this we will come back and um go through that yeah authenticated authentication in sjs in
the upcoming sections now the user got created now we can go back
here execute it now we get all the users sorted by name in a descending order okay it
starts with a u ends with d f let's also quickly find one user Let's uh look at the newly created user we have to pass
the [Music] uid and we get back the
response okay maybe let's create let's delete one user this also needs this authentication I'm going to quickly
comment them in order to do this I'm going to delete this user
for try it out give the U ID execute you get back the deleted user so that we can show some you know dialogue
or a toast message about the user who got create who got deleted let's also get delete the user
three and user two and user one okay we we have deleted those generic
uses now let's come back to the let's fetch all the uses the interface is actually a bit
clumsy you can have a sidebar have these routes and uh we can select here and we
can have a playground sort of stuff the right okay now we have three
uses where did I [Music] go okay the user 4 has my name okay so
it is gone now we have only three users now and yeah that is resty API Swagger user
interface so one problem is I I make sure that it's uh is optional but that is not being reflected
here okay it did not reflect here but as you can see when I create a
[Music] user when I create a user the name is optional okay but the documentation is
not showing that in action this is exact entity I'm using for uh implementing extending the create
user that's what I'm using inside the controller for creating right and I am able to create the user gasar
without passing the name okay but the user interface is is still showing this Aster
symbol making it a man making it look like it's mandatory okay maybe I'm missing
something but functionally it works good maybe I have to add I have to decorate more to satisfy this but I'm
just going to move on hello everyone our back end the the graph
API uh is working good the rest is also working good now let's have a quick walk through about
how we implement the authentication in our back end so we create this um decorator
so first we are setting some metad data we are we are getting an array of roles which is this okay you can have more
maybe I'll just have the manager here but remember we don't have the manager table yet but upcoming sections
we will set up all the tables required and uh everything will make sense so this
decorator now can be called like this in the comma separated way we can specify the roles that this particular
decorator has to allow so first I'm setting the metadata and then I'm using the O guard use I'm
passing the O guard inside the use guard okay first this happens and then this happens so let's have a look
at the O guard so basically we are first getting the graphql context we're getting the request from that and we are
passing that request to do two things first the authenticate user so inside the
authenticate user I'm getting the header the token first I'm getting the header I'm getting the token from the bar
header so this is how we will pass from the client if there are at this point if
there are if there is no token then we have to show this error I think we faced this error when we try to create the
user or something so if there is a token we will use this JWT service so remember in the app
module we imported this JW module where we pass the secret and also other signning options like maximum age
right so that's what we are using here we are using we importing the JWT service from the nexts JWT and we are
injecting injecting that so we get that instance and we verify the token
and we get the user object back there which is the payload whatever that is inside the
token and I'm just attaching that to the request so after this part if there is no
request I'm giving another error which is different right this is no token this is invalid
token the second one is authorized user this authorized user first I'm getting all
the okay actually this has to happen later first I'm getting all the required rules from the get metadata remember in
the decorators file we are passing an array of roles that's the metadata okay and I have a helper method here that
helps us extract the metadata based on this is the key okay I'm also passing the context
so this is how nextjs wants us to get the metadata which we pass using the set metadata okay this these are decorators
actually we can use it above our queries and mutations separately but I'm combining
two decorators into one okay using a reflector passing the key
we also have to pass the context get Handler get class this is the syntax has ask us to do so that's what I'm doing to
get this rules so this is going to be an array of roles if there is no if there is no R
specified the The Decorator we saw right allo authenticated can be used like this without any roles so this means
that that particular route the query AR mutation should only be accessed by the authenticated user when
I when we start specifying the admin or something now that is the required roles I'm going to delete
that fine so if there are no roles specified we return true we are bypassing the whole
method if not I'm getting all the you roles that the user has I have another helper method here which
just uh um why don't we have just like this this is okay so we are I'm declaring a Mt
roles array and then inside a promise all I'm having an array of uh promises which fetches multiple rows from our
databases when we have the Val and manage a table we may have to look for those roles as well if if that user if
the if a row is present for that user ID then we are just adding that role inside this uh and uh I'm just returning that
that is all about the get user roles now we have the required roles now we have the user
roles now I'm checking if some of the roles are present in the user roles okay if the admin and manager are allowed to
access that we are checking that if the user as either admin or or both right at least at least one has to be there in
the user that's all about the AR guard and Earth decorator and this is a ro level
permission check function which gets the user object which has these roles and uid the requested ID this could be
something that the user trying to modify right in the in the in the update mutation the user has to pass the
primary key when they want to update the user they passes a primary uid in the update in the
input request input there is the uid in the request uh header right the request is we get from the JWT that is a safer
way to know who is calling we are matching if this user ID if both are same also we are having a bypass here if
if the requestor is an admin [Music]
okay if the user request is admin this is also an an argument right that's a parameter they can specify anything they
can even specify the manager here okay so both the manager and admin can modify resources that belong to
others so we are just checking if they are same and um if they they are not same this is the third type of error
forbidden the first error is no token the second error is invalid token the third error is
forbidden okay now I'm going to just go through the uh look at the graphql let's go to the users resolver
I'm going to just use this one to test our to see our allow authenticated decorate in
action fine so now not everybody can access but the only authenticated user can access okay let's try that route
this is the user route I'm just sing something what oh okay so I was okay I was testing I
was so before this session I was practicing so I added the header now we get the no token provided
that is the first error no token in the header now let's fabricate a token for that we need the secret okay this is the
secret which we will use in the front end to create that okay when the user logs in this is
the token we will create to this is the secret we will use to create a token
now let's fabricate a token so I'm passing the secret here I'm opening this jw. iio I'm giving some payout here this
is what we will get once we U verify the token okay I'm giving a value uid called
ganguli we have a user called ganguli here okay this is a token valid token copy
that add a new header authorization beer followed by this string now I can
access okay let's also put a console log out guard that is the payload
right payload JWT payload
right when I test this you get this okay that's the payout that we put inside the JWT
that is the first test only authenticated users can pitch all the users and that is
working now let's uh create a uh wrong token right I'm giving a wrong secret copy the
token pass as a bar token now what we have to get a different error invalid token so this is the
second type of error first we were we were getting the no tokken error now I passing a fabricated token fabricated
with a signed with a with a wrong signature now we are getting invalid token
okay let's fix it get the right one now the third Let's uh let's try for the to third token
third error for that I'm going to enable a role here called
admin only admins can access okay one more thing actually while explaining this I told you that
this is the third error but actually The Forbidden happens here also so here when we are checking two
arrays making sure that the the array inside has some of the required rules the that the user at least has some of
the US when it fails when we return false from here we are going to get a forbit an error okay
that's we are not manually doing it explicitly but when this call activate can activate returns false we are going
to get this error forbidden resource okay when we manually do
it when we explicitly say it is forbidden okay we'll come back to that that's the fourth
actually third one is forbidden resource because only admins can access it now how to make this guy an
admin so that that's the uid let's make that person an admin just for testing go inside admin add
record gungi save now the now Gung is an admit admin now gungi can view this
okay now one more case what if we give a uid which is not there
right that's a case which I should have tested earlier but let's do it now forbidden resource okay no no
no even if the admin is not there that person is not even in the database okay I think I just found a loophole in
the system so in the a guard in the authenticate user yes we verify the
token we get back the user user we are expecting the user to have the uid this is the payload maybe
let's just call it a payload okay the payload must have uid if there if it does
not have then again it's an unauthorized exception it's an invalid token okay for development I'm going to I'm going to
just call like no uid present in the token something like that and then I'm going to find the
user where U ID is allowed let's assign this assign the
uid from the payload and then we can use that to check the uid is not there you are
throwing an error the uid is there we are getting the user from the database if the user is not there we are
throwing a different error no user present with the
ID so I'm making uh this elaborate error messages for testing for development okay for when uh when we are dealing
with a consumer facing client facing application we don't have to be really clear about these errors
also I'm I'm going to make this product as an API first also I mean API as a service we going to expose API both the
rest API and graphical API so sometimes an elaborate error is helpful for the consumers but again this is in a de
development stage so and I just wanted to add that uh giving elaborate error can lead to
people finding a loopholes in the system now I just patched the problem okay so the uid the payload now has the uid if
there is a uid the uid has to present in our database if that user does not present
then we are throwing other eror okay now I I not change the bur token but I changed the logic now I'm trying
it come on oh okay so I need to await this okay I'm
sorry now I'm getting invalid token okay so actually I have I have to rethrow that error from inside
the catch now I have a a right token but with a wrong uid that uid is not there in our
database when I try access invalid token no user present okay now let's um do that check that other one with the wrong
secret now we will get that error message which is invalid signature okay
fine so this happened when uh when we tried to verify this thing failed and we got caught here you you can also see the
token validation error message you're console logging right just on web token error invalid
signature we are again throwing that right so we get it here invalid signature it's an internal
server fine we are protected from different directions now let's um look at the
authorization this is a valid uid valid signature but but that guy is not an admin let's enter the valid one
and in the resolver user resolver I'm going to make it only admin admin only access this is a valid token which we
got the results now we get the Forbidden resource fine right so we have like tested like five levels I actually
explored a found a problem with the authentication system and I just patched it
now finally we have one more thing like uh okay for testing let's do this let's say this resource can be
accessed only by the owner of that row okay that person has to be authenticated now we get that authenticated user by
using this get user param decorator let's have a quick look at that param decorator this param decator
gets the context the graph execution context it gets the user. request. user remember that we passed we set the
request that user here we set the payload which is user information also inste authorized user I'm also setting
the roles inside the user request. user we are just getting it instead of using this param decator you can use this code
directly inside the query or mutation this saves some time now what I'm going to do check R level permission I'm
passing the user here and then going to pass the a.w. uid so the requester and the uid
sent through the input has to be same okay let's try that query user I'm
pitching all the information here now I have to pass the uid here right the uid is
Gangi the header is already populated Kung can access the data but if I want to access the data of
the drait it is forbidden this forbidden is coming from
the this place okay forbid exception can I pass nope there some random message to
see if that is what okay okay okay so that for is coming from the RO level permission yeah so now I can go back
here I can create another JWT with another with another uid and come back here and try to access different user
but you will get this Noe I mean the Forbidden error that's the Earth Gods Gods
decorators s the RO level permission okay so our graph C first API are ready along with the authentication
we have our cards ready with decorators now the problem is the
routes for creating user is not clear right that this is not how we create users we will use next o and we will
register user when they interact with next to so we need two routes here register with credentials register with
provider let's work on that so instead of this create user input I'm going to have two first
one let's call it um [Music] register with credentials input
we going to get name email password and optionally an image the second one I'm going to rename
this register with provider input I'm going to oh we don't have image actually
okay okay no need for image but I'm going to get the a
provider in this uh mutation we know that the provider credentials but when somebody is using a
provider route then we have to know what type of Provider the user used to register right now we only have
Google but later when we introduce more user actually needs to send this so these are the two
dtos now let's uh work on the reg um mutation okay let's import both the register with
credentials input register with uh provider input the resolver is going to be
simple this is the register with credentials we need to create
this service method we will do that lot of noise
so basically we are getting this input type we are calling a service method that's all this mutation is
doing the second [Music] one the second one is
similar this is register with provider okay actually let's just simplify I don't want to have a try
catch here because whatever we do inside inside the uh
service we can throw an error so that is not required I'm just returning the let's just simplify it
okay so basically we created two types of input uh input types and we are just created the mutation one for registering
with credential one for registering with provider now let's implement the user um those mutations
inside the user service we don't want this
anymore okay we can delete that register with
provider that is the first mutation so we are getting the name uid and type
let's quickly do a mutation okay let's add the I forgot to add image here let's I have added it let's do a
migration pnpm Prisma migrate Dev add user image fine now in the create
user we can add the image image here okay must we have to add the entity also when you restart when you
reload window you will get some type error here because we just did a database M
migration and the API and the database are not in sync now immediately we get this type error and um we cannot build
the project now we have to implement that the image is nullable so I have do this also let's update that rest
API okay that guy is also complaining okay image optional fine now in the
create D I add image here that's it let's proceed so we were working with our
service file now we can get the image name U ID and type the register with provider is simple actually it is just a
mutation I'm just using the Prisma instance using the user. create passing the okay actually we have to pass inside
the data now we can pass the uid name image and then I'm going to get going to
the a provider create create new pass the type okay that is one mutation now we
have the resolver we have done this okay now we have one way of uh registration done
let's implement this register with credentials next this is a bit tricky we are going to create a uid we are going
to Hash the password and so on let's do that the next one is register with
credentials okay that is going to get the register with credentials input as the input we get the email name
password and image from that okay first we are checking if the user exists already with the
email if the user exists already I'm going to throw an error maybe let's call it bad request
exception user already exists with this email and then I'm going to Hash the password plus I'm going to get a for
this we we need to install the bcrypt JS we also need to install uu ID for creating a unique ID so let's install
both these both of those dependencies uu ID I think we also need to install the types for them
okay now I'm going to import bpjs also I'm going to import The UU ID
so that's how we they export it so it's going to be like v4s uu ID now we get the we got the
bcrypt we got the password hash Now using the we generated a salt and we used that we pass the salt and the
password create the hashed password let's create The UU ID okay that's a unique
ID that is it now we can create our user so just how we did in the register with uh with providers user equal to a wait
this. Prisma do user. create I'm going to pass the data that is going to have the uid first
the name image and then I have to specify the
credentials create email password hash that's it and then I have to
specify the Au type the Au provider create type is going to be type type is going to
be credentials fine so for this I'm so in the return type I'm also going to after the data
I'm going to include the credentials that's true because um when
we register it from the next St we need the credentials back fine so actually we can just return
that you don't have to store it into a user and return that okay so basically we got we we
check if the user is there the user is there I'm throwing an error and then I'm creating a has password creating a u ID
and just register that user in the user that's it now everything is almost ready the user
generation user registration okay I have to actually run
the application now you'll see different mutations
oh fine see some Type errors actually I'm going to omit the image because I don't think the
image URL is a valid thing to filter users so you see the point right when I did a database migration you have to fix
the API okay for updating I'm going to get this um maybe let's just get the
user user from The Entity that works okay for updating you have you can pass anything here but you
have to mandatorily pass the uid okay fine there's one more error that's for sorting okay here it is
complaining that the user has an image and uh you don't have that in the order by I'm going to Omit that from
sorting okay that the image cannot be used for filtering or sorting the URL has no has no
meaning now the AP is ready actually it is showing some error
oh oh okay so this is again this is an enum so I have to decorate that okay here I am decorating
it oh okay one more thing is whenever you deal with the enum in the nextjs I keep like inventing this gotas
but uh in the common input you you would have seen that I am registering that registering enams right the query mode
is a enum I'm registering that similarly I'm doing one more thing the sort order is an En I'm registering that right so
similarly I have to register the a provider type before we can use it before we can use it here we need to
register okay so I'm going to should I just do it here register enum
type or provider type okay so that's one more thing we have to keep in mind whenever we deal
with the enums you have to register it also you have to decorate that you have to spec explicitly specify that in the
field decorator now you have
the graph you working and you are you're seeing two types of mutations let's try to do one
thing let's to register let's register a user using credentials so we have to pass all these
three four values and I'm going to skip the image email k at
email.com password okay now we got back the user information the newly created user the
image is null the name is there there we generated a u ID let's also go look look at the hash
password okay this is a newly created user I this credentials you can also see the hash password there okay that's one
mutation also the a provider is correctly specified as credentials let's do the next one
register with provider getting everything back and
also so you can see that I'm not I'm typing very or less here right I'm going to call this C
Google you get this amazing drop down right it's cool also you have to specify the uid here Google
ID okay that mutation went ahead us got registered okay this Google ID this is the newly
created user I'm seeing the Google name here there the credential is null we don't have credential there but we have
the Au provider which says Google hello everyone I forgot to add the login
mutation so we start with creating two types one uh input type I'm just extending
I'm extrating the register with credentials input I'm just getting only the picking email and password from
this and I'm declaring a login output which has only the token and string now in the user resolver I'm
creating let's focus on one mutation first I'm creating a login mutation this is the the login output right which has
the token string that is output the input is login input the email and password and I'm creating a new method
in the user service this is the login method so we get the user email and password we are
making sure that we have the EMA we have the user there if there is no user where I'm throwing an error invalid
email or password and I'm making sure that uh I'm comparing the password this is this is a
password from the input this is the password hash from the from
the query is the user row you get we we include the credentials when we query the user and we can get the password
hash from the credentials if the password is not valid we are going to throw the same
error to confuse the hacker you know so if everything is fine I'm creating a JW token I'm again using the jwd service
right we used this to verify previously now I'm signing in I'm for for the payload I'm just passing the
uid and I'm mentioning the algorithm to be HS 256 that's it I'm I'm retaining the
token let's have a look at that first we will register a new user let's call it user 1@gmail.com
this is the user one with the same password okay we have registered that user now we will see that user here user
one with a custom uid there and then let's um try the login mutation
login select the token the email is user1 email.com Let's uh pass a wrong
password in invalid email or password right we pass email wrong email we're going to get the same
error okay now let's pass the correct password now we get back the token okay now we can put it inside the
jw. iio to see what the to see the payload it it has issued a date and expir date the
expir date is one day from now okay it is 4:45 a.m. so 25 24 hours
right and yeah so this happens because we specified the max age here this is one
day we deare we we imported the J JWT module in the app module so when we use the JWT service
anywhere in the application we will have all those properties together the max the password this the JW secret
everything right we don't have to keep keep giving the those values here fine so this is important right
even though we are going to use next to from the front end we are not going to actually hit the
login uh route but we are also going to expose this as a API so people have to be able to register and login get the
token and then they will be able to hit the authenticated routes right that's why and I also created one more route
here called who am I okay this basically this won't get any arguments this just gets the user from
the header it Returns the user user object let's try that in the who am
I query who am I select everything we don't have any variables to
pass so initially it's going to complain no token provided so we have to add the add the header
authorization Bearer I think this is the new token a95 a95 is user right let's add that
call it now you get this data K a95 user one without passing any variables okay this these two routes are were not
planned actually but I wanted to add so that the API can be used independently
okay there are some drawbacks like people can this is an unauthentic route registration usually is
unauthenticated uh so people can keep creating new unwanted U IDs
okay but we are not sending back anything we are not sending a token or so people won't get access but they can
spam the database okay they can create keep creating dummy stuff like this
okay so that is one one small drawback one drawback no drawback is small um
okay hello everyone so we have a problem I had uh I faced a problem making the nestjs work inside a pnpm monor
repo problem is so we Ray a lot on this njs graphql plugin right it does things like it automatically underes all the
properties in the input object all the properties in the classes with the field decorator right also it automatically
gets the type from the typescript and conveys it when building the graph Cel schema so all these things this thing
was not working okay it has something to do with the reflect metadata not sure I was discussing with the in the njs
Discord server and I canot make it work so the options we have are we can actually go inside and
it's a huge graphical project and also we go really hard at building the d2os and you know so it's going to
be really hard for actually manually annotating all the properties and all these models
modules instead I'm going to just switch the package manager it has something to do with how pnbm stores the node modules
in the Yar there is something called um a no highest option I canot find the an
alternative for in the pnpm workspace so I'm going to switch the monoo from pnpm to
yon okay let's proceed first so all these are empty
folders I don't know okay I was building and uh when we actually check out the previous
permit the empty directories are are not automatically deleted I will clean that up fine so first we have to so instead
of the bnbm workspace yaml file I am going to open the root package.json and we are going to have
the workspaces option there it is still private and inside the workspaces we going to specify
packages so we have this no hoist packages to block from hoisting to the workspace route so that's what we're
going to do to avoid to host all the dependency of the njs to the root of the monor repo and that solve the problem
okay so the packages is going to have all the apps and their
lips and everything inside it and also inside the no hoist going to specify njs
okay come on fine now I have added it I have deleted the PN spaces I'm going to
delete the lock file here and you also have to make sure that you have y
installed you can simply install p npm i globally on and that will install y for you
so basically I deleted the pnpm workspaces and lock and I added the workspaces here along with the packages
and no Heist now from the root okay I also have to delete all the node
modules okay yep now I'm going to do this yon that is
a shot for y install no lock file found it's going to take some time to create that log file
and uh we will be good to go and then actually we are going [Music]
to um we need to convert a few or change a few things like this is not how we add dependencies
right okay so Yan was already complaining that instead you have to just specify the version number which is
I'm going to just go with a star any version with that I mean the latest version not sure about it okay
when when I give Star what version is going to take I'm not going to worry about
that any version maybe the latest verion is good okay that's a change I have to do
now I'm going to try to install it again okay the installation is successful we also get this Yar lock
file and um everything is fine now I have to change is pnpm right I'm using pnpm for running the
scripts we can I did not I could not find a parallel for doing this we're just parall running all the scripts
named TSC throughout the mono so I'm going to use NX as a so the NX is for the monor repo it's a
build system for monor repos we're going to use the for running the scripts basically to replace this ver
also we are going to get some local and remote caching for that so I'm going to npx NX I'm going to
initialize and next in this project latest init this is going to ask a few
questions you you have to run that from the root I'm not going to enable any plugins here just bypass it so which
scripts you need to run in order I need to run the build Dev DN L okay I'm going to enable all
these things which scripts are cachable build lint TSC
fine Al so what okay I have to change the font size
okay what does the bill script create any outputs yes it creates the next build
disc lint no TC no fine so our NX is being initialized we will get NX just on
here uh would you like to like remote caching yes so that is done now we have to can
run this so this will run all the build commands this is an alternative for this okay but the NX is
much more more features like uh local remote caching as I as I me mentioned this is how you build let's
try to build it so it it builds the uh sample lib first because both our applications are
using that Library it builds a library first and then it moves to BU build the API and
web okay all three are done first it R it took 3 seconds the API was finished in 3 seconds the web took 11 seconds now
if I run the build command again it's going to get that output from the
cash fine now let's replace this with the on NX uh run Mini e build and
similarly here it has to be linked here it has to be TSC also
here forat I just change that to your pnpm from y pnpm to
yon all these things fine now I think we don't have any pnpm we have to change the rme
right and also in the Husky we have run the ywn validate fine now let's try to run the Y validate
here so this will be executed when we actually commit we will do it we will see that in a bit I'm running this
script here also you can see that we did not change the files so automatically we got
all the build build outputs from the cache and we all remember we also added the
lint and TSC to the cache as well right you can see everything is taking a few seconds here now I'm when I do the Y
valid again going to do the format from scratch it formatting took like took like one second and then all
the TSC existing outputs match the cash all the TSC and lint were taken from the
cash okay you can do it any any any number of times and you're going to get that done in 2.5 by
seconds most of the most of the 2.5 seconds were taken by the formatting I think we are good to go we
have updated the pnpm workspace into your own workspace
okay let's start building autospace so go to the Prisma schema file right now we only have the user
admin and the credential the models the models that are required for doing authentication
and we also saw the login mutation the author mutations right now I'm going to add the models that are required to
store the data basically we going to create the tables that are required for building aut of
space Okay so for the user you already have admin you're going to have two more roles so these roles are going to be
tables so basically the role base authentication goes like we will just make sure that the uid exist in one of
those tables and those tables are going to be protected not everybody can write to it that's how we do the role base
authentication and the admin is going to have an array of verification so I have the Prisma uh extension installed so
that is giving me the is suggestions that manager is neither a built-in type or nor refers to another level another
model custom type or enum we will create that okay so those are okay let's create the manager and
valy one more thing is we need to also have the customer everything is optional a user
may have a manager may have an admin may have a valy customer table relationship but the customer is going
to have the uid also we have to link back the
user have the uid as a string and that that is the uid that is a foreign key that's a primary key that
access a foreign key for this uid in the the user model right and the customer is going to
have a an array of bookings an array of reviews I'm not sure if we are going to implement the reviews this project
actually I I this I was very ambitious in the beginning of this project and um yeah I trimmed down a few
things but let's just have that I may extend it later yeah and then we also have this
autogenerated time time stamps this automatically makes sure whenever a row is inserted in this table we will create
that we will store the time in the created at the updated at updates at the time of insertion and also whenever we
update arrow in this customer model OKAY the manager we can have the display
name and we will connect back connect the user model having the uid in the field and the
reference you also have these dates have the display name and each manager is going to have one
company okay and one company is going to have a number of managers and the manager is going to
manipulate I mean update the booking right they have to check in check out they may cancel the booking based on
whatever uh based they can cancel if they want so these are the booking timeline where
the manager interfered and the valet then we have the uid we have the
user think it has to be caps okay every user needs to be have caps that is the convention I'm going
with all the joints table joints the property names we are going to be capitalized we're going to capitalize
them this has to be capital u and once we migrated once we do the database
migration we have to go back and uh modify if any of these existing ones used used to the
provider okay so the valy is going to have the user so we cannot create an item here without having the uid that
particular uid in the user table that is the constraint we are creating here we have all
dates display name have a optional image license ID which is a string with a default value of empty
string and each value is going to work for one company they're going to have this we already
saw this we already saw in the manager right the booking timeline similarly the Val is also going
to check in check out pick up the vehicle from the customer and so on so we can in the booking timeline we
can see what are the updates done by the valley and this pick up assignments return
assignments these are the assignments that the valy committed to it will make sense once we finish the
model whole model schema and let's go on to the company the company has an integer ID we
have the dates display name description and each company is going to have a number of
garages so I have to register a company first and then I can establish garages anywhere using a
map each company is going to have a number of managers and from the manager manager can work for only one company
that is the reason we going with each company is going to have a number of valet and each Val can have
can work for only one company okay so if we want to make vales work for multiple
companies that is possible also but it complicates the system further so this is this is what we are going
with Y so next one garages a garage is one physical establishment with multiple parking
slots and uh that is going to belong to one company let's start from a garage is an auto incrementing integer we have
dates display name description just like a company maybe I think we also need a image or logo for the company also I
left it but Yep this is going to belong to one company you're going to have an address
verification so initially I was yeah yeah so we have this facility actually the admin is going to verify the garage
created by the manager okay and the garage reviews this I told you that even in the customer we
have the reviews part we are going to implement that in
the back end but I don't know if we can implement we will have time to implement that particular feature in the product
but I will try so the garage is going to have multiple slots and then the address
we going to have a the ones we we always have the ID and dates this is going to be the string address string 1 2 3
nework we're going to have the lat and long longitude latitude and longit as floats and each address is going to
belong to only one garage okay why is both of them optional actually I can remove that or
can I have like this I think that's Pro okay
um I'm going to leave this and when I I am I suppose when I finish all these errors this is going to show me an error
you must make at least one thing optional because right I know in my m in in our mutation we are going to create a
garage along with address but a database won't allow but let's see see that is the address and let's create
the slot the slot is going to have this ID and dates of the display name price per
hour in floats float we have the dimensions length WID and height and the type of the slot the
slot type is going to be these are the slot types we are going to deal with car heavy bike bicycle even
we have slot types we also have this Dimension so that we are also going to have a really cool filter dialogue where
people can filter parking slots based on the dimensions and also the type user may want a really huge parking
for a car right and a slot is going to have belong to one garage and we are going to also
manage all the bookings that happened to this slot okay then comes the a big
table is booking they going to have the ID and dates price per hour so we so this price per hour we can get
that from the slot but the price may change right the owner of the slot the garage can change
the price of the slot but we have to keep track of the price the user paid this is price per hour that is the price
at the time of booking the total price if that is price per hour right so if the user books the slot for 5 and a half
hours then we will calculate the total price there is also going to have valet uh charges or pickup drop or
both then we have the booking times start time end time vehicle number phone number passcode we're going to have a
passcode generate a six-digit passcode where the manager Valley and the customer are going to agree upon based
on one booking and we have a enem called booking status theing status is going to
have let's keep the enims in the bottom going to start from booked Valley assigned for check in this happens when
an Aly when when the valley assains himself or herself ass themselves for the booking and the
Val pick up that pick up the car if the booking did not require Val then the then the state goes like
booking checked in checked out if it has Valley then booking valign for the checking Val picked up check in this is
the valley checking into the the garage facility then the um for check out somebody has to assign themselves
to take the car the the vehicle from the garage facility to the destination where the customer wanted they wanted to drop
the car or vehicle they check out this is the valley checking out the car facility and
the value returned Val returning the car or vehicle to the
customer okay when we have the slot ID and the slot let's keep them together Which
slot the booking happened the customer ID and the customer and then the value assignment
this value assignment is going to have both the pickup and drop information and again the booking timeline this is the
booking this is the booking timeline and we can actually look the timeline of the booking starting from the book The
status to whenever the status changed we're going to have a insert a row in the booking timeline table and also I'm
going to index the start time and end time because because we're going to actually look for the remaining
slots when we want to book so if there is there are th000 slots it's going to be complex right
each booking is going to have a start time and end time and we're going to have a run a query to see if to see how
many slots remaining uh between a start and end time okay that is the exact time that
the customer requires a parking parking slot so in order to do that I did some performance clicking tuning so we we
index the start time and end time so that that query is going to be
faster that query of pitching number of free slots between any number of between start time and end
time fine so that is the booking table let's create the valy assignment model I'm going to have the booking ID
as the primary key here because yeah so we're going to have only one value assment per booking that
is obvious that won't change right and then we also have these dates we are going to
have the pickup lat return lat actually pickup and um pickup location can also be null because
the user should be able to request only for the dropping request valy only for dropping and not and not pick
up okay so yeah everything is optional that means both or any one of the pickup or
lat can be populated and this thing can be further optimized
because what if we have the pickup plat long and not the pickup valy that will create inconsistency we may
actually break this down into a separate other uh table where pick a plat long pick a
validity or all mandatory right and that joint will be optional from here so yep so I'm going to keep this a
simple design next one let's create the booking timeline
we have Auto generated ID the booking timeline I don't want to have the created Created and updated it I w't
have timeline this is like a log I don't want to keep we can have the updated update at
it may help at some situations but I'm not expecting to update this
okay we have the booking here have the valy here the manager ID manager and valy can update the can
actually insert rows into the booking timeline model and we have the review
model the ID and dates rating is a number comment is a string and uh who gave the rating which garage the rating
was given two then I think this is the last one last one is verification
you can see Prisma is um showing the error the admin can give a number of Val verifications and uh garage is going to
have one to one one to one relationship with the verification and we can actually filter
based on the ver based on the verification we may want to search garages that are only
verified okay now y everything seems to happy okay yeah so we we talked about this right the garage address and uh now
any one of these has to be undefined that's how SQL tables work we cannot mandatory uh make sure that both
tables get updated at once has to be either the address or the garage no
Okay so let's make the address optional and that is the whole database model so we have the users the roles you
have the user we have a roles admin manager valy and uh customer the admin can have any any number of verification
that is only a role that is only duty I have given to the admin and um the customer can have a number of
bookings a number of reviews and and inside a booking is going to have uh it's going to point to one slot
one one one among many slots the garage is the customer and um an optional valy
assignment so one thing we can do here is we can actually have two properties here like pick up valy drop valy and
here we can make we can make the location mandatory okay and also the ID
mandatory I'm not going to change everything now yeah and the manager is going to
have own a company and update the booking timeline the value is going to be part of one company update the
booking timeline pickup assignments we're going to keep track what are the assignments the valy took for the pickup
for the return okay let's see let's uh do the migration and we will start building our
graph CLE API go into the go inside the API I have the database upon
running okay this is the database running at on output number 2010 I'm going to do the database
migration Prisma migrate Dev okay so I was playing around and uh
the migration file we have here under the in our database does not match so I'm going to reset
it delete the directory or restore the migration file I'm going to delete it and do the
migration from scratch yes in
it okay all our tables are here database is ready now we can start
working with our graph Q API okay we already have a base for our API the back end API the back end is ah
yeah I told you right if there is existing problem this is going to be
typescript is going to complain us so it is saying that for the user we have added the manager Val and customer but I
have not added it right but instead of doing this now I'm going to create all the modules that is going to have all
the code for the graph C and SD API for all the modules we just created we're going to use a code gen so
this is an article I wrote last year sjs was plus Prisma Plus typescript equals robust and Powerful graph apis in
less than a day maybe it should be API yeah so here I'm saying API fine so
you can follow this you can find this article and follow this to create a small reproducible PC we're going to
have a simple commment uh post a simple database schema with comment post user we're going to set a Prisma create the
modules and for generating I'm using this okay this is an npm package I wrote is just a code gen
package that's going automatically create the Au dto Prisma and the types and also we can optionally pass
the flag graph rest for both we have to pass the complete for both and that is going to create all the code required
for the graphical and rest API so this section is going to be going to be a bit exhausting for me at
least I will I will Fast Forward it uh so we B going to um get help we're going to follow
typescript compile compile time error and when we fix fix errors we're going to have a functioning robust
API both graphical and R away actually so yeah so I'm going to use this I'm going to create
complete let's create um a couple of scripts okay entity gql NX njs Prisma C I'm
passing the flag graph K and for the rest I'm passing the rest flag and for complete I'm passing the complete flag
okay just just like I mentioned in the documentation
okay let's copy all the model names from the schema
okay these are the model names we already have the user user module created
here we don't want credentials and nor providers and everything else we
want okay let's upend
y entity complete and we're going to create there are 13
modules and I'm going to just run it stop the studio for a while and I'm going to just paste it this is going to
create a whole lot of files inside this models yes
okay the code generation is happening and you can see the folders getting populated and you can see an insane
number of typescript Errors okay we have like 284 typescript ER it's going to be it's not going to be
cognitively demanding but physically demanding you can listen to some music but you have to do only once for a
project okay we generate you take all the model you create generate all the modules for the nextjs and you fix this
typescript errors and then this is a onetime process it's going to take an hour for
me like I'll be listening to some music and it's it's going to be a boring boring job okay and once and this
creates a really uh a tight dependency between the the database schema and the njs graph
schema so when we change database schema we going to see some errors okay okay so I'm going to show you how
to do this for like one or two two of these modules and then I will be fast forwarding basically I think I will be
copy paste this folders from the my practice project but yeah so always start from the
entity I skip the PR my schema nearby so we are working with the let's start with the admin
one okay and uh this is the admin in order to do fill this you need
to populate so right now this is complaining okay we have to look at that restrict properties so this make sure
that we passing the class here the type here and the class must have only the types that the types this is the class
okay this is the admin we are passing the class itself inside this maap so it's a a map type and it's going
to make sure that the admin class is going to have the types that we have in the admin type that this is the type we
import from the Prisma client okay so this is going to be the type of
the admin and this prisic properties mapped type will make sure that this class can only
have types from the the properties from the admin type and not anything more you can do this Implement interface okay and
since we have the nest CLI the since since we have the N graph ke plugin set up I don't have to decorate it the whole
point why I switched from pnpm to yon not monor repo is because doing
this for all these modules input typ is going to be impossible I mean it's possible but
exhausting and uh yeah yeah now typescript is happy now one draw a de rate problem with this
restrict properties is that I cannot do this even though the property can can be n
even though the NS graph CLI will understand this and make the property n in the graph C schema also I cannot do
this because of a limitation of this map type so whenever you see an optional field you have
to do it like this okay so in this case updated R is not optional we have we don't have any
optional Fields so we don't want to add that that fine so always we start with the
entity and then we will move with the move to the create admin what it takes to create an
admin only the uid others are autogenerated and verifications this thing happens once
the admin is active and uh start interacting with the system and creating verifications and in the update also are
having some error here because this works for the for other tables right for example we don't I
don't want to update the update hyphen company. input. TS because the primary key is ID and we don't have to do
anything about it but here I need to change the basically update input gets this makes everything
partial in this case it does not make sense because we only have one property but in other cases we can see that for
the company we will be having display name description and in the update dtoo we will have optional display name and
description and a mandatary primary key right fine so in the find this is going to
comprise of all the filtering and sorting pagination capabilities okay in the cursor even though we are going to
use take and ship skip for pation I also have I want to keep this graphel API really
powerful wide so I also add this cursor here I can you can see that the primary key is not ID U ID and it's uid
and the uid is not number you can also see the error here you can just follow the
typescript now it says that the number is not ass assignable for the for string
okay so you can just read the read it and can follow the typescript now it's happy let's go to the
where it is unhappy because it is lacking we are using this restrict properties map type and it is saying
that the types we have here are not available here we can do this implement the
interface and NS doeses not understand this right so we have to we also have the common
dtos I'm going to import the string filter from the common dto date time
filter from the common you can have a look at this okay this is this is inside the common this is autog generated as
well from my package from the npm package okay fine and the user relation
filter this is going to we are going to import this from the user module okay this is going to come from the users
where similarly in the admin V also I'm I'm having the admin relation filter admin relation admin list relation
filter and admin relation filter okay this is for one to one relationship this is for one to any
relationship where is happy there there are no types scri okay I have to actually fix
this so I have I'm just creating this uh Network all these things I'm importing are from the other modules I
generated you can see the errors are are reducing slowly and the final final one is order
by can implement it and here the problem is njs does not understand this so I have to recreate that because this is an
enum okay this is not object this not input type since the NS cannot understand it I have to
decorate it manually and these are coming from the mod modules I
generated already and automatically this is one to one
relationship right the user to admin is one to one one to one you can see that and this is this is forther one to
many in that case it just gets the number okay the admins
RQ is Happy other than this one error it says that here yeah I am destructuring the
I'm looking for the ID in the update admin but we updated this to U ID so I have to modify
this fine and the same in the service I'm restructuring
the I'm getting the ID I'm passing in the be condition and I'm passing [Music]
I'm collecting with the rest operator I'm colleting all the all the rest data rest
of the information from the update admin input and I'm passing that as a data okay that our graph
CLE is ready actually how the problem is the rest I miss one thing the N is already running but we we were seeing
some 275 errors right problem is we did not add all the modules here let's do it I created an
Untitled one okay I'm going to again copy all the module names and U we'll we'll just
import it or we'll just start typing it admins module customers module manages
module value module okay so I have added all the I have
imported all the modules that we generated okay now we have to 2 70 errors and 's keep going the graph part
of the admins is done let's go to the rest part go to The Entity
implement it the dto I omitting automatically I'm omitting the created it and updated it
and uh uid ID you can also do this you can do the type from the N not the graph this is API you can only pick one item
that is U ID and other dtos are happy I have to modify the primary key here also in the
update d in the controller we have to do a few things like modifying the primary key
from the ID number to the ID string U ID string same thing happens here okay I'm going to select all the
IDS that is going to there is also doing this but we will have
typescript now we also have to modify the uid number to string fine now our controller is also
ready so in this case I'm going to come back when when we are working with the graph C front and we will come back here
and we will make sure that the resolver is is protected right now anybody can create an admin okay we will we will
come and we will this is a role based authentication now this path can only be update can only be
done uh the query this is mutation and will be done by the Admin and also finding all
admins finding any one admin everything is actually authenticated and uh they can only be accessed by the Admin not
even by the manager the admin is going to represent the auto space as a compy the managers or managers of the
garages okay that I wanted to just show yeah now the admin admin's module is
ready it is showing that 256 error 257 errors let's do one more thing and I will be F
forward entity okay implement the interface the display name is optional so add
this go to the update okay create customer going to pick the uid display name the good thing is automatically
when we pick the the display name will be nullable in the create customer input du also it it
get it it just get it just gets that from the from this class all the same one same like the
admin for the rest AP entity I'm going to use the is optional from the class validator the D are happy
and let's fix the controller again the primary key is going to be ID I'm going to select all
the IDS I'm going to rename that as U ID and uid number to uid
string okay now both our admin and user modules are ready now they are stands at 230 so each thing takes like a couple of
minutes and and we have uh 11 more modules to go
okay so I went through I went through all the models and
modules and I have based on the christma schema I have updated our modules for example this is the
garage and and garage has display name and description as nullable
properties you can see the nested parting and filtering also okay and all the rest JS and rest
the API is also ready and the API is actually running I
have think I showed you I renamed the dev to Dev so I'm going to use
Apollo Explorer this one the Explorer sandbox here we can use 3,00 SL graph actually n
also comes with this graph playground but this interface is much more
better that's AI okay with this these are the queries we have these are the mutations let's try to do a cred
operation let's try to create a company okay first let's have our database open so we can make sure that
we have the user we have the data so down prma studio and it opens
here we have nothing let start with register with credentials
running everything here we also have these on I'm going to register a user called user
one email.com we don't have email verification system this project but we have
Google password is okay our registration is successful now we can go back to see the the data
the user created there the user is created also the credentials can see the password is
hashed and uh basically the user is created okay um now let's try to login with the same
credentials it gives back the token email is user 1@gmail.com
password is this is the token fine now let's look at the company resolver to see the
create company mutation I think it's going to be a bit different from it's somewh in India we I
have the AC running very hot okay so I think in the front end uh
we are going to use all these mutations and queries okay we are going to our frend is going to have it its own access
patterns the way of the way how the users users going to register as a manager create company and so on there
there's going to be a different flow but I want this API to be accessed regardless of those access patterns
fixed access but as that our front and use so that's why I'm seeing what the create company takes so the create
company is going to going to Omit created updated updated and
ID so we are going to send the display name and description you can also see the schema this is the graphql schema
created okay this 1,262 lines of code this is code first graphql all this code got generated from much more lines
of types script actually you can see let's see if I have the clock there wait a minute I will copy paste the
oops clock script so this script is going to tell us how many lines of typescript code we
have I'm going to ignore the node modules just to build lock file package of Json
generated right this is actually the generator is going to be typescript code but we are going to generate it using
graphical Cod gen yeah actually we have a whole lot of lines of codes code
actually around 5,700 lines of code okay that's a lot of
modules but everything is dependent on the types from the Prisma CL everything this is the
entity okay this is the create update dto this this is find and for the find dto the input um
argument type is going to comprise of everything right this is also implementing the Prisma slot find many
arcs okay everything is dependent upon the Prisma is it a good
thing it create some strong typing in our project in our project whenever we change the
database I script is going to complain and ask us to update our API or else the code will not
compile so yeah let's create um let's run this create company mutation I'm going to return
everything okay and one more thing the next very next section we are going to uh set up the the resol fields the
company from the company we can get like managers name okay that's the beauty of graph right that's the point but we will
do it in the next section description paring
company okay display name name par company name really bad at coming up with
okay so it's asking for a token because the company's resolver I'm ask I'm telling that only
the manager can create a company makes sense right there are two things the the the
request has to be authenticated that means we have we need to have the this token the token has to be legit
two things first we need to have this token and then and then the uid inside the token you can see the uid here
payload of the JWT okay so this is the uid we have the expir date isue
date and this person has to be in the manager but right now we don't have any
manager can see this is the ID you have in the token okay so now I have the token now
let's see what other error it's saying it is going to say that forbidden resource because the user does not have
a manager access that means user does not have a manager account so in order to bypass that going to just create an
um manager account now I can proceed wait a minute
guard this is for authenticating the user this is for authorizing user okay get
roles okay actually I did not include the we need to have the manager and
Valley we don't have uh one for the customer this is going to give back the manager and Valley this is we are using
promise all here I'm going to push the valy manager and
um admin roles into the roles and that's that's what I'm going to compare with okay now the
ru only has the manager admin let's also add the valy there fine now typescript is Happy our
API is running now this should go yep it's successful we have created
the we have created the company we can now look at that here have the manager
here [Music] yeah okay fine fine fine actually when
I'm creating the company I'm not creating the manager here okay but say told the
API so actually this should happen but I'm not going to work on this right now because we will come back when we are
working with our actual forms we will decide on the on the actions of the mutations fine maybe let's
just let's just quickly add that going to add the manager ID which is going to be a number okay that is mandatory now
you'll be getting some error the service okay so manager ID is fine
um let's D structure the values and um ins the data I'm going to give the description display name and then the
managers I'm going to connect with the U ID the uid is the
manager ID and already is a string sorry here it has to
be string because that's a uid fine let's delete this uh company let's create it again now but
this [Music] time this time we are having this error
saying we need to pass the manager ID let's pass it going to get the manager ID from here
and U pass it and it is successful
now that is the link okay fine but still as I told you the the way we are going to approach the
front end we are going to have our own access patterns and that's how we will shape the back end I wanted to show this
demo fine now we created a company company is created by the manager the next section we will be
creating all the resol fields okay everything is uh ready now we also have to worry the
garages compies yeah I also wanted to show that filtering sorting capabilities we have
one company right let's create one more company one more
company yes to we will delete all we delete these things name
to same manager okay so we have three companies now two three and four now we
can do pagination keep one take one so take two okay it skipped the first item which was
id2 and U we got these things back you can do some filtering sorting I'm going to sort by
ID oops um ID okay I have to mention y y maybe yeah so variable order bot so we need
to is this uh error message that we can send back to the front end variable s b got uh
okay maybe but we can even polish if you are using API as a service we can further polish this error messages but y
this is fine ascending when I do descending we're going to get the three and two because
four got skipped here okay 4 three that is sorting and let's also do some filtering
um and also it is nested okay I'm going to filter by manages some U IDs
okay some text this you what manager U ID right okay so manager U
ID so the manager uid has 23 that's not a problem but um I am worried why I getting only one
result okay that is because when I am passing the manager automatically if
the manager can be a part of the demo did not go as planned but still the manager can be a part of only
one company right so when basically in the create service we need to have a check to see
if the manager make it async use the
this chisma manager. find unique where uid manager ID we got the manager so if
the manager the truful going to
throw new B request exception manager is
already a part of a company is already a part of another company okay so I should have done this
right what happened is that when I started passing the manager got first I created this parking company name right
and then I created this name too and then I created this name three the manager got
switched to the newer companies that got created now if I passing same manager ID with another company I'm going to get
this error manager is already part of another company fine so I just wanted to show
you the filtering and sorting capabilities and uh yeah in the next section we will be able to create create
all those resol fields for everything okay our API is working let's create the resolve
Fields is the brisma [Music] schema for the user I should be able to
query the admin manager valy and customer so you open the user resolver
file okay let's um use the resolve field here we are going to return back
the user let's import the user uh entity going to just name it user in small case here we can uh in the
argument decorator you can use the parent argument parent argument decorator and get the okay actually we
are actually okay this is it's going to be admin we're going to return the admin
entity we have to make sure that you import it from here in the parent we are going to get
back the user here I'm going to just use the [Music]
Prisma dot admin dot find many find unique and going to return the
admin based on the uid okay where how do we get the uid from here from the parent user. U ID that's how we get the
admin now we can go here users you can fetch everything along with the admin
information okay this one there are few things which is not protected enough okay at comp time can user be user is
admin can be n right you have to mention that or else you are going to get this runtime
error you have to make this nullable true when you try that you get the user and the admin is is
null for testing I'm going to add admin for that user okay
when we fetch fetch back we are going to fetch the admin fine let's do that for the manager
Valley and uh customer three times this is the manager from the
manager entity this is also nullable change this change this okay this is
Valley let's change these two things finally this is customer fine
now when we fetch the user we can fetch all this information yeah so we created that
manager right man so this user has an admin access and the manager access and you can see
that let's go one step further um let's go to the
customers and create the user yeah not just for testing customer resolver we going to create a resolve
field called user we're going to return back user entity have to import the parent and the
resolve field from sjs graph parent is going to be customer
okay now we can do this I should have actually added this in a in an admin
or the manager because that's those guys have the user account going to turn the
user par is admin okay now from the admin I can fix the user
back I'm just playing around so we can do this so that mean we can
Fitch okay yeah so let's F forward and I'm going to create all the resol fields in the admin we already have the
user let's create the verification count and verifications this is how we mention the
return return type in Array okay array of verifications and I'm again using the Prisma the resolve Fields mostly are
going to have one database like P it could be fine if find unique based on the relationship between the
models admin is done let's do the resolve fields for address the address is going to have
only the garage okay I F forward and I created all the resolve FS
the address I have the garage and everything is going to be very similar sometimes you may want like a custom
resolve field like this verifications count like this is going to return back a number okay just a count of
verifications where the admin ID is the requester yep so everything is ready in the valley wanted to show
you pick up value return value so just I'm I had this open and based on this joins I created the resol F so we are
like building upon this database schema our graph API directly so it directly reflects the
shape of the database schema you can see plots has
bookings garage information right you don't have any slots yet but that's all about the resolve Fields
basically you just reflect what you have in the the joints in the database as as resol fields and you don't it's not
mandatory okay also you can have custom Fields like this one okay our AP is almost ready okay we
are we will actually come back to have some custom mutations and some changes if required and also we
have to secure the API not all paths are secured properly um okay so we have this API we
want to fetch data and we want to do that in a type safe way we not just fetch data both the queries and
mutations even for mutation here as you can see the variable what okay yeah so variable is typed
right here in the Explorer we want same kind of type safety in our front end we're going to use a something
called graph Cen so let's get started I'm going to create a a network library inside the
lips I'm going to create a new directory called Network so inside that I'm going to initialize a
project with iPhone y that will set all the default values this is what we
have okay in the network basically this is going to be a dep dependency okay we are not going to use this in in runtime
we not going to use the orent stuff in runtime we're going to generate the Coden in the development when we are
building the front end the codeen is like a bridge between the back end and front end so let's add Dev dependencies
first we want the graphical code gen CLI this is what we use to run the codeen and then let's have a look at the
plugins okay the first one is a named Operation so this named Operation will give back all the qu names of the
queries and mutation which are really useful for invalidating the cache we are actually
going to use next next JS fetch okay for doing static fetching ring that uses the nextjs okay also we're going to use
Apollo client for doing CLI side pitching all these things this named for example this is going to be an
example we are going to access the you can access the queries mutation in fact subscriptions whatever we have whatever
we do whatever we inputed the query names and mutation names second one is type
document node this is very powerful we Ed to have Apollo
client but now we don't have to use we can just install Apollo client and use the use Query
we can pass this type document node directly and the query the hook use Query hook or use mutation hook becomes
types typed okay so basically here get dogs they are creating a query here instead of this we
are going to we will pass a type document node here and this data will automatically be hped okay the data will
know what type we are going to get back similarly in the use mutation when we pass instead of this j
j instead of composing a query like this when we pass a type document node inside the use mutation we're going to get the
data the data is going to be typed and also use mutation typically has this variables right this is going to be
typed as well we will see in a bit so yeah those uh plugins I'm
installing then also we need that typescript operations so this generates the types
for the mutation queries subscriptions and fragments I think that is it okay so
these are the requirements I'm installing them as Dev dependency and then I'm going to create
inside a going to create a Cod gen. TS this is the script we are going to will run as I'm going to import the
config it's still installing the document pattern this is the document pattern
this is the input file document pattern going to have the plugins typescript typ operations named
operations type document node these are the plugins and uh let's create the
config first I'm going to add the overwrite is true when we change the input
file the output file is going to be overwritten I'm going to this is inside a mono repo so we can
directly access the Kima file from here okay this is the databas schema the graph schema file I'm just
going back two steps going ins the app C API SRC and directly getting the graphical schema file as a
schema I'm also going to enable the watch so whenever an input changes automatically the output
gets generated generates the key is going to be the
output file path the documents we have to mention the input file path which is we going to have an SRC here and
then SL queries. graphql okay this is going to be our
input file and when we update that we will get back a generated. TSX inside this jql file right and also I
copied all this into a separate array so that so that this looks clean so you can add more for example if you have some
seed data here and if you want to do that in a type type uh type Safeway you can generate a file into
this API folder right from the network okay you don't have to keep uh having this code gen set up into into the
applications and projects now it's almost ready Let's um test it this is the input file
okay I'm going to just copy this put it here and um we need to create a script in the package of Json in the
network I'm going to create a script all Cen I'm using the graph Cen which is a dependency and I'm targeting
the config which is this Cen do Coden dots fine now if I run the Coden something is
[Music] wrong okay so actually I forgot to export the config export default
config fine it tells that okay so it asks me to install the parcel Watcher in order to
use the watch I think let's comment this and try it again fine see now we get now we got back the
generator. TSS it's going to be a huge file it has all the types of the our graph C API and finally
you will see the register with credentials document okay now we got back
this let's quickly set up the Apollo client and we will try to do the mutation okay so I'm I'm going to keep
the upo configuration here inside the SRC I'm going to have a config directory apollo.
TSX okay because we are also going to have export the Apollo Provider from here let's install the Appo
client this is not a Dev dependency because we will be using it directly in uh at run time
[Music] okay I'm importing Apollo client HTTP Link in memory cache let keep it
simple this is the interface for the provider because we are going to get the children we need to
wrap the children right say that I'm going to create the uplo client
okay so we need to create the HTTP link okay so we need to this is going to be uh environment variable the API URL
which is going to be as Local Host 3000 Here Local Host 3000g graph and uh we can directly pass it
here we can enable in memory cache one problem with the yarn workspaces is that here the network
Library I don't have react installed right as a peer dependency but still I can use this
because the the root node modules has react okay the react the root node module has react
so it's not complaining when when we build and push also I'm not seeing any problems but I'm going to add this as a
peer dependency save Pier um okay I think the save Pi did not
work okay I'm sorry I have to this is hyph I Pier to save the perer dependency the network now we have react
in the PE dependency and uh I think we can remove that from the dependency fine
now let's add react as appear here yeah okay we are we have we are actually
building Theo provider we have created Theo client withtv
link and I'm just exporting the provider by passing the Appo client as a client this provider is Appo
provider fine now we can simply wrap this provider um wrap the application with
this provider and uh inside that we can just install Apollo client as a dependency in our application and we can
use this typed note type node typed document node inside that and we can TCH that and
before that we have to set up some TS config stuff here you we are using jsx but um it does
not see TS config to help that so let's create a TS config [Music]
Jon so first I'm going to extend the DS config that is in the root here we have basic this is what we
want to use the you know throughout the monor repo I'm extending everything then I'm
going to have my compiler options going to have the out directory and the root directory and I'm also
going to specify jsx as react jsx okay now be
happy yeah I think that ER went away okay now let's rename this is called network but I'm going to rename this
autospace SL Network and uh we need to add this as a dependency in our web I'm going to go to the package of Json and
similarly I'm going to do that to the network add the network and in the
web I'm going to do the ywn to install the dependency fine now in the layout
file SRC layout wow all these empty folders in the layout file I'm going to
import autospace Network SL src's config Apollo I'm going to import the Apollo provider and I'm going to wrap the
body fine okay so create the environment varable next public API it's Local Host
3,000 that's what we are using in the Apollo config so yeah we have created the type
document node we have created the PO provider and wrapped this now let's switch some let's do the
mutation as I told you I did not install this Apollo client as a dependency in the web application but still it is
letting me use that import stuff from that dependency that I don't
like create mutation document yeah register with credential
document that it let's try to use that going to just show you the safety we get okay I'm passing it I'm not getting any
types types of variable types of WR type but look at this we can okay this is an array and u
we can get the data and loading stage from here and the data is typed so this is a return type
remember this is exactly what we got here updated at uid name image and so on okay that's not it the
variables are also typed okay register with credentials input
that's exactly the variable name and inside that also we get what value to pass and which which field is
optional okay even the optional field is not showing here but the graphical Cod gen allows us to do
this okay so instead of I I chose to um show you the mutation example here because I wanted to show
how the variables are are type safe as well along with the return type let's also
have a query like this companies I'm going to just paste it here and the network is not running okay
sorry for actually it was as asking asking me to
um install The Watcher now we have the company's document right now we go here we have to
use the use Query and here company's document and let's use the use Query with the company's document it
um okay actually a query also has all these uh variables okay yeah order B skip take
where I I think something is missing the resolver D find
where Okay okay so that is because uh those are the four things I picked here
right let's create another let's return everything and I'm going to select all
these things all the variables yeah I think I did
it fine this is the quy going to replace that right let's run the Cod again
now in the page this is not an array the return return type is just going to be an
object with a lot of things here including the data loading and so on the variables
now the we and so on okay here also you can do this nested filtering whatever we saw here is
possible in the front end also now in the the fetching the component I'm going
to just Loop through the companies company. name display name also you have to specify the
key Company ID fine let's run the
application the application is inside the API app SL web y Deb
3001 since we are using hooks here I have to men mention this as a client component yeah that's not the problem
here use client yeah okay so in the layout I'm using this P
provider so I have to also mention this as use client now now the error is gone now we can see three companies here
parking company parking name one name two let me quickly had some style there okay so these are the three uh
names and we got that fully in a typ safe way
okay yeah so in the in the upcoming section I will be setting up the Au options for the next
Au and we will do authenticated queries okay so our back end is almost ready and in the we have built the
bridge which is the graphical Cod genen which lets us query data in a type Safe
Way okay in this section we going to proceed to build uh the next o we're going to set up authentication and also
we will be making authenticated queries and mutations through uh po let's press
proceed let's create the API routes for authentication API SL SL going
to this is going to be a catch all this is going to catch all request datas that's going to be like Local Host like
the URL / a// anything first we need to install the
next o in our web then we need to create the Handler going to use the next to we have
to pass the a options here that we will uh create inside our next inside our network
library and then I'm going to export the Handler as get and Handler as post and now let's go to the network
library and we will create this Au options inside the config I'm going to create
this all options TS okay so this is the skeleton
basically we are going to use the next to options let's import that from next
to so we're going to use two types two types of providers Google provider and credentials provider
and I have set up that we have to create the Google client ID and secret ID you can create account in uh a project in
Firebase and uh even Google console I'll show you create a new account new project in
your Google Cloud console uh go to API and services click on the credentials and U you can find
the client ID here and the client secret here also you have to have to add the origins these are the
frontend URLs and the authorized redirect URLs they are going to be like PR ur/ API sl/
callback SLG gooogle yeah you have to do it get these two IDs
to the client ID and the client secret the environment variables as Google client Google client Secret
and then I'm also configuring the email password authentication so basically the next Au
does not know about the backend right so we have set up these providers Google provider and we can login using Google
and or using um client but actually we have to manage this client provider right we have
to make sure that the email password is there in our database all this all this stuff
that's what we doing here inside the authoriz we get the credentials here and I'm going to there are no credentials
I'm going to just return null so that won't pass I'm going to destructure the email and password and if the email and
password email is string okay um maybe I don't need this we can throw this
here return okay don't we don't need that check let have a trke catch
block so here we are going to actually call our login
document so let's make sure that your network Cod is running and in the okay so um I have to enable
the watch through so that I don't want to keep doing this again and again and I
need to install the watch parcel Watcher okay let's install that I said Dev
dependency the C is asking me to do that in order to use this um watch through feature
fine okay now it's watching in our graphql queries or graphql this is this is our input input file right when we
post a query here we will get back the type document node here so I'm going to get the
login document Apollo Explorer 3000 SL graphql or let copy the mutation for
login this is going to give back the token now in the generat we will see the uh login
document now let's go back to the O options we have to import that from the generator in order to do this uh
mutation I'm going to create a few PCH functions inside the network library I'm going to create
pitch index.ts we're going to basically extend the nextjs fetch to help us accept a
type document node so simply what Apollo is doing here the use Query I'm not passing
any generics okay the the return type the variable type nothing this contains
everything so we're going to create a fetch function is going to just get this uh type document node and it will infer
the variable type and return return type okay let's Implement that the fetch this is going to be the fetch um
return type going to get a uh generic that is going to be return type and the error is going to be stram
string this is going to be the type it's going to contain either both the data and error or optional and data type is
going to be passed through the generate but the consumer of this function don't have to do this don't have to pass the
types so this is the argument type for the fedge function this is the return return type
this is the variable type can we also have to import the type document node from
okay I don't remember installing that I think this will do us okay this should do so this is the document we are
going to get which is this okay the type of this is document node okay which is the query
and uh all the variables that is a document type and the variable is going to V and also we
are going to get the other config where the next JS switch function gets like um yeah extending it so I'm also getting
this configuration and also the token this is going to be for the authentication I have some documentation
here so that when we hover over the function we will get some information about what the function gets what what
it returns how do you use that this is going to be this is an async function it's going to return return a promise of
the fetch result which is this we passing the data we going to get the query from the
document print okay so print has to come from the graph Q itself and I'm going to return function
we're going to first give the AP SL you we already have this in the environment variable the URL /
graphql inside that I'm going to we're going to actually do a graph CU query or mutation right the method is going to be
post and the [Music] header first I'm going to have the
content type as application [Music] Json and I'm going to optionally use the
token so if the token is real this is going to be the JW token we created
we get back from when we log in right if the token is real we are going to we are going to spread this object that will
basically make the header that's that will just insert this property in the header or else it will spread the null
which is nothing right so this is how we optionally add this property in the header and let's add the body you're
going to do the just on sty I'm passing the query and the variables Also let's spread all the all
other configurations that we just saw right that next CH switch function usually
gets fine so next I'm going to get the response here get the
to make this yes sync we get the data and errors here and if there are errors I'm going to just
console L it and return the error so remember the the return message the return type is going to be either the T
data of data or error as string so that's what we are here we are returning the error with the
string or else we can just return the data okay this is the implementation what happens is we get the document when
we consumer when we use this function we don't actually use we we don't have to pass these types as T data and variable
T data and variable are going to be received so when we pass a document here the function knows the T data and
variable and we will use it the variable will be the the function knows the type of the
variable the function knows the type of type of the return return type this is the gra graph let's use it in
our options okay so inside that I'm going to call
this wait PCH graphql from the fetch inside the we are inside the network library
so and then we have to pass a document which is login document also we need to pass the
variables also you see that right everything is typed I'm not I'm not letting the function know the type of
the variables and return return type but still everything is clear here also we get the data and error
which both can be optional and when you look at the look into the data you get the login. token that is written type of
the login mutation Okay so if error dot if error is not null is
we're going to just throw an error here or else I'm going to return the
ID okay what okay I have to destructure that
data oops okay h fine so um actually I we have to add quickly add
the user information in the login Also let's go to the user service here we get this user right I am
going to add that here and also I have to mention that in the return type here
along with the token I'm going to also add the user now the user service is
happy now we have to restart it because this is not the code is not listening to the changes in the back end changes in
the API it will it will look for the input file the graphical queries and mutations but not the actual API I
restarted it now inside the login we get back oh what okay so user resol I have to also
I have added this where does it come from fine that is
fine API is running yeah we can we can get the UI we can get the user and everything
[Music] here we should be able to get the user information W okay I found it that is
I'm not getting getting the user here okay the query does not specify the user and hence I
was we need the image name also the email okay uid name image email it is saying that email is not
that's not it's not there in the user resolver so I'm going to create a resolve field
here that is going to get the email okay actually the email can be um
received from the credential itself right so because we use that email to login so this is going to be that email
is going to be is going to belong to the user we get back from the
data here is data. login do user uid same thing image
okay so I have to add the image here fine so this is the login mutation we're going to get the token we're going
to get the uid name and image everything is happy if there is an error I'm going to
just return null that is how we authorize when the user enters the credentials email and password that's
how we this is how we we manage it um we also have to return the name
okay we still have this error okay so these things cannot be null
probably so let's make sure if there is not no data. login. token or
error now we can remove this and uh typt is happy you know and that's how we handle the
authorization that is login using the credentials provider we still have a few things to
do I have enabled the debug so that we we will get more log in the development mode I think and
I have enabled the JW strategy we also have to pass the max age I'm going to keep the max age here but later we
wanton actually use this in other place as well so we will be having a U library and we will have the this constant
there then let's work on encoding and decoding the JWT token this is going to give us the token
and the secret if there is no token going return the token is undefined
error or else I'm going to get the sub this is going to be the ID the U ID and all the token
props so in order to work with the jwd we also need the Json web token let's import let's install that install that
in the network and we can import the JWT like this I think it we also need to install
the types type definitions for this uh add this as a Dev
dependency and now we get the JW we can work on the encoding and decoding let's get the current
time let's calculate the expiration time this is the issued at this is expired at times okay I'm going to sign a JW token
we're going to just pass the uid all the token props If U you pass anything else and the expiration time
stamp yeah this secret we get in the en code right actually we do we have to store a
environment variable there going to call basically open your EnV for the
front end and just have next _ secret you can pass any Secret I'm just having this
locally so I have a weak password weak secret there but you can have other harder ones we will use the same
Secret in our API so that we can decode the jwd
there okay now we have the token we can just return it fine that is the encoding logic let's
do the decoding the decoding is okay the difference is this token is
data okay this is an object this is an object this for the decoding this is a
string okay this object is going to have the ID and other token props that we used to create and return
the token decoding is opposite we get the token the JT string the same secret and we have
to decode and return the object the payload of the token let's do the C TR
catch okay here I'm going to decod the verify this is the algorithm we are
using HS 256 and we are passing the token and the secret we decode the token this decoded token is going to have an
object it's going to have the uid and issu a date expired date and so on yeah so we also have to import the JW
team can put the JWT from there next start Hy JWT uh okay maybe import store as okay
fine that's how we oh okay so if if it's an error I'm going to just return We to throw an
error return null fine now the encoding and decoding is done now one more thing is remaining
that is two more things okay the call backs this sign in will be called for both the credential provider out Google
provider or any other Pro what providers we use in the application but when the user first logs in signs in using Google
we have to create an account for that user in our database right so inside
that I'm going to check that account provider is Google so we don't have to do anything when the user logs in with a
email password because the user users themselves created account registered themselves
into a database when they registered but that won't happen in the Google Google sign in so we have to when the
user signs in for the first time we need to create okay so for that how to make sure
that the user is there already in your database I'm going to create a new route for
that in the user resolver I'm going to create a query it's going to say going to be get
all provider we're going to basically get the O provider data which only contains the uid and the
type of the AR provider okay which is Google art credentials that's all I'm just creating that and we need
to create that U object because we did not create a module for o provider so let's create the O
provider in the user entity all providers going to have the U and the type yeah
that's it so um this is required for confirming if the user already has the account or
not so um let's create the query in our
Coden okay get Au provider we are returning the uid and the type now we can use that here
so if the provider is Google we we are D structuring the ID name and image and I'm using the same graph F
graphql to do this query and also we can import this from the generated DSX I'm passing the
variable as side from using the ID if there is no
user there is no account there we going to create create a new user if there are no existing user then
we will actually we have to create this get register with provider document
also IM mutation and schema doq queries.
graphql past this we will get back the register with provider doent from the generated
file also we can get the so this generat is going to have a lot of things like everything that we need in the that we
have in our back end in our API including the wear type everything okay so we can
get the types into our front end from this generated code and so finally we have to return
true basically in the call back sign in call back we uh made sure that the provider is Google and if there is no
account we are creating the account and ins say the session if the token is
valid we have to add the data from the token into our session so here I manipulating the
session object and passing the image from token picture passing the uid as token. uid email as token. email name
and as token. name after we setting after we set everything we're going to return the
token the token is null then it is null in the session also to satisfy this for example you can
just click through and see the type the default session as name email and image but I want to have the uid in the
session information so that I can get the uid in the front end so in order to do that I'm going to have a type
definition that will add uid to this okay so in the S RC the root I'm going to create a next
hyphen O.T D.S there I'm going to import the default user which is
this okay I'm importing that and then I'm I'm inside the next module the session
interface I'm modifying the user object actually use the default user but without the ID and I'm adding the U ID
there okay now when you have this type definition in the root of the network
you won't have the error here now this error is gone now session is unhappy for some
reason promise I have to return the session sorry fine so that is
it I'm also going to have another function called get Au so basically this is an au options and this get server
session comes from the next to O package okay you can in your in the server components you can use this this
an asynchronous function you can use this to get the Au object that is going to have the uid image email name but I I
don't want to pass around the all options this is simpler this shorter than this right so I created this helper
function that's all about the Au options now we get back to the API route and we will finish this now we can
import the options from um the Network slash SRC config Au
options fine that's it now we I'm also going to create a token route which is going to
going to get the types next next request next response get the cookies I'm going to set up a get
route and inside that I'm going to get the cookies the session cookie the session
cookie is going to be saved in this name okay next hyph do session hyph token we get the we get that and we're
going to return that in the response so we have two routes inside the API one is this is going to be this
is a collect all route this is going to collect get all the routes that ends with API sl/ anything we have a Google
SL callback also right so everything comes here goes into the Au options and it gets worked also we have uh the
token route which is which basically when called it is going to just return the string the uid the the JWT token of
the loged in user if the user is logged in or else it's going to just return the empty
string so we have set up the Au routes and uh before proceeding to proceeding to create the Au Pages like
register login we need to create the UI Library so inside the lips we're going to basically create a UI it's a nextjs
project so typ previously in the previous Foundation those I was using wi wh had facilities
to actually convert that into a publishable library but this time I'm going to keep it simple I'm going to
just create a next JS project as for the UI Library so um yeah when I was trying to
commit the code I got this error it says that the uid does not exist in the type the default user right we have the type
definition here now we have to use that we have to import that inside our application also
here I'm going to use create a types. d. TS and I'm going to import that fine now we can also
individually run the validate script before trying to commit and since we are using NX a lot
of things are already cached well so we don't it takes very less time
fine that I wanted to to save now let's proceed to create our uh UI
library inside the lips I'm going to create yarn create next hyphen app name is going to be
UI and typescript Es I'm going to enable Ty typescript es Del window SRC app router and no inputs
and inside the UI the TS config I'm going to delete the path paths I don't want that because that will create
problems when I try to import some component from here various problems these internal
paths and we have to set up the Tailwind basically what we going to
do is we are going to set up the Tailwind here and we are going to delete this global.
CSS okay right now we don't have anything there but we will have more some some
styles that are um that are about the toast map and so on so I want to have one CSS file and that CSS file is going
to exist inside the UI library and we are going to have multiple UI multiple applications and everything is going to
use that CSS file instead of copy pasting everything inside the these separate Global CSS I'm going to delete
this and let's rename the package name here to at autospace slui okay and in the pack in the web I'm
going to add that as a dependency okay so we have to install that inside
the web run Yan right now in the layout of the
web we already deleted the global. CSS so we I'm going to get that from autospace slui SL RC
slash SRC slash yeah global. CSS okay fine now we have to configure the Tailwind config Tailwind configuration
also we have to set up the theme primary color and so on so I have
um I'm to create inside Sr I'm going to create a styles styles I said Styles but I typed
it wrong config.js I'm going to copy paste all the configurations we're going to have the
brand we are going to use H hsl Hue saturation light lightness here okay this is easy to even
uh see and understand the color this is going to be in yellow okay zero is going to start with
red it becomes orange yellow green and so on it is between zero and U 359 is the saturation this is a
lightness so it starts bright and becomes dark okay this the primary palette we have the gray palette we have
the yellow palette which is uh we don't want that we have the green red we have the
animations for spinning spin ders wiggle slide we yeah all these things you can use also we have to create the key
frames for those animations this car park this just a funny thing we will see a brand icon
starts at zero it starts somewhere and then it goes parks and then it it returns we don't need yellow because the
primary color is yellow right that's that is the configuration now inside the Tailwind
config file I'm going to import the config that is going to have the color
configurations spacing configuration animation configuration and key frames configuration I will enable the
important to true I want Tailwind CSS classes to be the most important ones content and then the theme we don't want
any plugins and then the theme I'm going to just use all the configurations I mentioned earlier I
created earlier right also have some rink color to be primary outline color radius by default so I'm going with
a serious look with we are not going to have any B radius anywhere we're not going to have rounded Corners okay just
to mimic a parking slot parking slot won't have rounded Corners right I think I I haven't seen
so that's the style we're going with this is the spacing configuration also remember we are
extending it okay the color configuration we are overwriting it ta is not going to have any other
colors okay the blue ones normally ta will have if you put it inside it will have
all those colors and it will override only the colors we mention here and go either way but I'm going to
just be strict about my colors about the colors we can use in this application that is the TA configuration
now go to the web tailin web and I'm going to extend the tailin configuration from the UI okay as
a preset we don't want any themes or plugins here I want one source of Truth
since it's a mon I'm just going out into the libs UI and I'm just ping that trailin configuration as a preset for
this web also you have to be mindful about the content I have to have all the TS TSX inside this the
front application and also every TS and TSX inside the UI because we are this application is going to have some pages
Pages need Styles this application is also going to have some components inside the UI Library both needs to be
styled that's it now let's let's look at the Styles I'm going to give a BG primary
for the entire Main and um I have stopped all the servers I'm going
to turn that on now when you open 3001 you should see the primary color
which is yellow but and resolve okay the
web UI okay SRC app let has to be inside the app SL
global. yes fine now it should work yep fine now also we have I did in the global. CSS I'm going to delete all
these dark mode stuff it's good also let's um remove that
background Gray from here so that this is the primary color so basically we created a simple UI Library we
configured the Tailwind we extended the Tailwind not just the Tailwind configuration but also the whole global.
CSS file into the application this is what we going to do for other other application also we're going
to create create web hyphone manager web hyph valy web hyph admin everything every application is going to carry the
Styles the same primary color the same no border radius every configuration
that is the uh that's so we have just set up the library we will create some basic
components and we will create short create our uh register and login pages okay so in the section we will
create a few UI components like um HTML input label Button Brand icon a few things and uh we will create the login
and register pages also we will we set up a form library that will have zard react hook
form inside that we will have our schemas and so on first let's start to start
creating um the components I am going to follow the atomic uh Atomic design which is
which divides the components into templates organisms molecules and atoms inside the SRC components I'm going to
create atoms molecules fine first let's create the brand
icon simply it's it takes some Child by default it's going to be 100 with a shadow this is the car okay and we have
animated car park park car okay so this is the park car anime config it's going to take 5 Seconds easy
and infinite it's going to be looping this park car is going to be inside the key frame which have it starts from
translate x150 and U below basically we have some key frames
we just rotate and we park the car and we go get that out this is the uh the parking slot we have
the Border yellow 500 we have some width and height everything is inside is going to be Flex
box also I am hiding everything overflow hidden using the Overflow hidden so that we won't see the car won't go outside of
the paring slot now I'm going to let's just look at that in the page I'm going to import that
component / SRC components atoms and icon let's have a brand icon here okay so I have a practice of
actually stopping the servers before committing the code I do it
impulsively don't have reasons why I do that okay let's remove the brand color here so that we can
see okay this is our icon what happened to the color color of
the parking slot border yellow 500 it's not working why fine fine so we actually I deleted
the Border yellow instead we have to use the Border primary okay now you will see this N Style of
logo along with the car and if we take that overflow hidden the car goes like that which we
don't want it it breaks the illusion okay when we have it back it looks like this okay let's create more components
and we will be creating our forms the next one is the button so we need to install a few
things we are using a Tabler icons react in the previous um videos I was using Lucid react I loved it but this time we
will use this Tabler icons okay this also has a really good variety of icons
so the button goes like we have the button sizes also the
variance next outlined contained these are the variance and uh ins say that we can mention
the Yeah so basically we have to mention the variant and the color and I'm just using the basic
button passing the type the type is button by default okay when we we have to specify
submit specifically when we want submit buttons we have some Styles we have the re we
have the loader there let's check this button first I'm not going to do this for every
component but uh I wanted to see something here button is there
yeah this is the button let's have something inside it hello this is the button also you can
pass the loading to true it is loading okay this is what I want to see okay that button does not look good it was
like going back let's change that animate spin but if you do that the
but the arrow is wrong refresh reload this is refresh this is
reload rotate clockwise okay we can use reload or rotate
clockwise I'm going to use rotate clockwise icon rotate clock wise what is clockwise
two okay this is clockwise two fine and now the button uh not bad I'm going to go with
this so a few more components I'm going to f forward form form error input and
label this form we just extend the form we have some Styles uh Flex Flex box we have some Gap to between the items
and um some ring color and text small I'm also forwarding the ref here so that we can assign for assign some ref into
the form similarly the form error is just a div the is there we going to have this is some opinion thing okay we are
going to have some exclamation mark followed by this the a string it's going to have some color
red input again we we we use we extend same thing with some opinionator Styles here same goes for the label also but
here I'm also getting the title I I'm destructuring the title and I'm rendering that and I'm also we also have
the optional field let's have a look at okay we will be building the forms we will see this optional in in action also
I'm having this form error right the label gets the error string I am extending this here okay I'm
extending the HTML label element property with the error and optional properties
that that if the error is there we are going to render the form error and inside the molecule I'm going
to have a simple o layout later we will we are going to have a 3D scene in our H layout right now we are this is what
came up with it's a grid layout we're going to have the brand color here some children and the back to home page you
can further simplify this but as I told you we are going to have some 3D uh 3js stuff inside this path layer
that's how that's why it looks some complicated okay we're going to just create wrap the
login form and register from inside the sou l so it will look good that's we don't have any organiz
right now we can start to work with our login form and register form but before that we need to create the forms Library
I'm going to just um create a forms directory go inside it initialize a project um rename the
project to what autospace SL forms and I'm going to install start react hook
form and at hook for/ resolvers I think so I'll make [Music]
sure hook for/ resolv react hook form Z okay these are the three dependencies which we
want and I'm going to create a SRC inside it going to have a schemas
file Let's uh build our schema first we need import the zard first let's create the form
schema register this is going to be a z. object and inside that I'm going to have
the name image both are optional both are string both are optional and the
email see you don't you don't need that reject rigex to validate the email you can use uh s to validate the
and password you can have complicated password rules but I'm going I'm simplifying the I'm just going with a
condition that the password should have at least six characters now I'm going to create the
form schema login a Twist is that I we can extend that dot pick I'm not going to create any
duplicate stuff it's just email true and password true how cool is that these are the two
schemas and let's create them form management hooks login. TSX I'm going to import the use
form Z form schema login from the schemas now we can infer the type of this okay using the z.
infer that's a plain type that you can use something like uh this um I do this it knows the data
there okay so that's uh helpful in many spaces many places and let's create the use form this is the form management
hook use form we have to pass the type here and then here I have to pass the
resolver is going to be zard resolver have to import that from the hook form at hook form resolver
SL resolver using the Zar resolver we have to pass the schema
there fine can also have some default values so on so this is the use form login similarly
I will create the register one is going to be very similar okay we inferring the type we are
exporting the use form register we using the use form we are passing the the inferred type as a
generic you know when if you compare this with our uh PCH
graph here this document contains the both variable and the
every type right the return type the variable type every type this one type document type node contains everything
I'm not passing the types here right but the problem is here I'm passing the schema actually you can infer the type
from the schema right so if I'm not passing this this thing won't work when you start using that hook that thing
won't work so I just wanted to say that the Fitch function we
created is efficient right I mean U at least in the type safety way right now we have the schemas we
have the hook forms we have basic ingredients for the
form inside the templates I'm going to create the login form. TSX F this is the interface it's going
get the class name I'm going to use the inside this let's
um let's import the use form login a space so um we have to install that in
the UI all the at outut of space SL forms also you have to Reg you have to in do y
install okay now you can install you can import the Lo use login use form login this is the form management
hook I don't have to pass anything we we can we get the register we get the set value set error set Focus everything
like it's it's a very powerful Library it saves a lot of time and
energy okay let's uh get the form from the atom I'm going to have the HTML label inside that HTML
input now you can register this register knows what properties we have for this schema
email and password Also let's have the button from the atoms
submit and I as I told you the type is type has to be submit because it is button by default
and in the on submit here we have to use the handle submit here the handle submitting a call back gives the data
let's just look at the data and this part won't uh be satisfied if the if the form
contains some error errors so that we can get from the form States errors I'm going to console log that as
well errors errors this is the login
form Let's uh create a new page in the web application in the app directory I'm
going to create a login SL page. TSX Let's uh import the login form
template and we will just export it this is a page in the page I'm going just going to
return the login form and the login form so this has to be be a client
component again this is the form we have to add some we can add some placeholders so right now we don't have
any errors but when I click it you will see the errors it says that invalid email string must at least contain six
characters for the password remember I have we can pass the error here going to be errors. email. message similarly
here also I'm going to have the errors. password dot so that is a setup which we had
okay the we if we pass error we will render the error below the box like this this is the exclamation mark follow by
the error message and also I wanted to see the optional thing
worked the password is not optional but you can specify that okay also you can you have to specify
the title email there is
password Al I have quickly have some placeholder yeah so when you start typing oops the type is type has to be
password here so when you start typing here when it reaches six characters the error
error goes away right all these functionality we get
for very less amount of effort and also when I when I type something something here until it becomes an email it keeps
complaining okay it's a really good user experience that's how we build up a form let's um
just [Music] uh I'm going to add a few more things
here that's it I'm going to have a text here saying if you already have the account you can go to SL
register okay sorry if you don't have an account go to SL register to create a new
account that's pretty much it now how to actually sign in so we can get the sign in from the next Au react and you get
this data and this part make sure that the data is going to have email and
password you get that both we just call that okay here we can call the sign out we need to
Avid that sign in from the next op you can pass okay this is going to be a type of
credentials you can also do the Google signin which we will do this is credentials and then I can pass
the email and uh password I'm also going to set the redirect to false because we are going
to manage the redirect ourselves so if result Dot okay I'm going to use the use router use router from the next
navigation not the next router here I'm going to replace okay you can push but
replace make sure that you cannot go back once you log once you log in we
will redirect you redirect the user to the homepage if the result has error I'm
going to actually we are going to create a toast component from Rea defy I think before that let's just use the alert for
now the error is there I'm going to alert saying login failed try again that is the login
form since we already have a login going to try to log in okay so also in the login page I forgot
to wrap this with the O layout o layout is inside the molecules we have the O layout
and right now the yeah so it it it makes the page look a bit
cleaner okay so it needs a title the title is going to be log in here okay this is the
page this is the page okay we're going to have some 3D scenes side by side also you can see the your
brand you need a space there create one can have a space
here fine looks good now we don't have the register page yet but let's try to log
in okay user one at gmail.com okay cool the the login is successful
and we are redirected to the homepage now you can go to the application you can look at the
cookies session token and this should have the information about the session the loged
in user the U idid name email and so on okay let's also create the register page um this that's going to be very similar
to what we did here but uh yeah we going to actually do the mutation register mutation into our database and after the
mutation successful we will do the same thing here we will sign in using the next do so that it manages our cookie
here that's what we will send when we hit our back end let's create our uh register register
form so I'm just going to copy paste it and we will go from
there okay so before that we need to create the mutation right so in the user resol we have this register with
credentials this is the mutation we need to hit let's get that
type mutation register with credentials I'm going to get back we don't want much data there that is sufficient open our
queries. graphql paste it let's make sure that network is running it's not running let's run
that I think we already have this no yeah
credentials okay yeah so already we already have this so y we don't want this we don't want to create it
again let's create the register form. TSX so we are actually using the type
here right the common types um we need to create okay let's let's do that let's not keep pushing it
I'm going to create inside the libs I'm going to create a util Library go inside that initialize
it and let's create a types file inside it also have to rename it and I'm going to just create a types.
TS and U keep it here now we can use that here
also the register form I'm going to import that from that autospace /sr /
types so we need to install this in the UI Library
util let's also install dependencies similar to what we did earlier I'm using the use form
register from the forms Library use form register and I'm going to use get the
use mutation from the follow query client use
mutation so this use mutation works exactly like uh how pitch graph C
Works register with we need to in import that register
with Cals document this use mutation is going to give back an
array it's going to give a uh an mutate function registered with credentials and then it gives the loading data reset
everything I'm going to copy paste the form this going to be very similar to we did what we did
earlier form onsubmit I'm getting the form data I'm using the what is the
problem name is in compet okay okay Stringer undefined okay so our graph K API has a
problem register with credentials the input okay the name has to be optional
okay instead of this duplication is the problem if you look at the user object you know that the image and name
are optional right but since I recreated it we ended up having this problem so I'm going to
extend this re um this input D extend pck type I'm going to use a pck type from the graph
qu there I'm going to pass the user from The Entity and we have we can pick the types
which are user does not have the email and password so we need to pick the name and
image from The Entity and we will get the we will just add the email and password Here
below okay also you have to specify this as an input type yeah this is
credentials input let's rest okay the API is running let's rerun the code
gen let's go to the user register form now this part is happy now basically what happens is we
are doing the registration if there are some errors I'm just doing some alert with the errors if the data is if the
registration is successful and doing an alert and also I'm signing it using the next
O next St slash react I
fine and I'm including the call bag as homepage here but you can also do this
like result result. okay or something right this will also work let import the HTML
label input and the button and Link this the register
form um let's uh just duplicate the login I'm going to replace with the register rename the to register and we
will convert this into register form let's also rename
this fine so now how to sign out in the homepage I'm going to have
have remember we created that get o function this is a client function okay okay so if it's a client component we
can directly get the use session okay so use session is going to
have going to have the data status and update s
data so if the session data is there all these things we will just throw it away okay we we will be having a now bar in
in the next section but still we are just going through we're just looking
U how stuff works if the uid is there I'm going to this also gives us a sign out
function okay I'm going to just use a button here saying sign
out on click let's just call it we don't have to do anything or else I'm going to maybe
render the user information there session data. user. uid oh provider
okay it so in the layout let's import the session Provider from the next art I think it
won't work because it's we cannot directly import this session provider into a server component so I'm
just tring it we context available in So yeah so we have to export this session Provider
from inside a client component and uh things will work okay so inside the
molecule we going to create a session provider. DSX basically I marked this as a client
component I'm importing the session provider react node I'm basically re exporting it okay that gets some
children so instead of uh this let's import the session Provider from our UI Library SRC M component
molecules provider fine now it should work okay so I'm signed in I'm this is showing we are getting the sign out
button got it actually this has to be a link because user won't be logged in so we
won't have the uid there so login is going to have the hrf of um SL login I'm not logged in but why I'm not
logged in let's log in again okay now I'm seeing this out
button and look at the session cookies when I sign out the session will go oh actually I'm
sorry we need one more environment varable actually that tells the application
URL so open your environment variable create an environment variable called Next _ URL with the URL of the
application okay I have set set that up now we won't get this problem I'm not logged in now
login automatically we go to this 3001 okay based on the next Au URL it has to be named this way okay you cannot
change that you can change but I think when you don't change you don't have to do any
configurations okay oh when I give some wrong password
you're going to get this alert upcoming sections I will be creating I will be setting up
the react toasttify re actify okay that will look a bit better
than the alert okay so let's try try our register
page again register form has to be a client component and let's do some register Let's do
let's register user two same password user two register so we are showing the alert
now when I close the alert it read it signs in after I close the alert it signs in with next to and it goes back
to the homepage you can see the session here now you can do let's add one more thing we already have
we are doing a query right let's do um but this query when you look at the config we don't have any authentication
going on we are not adding any beer tokens headers Au tokens Au headers authorization headers right let's add
that let's add that and then we will make this get company say so right now the company
resolver this this is what we are doing so when I add allo authenticated okay only authenticated
people can access now I refresh look at the network tab you can see no token provided okay you cannot access the data
now now I'm going to update the Apollo client I'm going to create a Au link about link
for that we you need the set context from the Apollo link context I'm going to create the after
the HTTP link I'm going to create the o link that is going to give us the headers I'm going to use the PCH so
remember we have a token route okay the API this will be basically return back
the JWT if the user is logged in when we are hitting this this is hit from the client compound right we this is inside
the Appollo hitting it we getting the token back and I'm going to return an updated
header okay I'm getting the headers I'm splitting everything inside and I'm passing the authorization header based
on the availability of the token let's do something if the token is there I don't
want to send an empty authorization header or else
null oops y okay if the token is valid we will destructure this so we will end up
having this header okay auor header or else we will destructure null and we will get
nothing okay that's the link now we have to concat that maybe I think a better syntax would
be this right but we have to concat link. contat and we have to pass the HTTP link inside
it Al so we need the comma fine that's how we add the header in our header Quest now when you go
back here I'm not logged in and I'm hitting this error right let's log
in user two I have logged in now still the data is not there invalid
signature what as on web to ER I think it has something to do with
authentic authorization let's just rever back to this and refresh not toen
provided okay so this invalid signature error happens because I did not add the uh the
secret secret to ecode and so we get this here we are verifying the token and in the JW
service not this app module we are setting this up right and we need this gwd
service in the environment variable of the back end okay so you have to have the next.
secret saved in the front end okay this has to be same to the environment variable we stored in the back end for
recoding the JW also okay so this is the environment I stored the back end the API this is for the web these two has to
be same and when you name this this way nextore secret you don't have to this is what we will get in the north
options in the secret okay when you encode and decode you get the secret here
right so that's that's a strting you will get here now once you fix it you are we are getting back the
data okay now the API is actually working now this is an authenticated route
remember the company's resolver we have the find all only authenticated people can get it so we have our authenticated
authentication setup with all pages like login register thatc section we will create a
nav bar uh with uh the signin button signin register
links and so on hello everyone so our all pages are done and also we are doing this
authenticated graphql query from this section we're going to create a Navar a header with a sidebar
with some menu and we will work on automatically close cling that uh the
sidebar when the route changes we are going to use for UI for for UI for U styling we are using
Tailwind for components we're going to use this headless UI this is from the team behind tail
Bend also we have a list of components but uh we need more like a range slider stuff like that for that for additional
components we're going to use the material UI and M material UI [Music]
um has tree shaking so when you when we use one component we are not going to import the whole
Library okay and for toast I'm going to use this react toasttify it was simple to use you
just use the toast container and uh use the toast function to generate this toast
and we will actually customize the look to match our style okay there's nothing here but we are going for an yellow and
black style look for the application yeah so let's start by installing
the Headless UI okay let's do this inside the UI
install the Headless UI react package and let's create the sidebar for
the sidebar I'm going to use the dialogue component from The Headless UI this is the code I just
used this code I made the body I changed the animation to come from the right and also I gave some styling to
make it occupy the entire height and I having a fixed width in the Right End
okay so inside the organism I'm going to create a sidebar TSX I'm going to copy paste this
component and we will walk through that and but at the time of uh my development the introduce this version
two we changed a few things so it used to be like dialog. panel dialog. title and so on but they have introduced some
changes it used to be like like transition. root transition. child they have introduced some
changes um okay so this component sidebar exposes a button so it packs the transition the it packs the heights the
dialogue and it exposes only the button the button is going to have the menu we are using this Tabler icon there are
other options for menu I'm using this menu too the hamburger one and on clicking it we're going to
open the dialogue okay so this is the dialog overlay okay I'm going
to import the sidebar into our page and let's have a look at
it and um okay so the sidebar so it needs children let's have
some children so this is how it's going to look we will have this in a in a header
here at the end of right the right corner we will be having this uh hamburger and clicking this
the menu will open and you can close it okay so um there is this transform
transition okay so the sidebar is working and um you can simplify if you don't want the over overlay you can take
that but that you know that um so having an overlay brings some attention to the sidebar I really like it
and even if if you want to simplify you can even remove the transition Al together and just have the dialog up
here and remove basically the transition works like we have this enter enter from enter
to leave leave from leave to and uh we just set the it's like key frames we just set this uh
States it it could be positioned like you have you see here or it could be opacity and so on along with
duration and you keep the children inside it we have two transition children here
one for the overlay one for the dialog and the dialog is much simpler we just have a an absolute button
absolutely position button in the right top top zero right zero with some margin we have icon X there that's what is you
used to close the dialogue okay um fine so let's start uh let's use
this side uh sidebar in a header component so before proceeding with the header let's we need a brand icon brand
component now um look like we get the class name we get the rule basically in the
header near the logo we are going to mention uh what application is this like manager admin valet and so
on and it's also optional basically which is short form we are just going to go with the brand
icon which is the uh parking slot with a car coming and going right having a space followed by a a
DOT if not we are going to have the brand icon and with and U Auto space and uh my
name and we are having this type this is the brand name and the type the rule is also
optional type we'll make it optional let's import the
brand let's also create a container component the container container just uses a container T classes class with MX
Auto in both the margin in the both sides I'm also having um px2 to create some space some Gap in the
border it's a preference thing we can remove it we don't like it
okay let's uh we also need a let's see a type here called base component I use this in a lot
of applications it comes with the children and class name which I think I use in
pretty much most of the components I need children I need to pass children I also need class
name that's a base component type the header properties we're going to get the type here actually this is
prop drilling okay we will use this header in the layout file and from the layout we know which
application right we have for example this layout file belongs to the web application that that is Con is consumer
facing customer facing we will create more more applications here web manager web valy web admin so that the layout
files know what application they belong to so we pass the type into the header and we
again pass the type into the brand yeah it's also create that menu item
type go to the type page and going to have the label and the Hatcher of the
link so again we are going to set the menu item from the layout page itself because the menu menus are going to be
different for different applications so we are making the header and sidebar reusable let's import the menu item and
the base component create the header we need the UI information for that we are going to use
the use session from the next o react package and did you remember we updated we created a custom type
declaration in the network library we have this right and also we extended that
here we just imported the type declaration into the web application we need to do the same for the UI
also this types. d. TS is the file is going to have uh the type declarations we can add more if you want if you are
like this is actually we are customizing type of an existing package right this is not our type this is the
type that next came up with and I don't want the ID here I want that U ID okay so that I changed it so if you are if
you want to update use modify a types from a different package that's where I use
this kind of type declarations and when you use the same package in another Library you have to
import the the updated type declaration and now the error will go
error will not be there let's start with a header and a nav bar the nav bar is
fixed in the top okay it's full width it's going to cover the whole thing and then I'm going
to have the container inside it so I have some Styles like I have some transparency for the Navar background
blur have some Shadow this is too light actually okay with top zero and it's
fixed and inside the container first let's uh let's introduce the logo which is a link to the homepage
okay and based on the U responsiveness the based on the page size I'm displaying the brand or the brand with
the short form actually we could you could have done something like uh manage the responsiveness here okay
but this is what I went with so automatically this will be hidden by
default and uh when the when the screen is small small we will render this one with the short form the parking slot
followed by the a DOT for the bigger screens that is small and above we will be rendering the full version that is a
parking space parking space aut of space and my name let's use this in the layout and we
will build that initially I was having story book for this development it was taking too
much of my effort so I got rid of it hopefully in the future we will
[Music] see we will see a project which uses story book for UI
development okay let's forget about the menu items for
now context we need to make this a client component okay
so this is the header okay this is the icon and as you can see there is some
content behind the underneath the now bar I'm going to use a shortcut which is this is a fixed layout
So Below the nav bar I'm going to compensate this height now we have
this okay now any to any page that uses the now bar we are going to have a fixed now
bar but the content will start below the nav bar there won't be any um overlap content are is not going
to be hidden behind the noware okay let's uh keep the so we already have the uid So based
on the login status if the user is logged in we're
going to display a sidebar which is the hamburger menu and clicking it we will show the Side Bar sidebar if
not we're going to just display the register and login buttons they are actually
URLs we need to create that user info component the user info component again uses the base component it's children
and class name we get the in uh session information I storing the image name and U ID and I'm just
rendering them okay it's a whole flux box we're going to have the image in the left name and the uid
T in the right in the side bar the sideb bar starts with the user menu and then we
Loop through the map menu items and we will render links let's also create this log out
button because um I think we use this in one another place also I don't want to keep doing this
okay we just inting the signup out it's just a button not a link inside that I'm having this icon door exit from
Tabler or exit this is the log out button we have some Flex box a simple component I'm actually worried why am I
using the a button component inside button inside a link okay so since I'm logged in
I'm I'm already seeing the sidebar okay I'm going to have a default
image so that's what even in the user info I'm using this user.png I'm going to copy that user.png
to the public directory okay I just created why a simple one
like this maybe it's not perfect but it will do the job it looks massively
misaligned maybe let's create a have a border in the image not
bad Al I want the log out in the bottom header Mt Auto but still it did not listen it has to be
a maybe let's use the justify between here and we will bring the log out button inside
it that worked because let's have a padding bottom and uh yeah the log out button
looks good that is a side bar sidebar let's add some menu
items from the layout page we're going to have the search bookings and about
pages and wow okay I introduce another Flex box inside
U to render the list and I'm also having this hover Style on hovering I'm
transitioning I mean I'm I'm including an an an underline with an
offset okay and also I'm moving I'm adding some padding LIF okay so that's the now let's
um let's SC a dumy page and we will see okay that's the about page when I click the above wow okay now
one more problem is the sidebar is not closing right sidebar we use this use State and on
clicking we are managing the state but the sideboard does not know if the URL
changes let's create a reusable hook okay I'm going to create inside the
UIL I'm going to create a dialogue
yes basically we create this use State open and set open and we are returning the open and set open but in between we
are looking at the we get the path this gets triggered this gets updated when the path name
changes we said that we also said that as a initial path name using use ref so when this changes it won't trigger
retrigger it's just a placeholder and whenever the path name changes we are checking if the path name
is is same as the path name we saved in the US if it's different we're going to we
are going to close the sidebar that is setting the open state of false and then we are assigning
the updated path name to this initial path name instead of the use State we can use
the use dialog use dialog state from the
UIL okay now let's look at the go to the
homepage go to the above now the sidebar closes okay so we have uh our basic UI
setup ready we have the na bar sidebar we have our Pages we need to create those pages we can also log
out if the if the user is not logged in then we will show the register and login buttons and we can log in
okay we have a few things going on here let's clean up that is from the
page okay so I'm going to remove everything except the query one okay so in this section we're going
to create the search page okay we're going to basically search garages and uh the garage should
be having free slots and we should we will always be also be trying to filter the garages
based on the types of slots it has we have like car bike bicycle and heavy heavy
Vehicles right so let's get to the garages resolver this is where we are going to
keep the search garages very so before creating the uh query I'm going to create some input items input
dtos I'm going to call this search filter. input. TS here first we need the date input
filter which is going to have start and the end dates so we get string for both of
them right okay and the second
one we should allow people to filter the garages also so we already have this find mini garage
arguments this we're going to have the we order way cu or disting Etc I'm going to only pick the where order by Skip and
take and finally we should we will also return a slot count per garage so for
example we are looking at a garage and we need how many Slots of slots per type of uh slot how many number of slots
available per type car 17 slots Bike 12 slots that's that kind of information so this object type will
return that we're going to send the type price and then the count that number available okay back in the
resolver let's start creating the query this is going going to return back an array
of garage I'm going to name this search garages so the arguments you're going to
get the date filter that gets from the date filter input which we just created location filter is going to come from
the common input okay so we have this so this is the bound not lat
long Northeast long Northeast uh lat Southwest longitude
Southwest this is what we use to filter the garages okay this is we not we are going
to just use a basic wear condition to look for the latitude and longitude that exes inside the
rectangle and this garage fil is something that we picked the we order by Skip and
take and also the slot where filter comes from the slot dtos okay this is one this is the
filter I need to update something because uh we are going to pass an array of types so users scan search
slots with the slot types car bicycle and bike so they should be able to do that so right now we can pass only one
right that's not the case our filter is going to be going to allow multiple types mention multiple types
when filtering so I'm going to create another input type
called enam slot filter type says equals that is the equivalent of this right we can pass one slot type so this slot type
actually comes from en. slot type okay this is the we can pass only
one slot item we are basically empowering the front end that is the whole point of graph Q right so in here
we can pass an array of slot types here we can pass an of SL types and Prisma will ignore those things I mean filter
okay that's an opposite of in right not in but not is opposite of equals so slots except this one
type now we can just pass this and I don't have to explicitly mention this because
this is already an input type so next nextjs will recognize that that one I I wanted to do then let's proceed with
building the resolver let's get the start and end time let's convert the
dates these are string so I'm converting that into dates and also I'm finding the current date now we need to do some
validation we are going to have some validation in the front end as well um using zard to calculate to to
have conditions like the end time has to be later than the start time and so on but still this API can be accessed
by as an API right without using our front end so we also need to have some conditions
here I have set this start start time but I'm making sure that the start time is if the start time is less than
current time I'm just setting the start date start date to the current time current
date okay and then I'm finding the difference in seconds because we have one more
condition if the start time start dat. time is greater than the end time I'm going to
add the difference to the end time end okay if the difference is like 2 hours the booking is 2 hours the start
date that there is some data corruption okay we can basically return an error here but I'm doing some
yeah uh okay maybe yeah returning an error could be a better option but I'm doing
this so basically I push this start date to this
date to the current time and then if the start if the start date is greater than the end date I am taking the difference
and wow okay okay
actually we have to do this here because we have moved the start date so we have to move the end data
Also let's do it difference in seconds let's find the difference
here okay and if this error happens we should just throw an error through new bad request
exception do time should be
earlier than the end time
fine let's get the filters from the garages I'm I'm extracting the garage filters and I'm making the wear
condition an empty object because later we will be spreading
that that's it now let's uh return this. Prisma do garage. find many spreading all the
garage filters okay so types script will make sure that everything is typed we created
this garage filter okay from the FR mini garage so types skp will know that okay these
types are same so that goes right into the find mini
function fine so we have so inside the we condition first I'm going to spread the we i d structured right
so this is a default value if the Val is not specified then we are passing an empty
object okay I was expecting an error here trying to
destructure it not nullable okay so I'm going to just make it an empty object and uh
let's move on the second condition the important condition is the address I'm going to this is the rare condition okay
the lat of the garage has to be less than or equal to the Northeast lat that is the boundary print and scent
right when we move the map GL we get the boundary Northeast and southwest corners and we we will pass and we use this
condition we should be greater than the Southwest lat I have to restructure
that okay similarly for the longitude also we're going to have the less than NE
longitude and greater than Southwest longitude fine and that's not it we also need to filter based on the slots the
slot type and so on the slots some so slots and garages have one to
many relationship right garages slots have one to many each garage is going to have multiple plots that's why I we have
to use this sum uh that is why the Prisma which helps us filter this one to many
relationship inside it we want to make this is the second important filter the first one is the address second one is
the slots the garage should at least have one slot without slot they cannot book we are also not going to return any
return the garage if the garage does not have any lots
available here we are checking none of the bookings so we'll have a r condition here the first
one none of the Bings must have this condition that start time less than end time and end time
greater than start time that's the first condition the second condition is start time greater than start time
end time less than end time okay so that we are making basically making sure that the time requested by
the the customer is not overlap with any of the slots already booked slots actually I
made it I want wanted this to be like really complex think about it we can create hourly slots okay 78 89 something
but this is much more flexible 714 to 858 it's not hourly charge mostly parking slots book hourly charges right
maybe they round the hours and but here customers can can
actually book in ter in minutes or seconds actually actually the from the front
end that is the search garages we have one more uh query which is available slots this is what is going to get as
the number of slots number of slots per slot type and also the
price okay we're going to get the the parent will give the garage information we also passing the same date filter
okay that we pass here you will see how we compose a query okay we pass in one hook we pass the garage filter date
filter and everything and we will share those input into these two queries S search garage and uh available
slots so let's restructure the start and end let's convert the string into the dates and then I'm going to
create so this time we need to do some uh manipulations I'm going to first get the group by slots
information by ating this. Prisma do slot. group by I'm going to
group by okay I'm going to group by type okay second
one I need the count count count let's also have a rare condition
here destructure all the slot filter and the garage has to be has to equal the garage from the parent garage. ID we get
that here also we have the same condition here about the bookings the booking should not overlap
with the requested date requested date time here so we give we get
this this going to be an array and we're going to get the count and type
okay also we need one more information which is I'm going to get the minimum of price
hour okay there are going to be different types and the same type can have multiple prices so I'm going to
return the count DOT type so we need to clean this up so basically the count is going
to have the number the type is going to have the type bicycle car Etc minimum is going to have the price per hour let's
clean that up I'm going to we we already mentioned the return type is going to be type price price price per hour and
number I want to clean this up so basically I'm I'm looping through that I'm getting these things and I'm
returning a simplified object type is type count is count. type price for hour is minimum. price so these are the two
resolvers now let's move on let's see if our back end is working okay everything is uh
everything is working now let's move on to create our forms we're going to actually use Zod and react hook form to
have the search information so yeah the API is done we will move on to work with our forms
Library okay actually before going to the front end stuff we we have done the back end part the quer is the query is
ready along with the input and output types designed and um we have to we can do the bridge actually which is the
graphical Quant part I'm going to compose a query
okay search garages going to pass the slots filter garage filter location filter date
filter and inside that I'm going to pick the ID and uh the address we are going to
pick the lat long and the address which is a string maybe this is a bit confusing we
can rename this but and getting the images available slots
price type and count type price and count and also verification verified so we're going to display that in the front
end okay actually the the available slots is the res field okay I was wrong I thought okay I I was mistaken I was M
mistaking this as a query it's a resolve field so that we can just keep it inside this searches query okay so we have
this date filter must not be null okay so I'm going to actually use this generate the hook and we will actually
access that from the front end so we will open that query. gra is the input file for the Cod gen go to paste it and
uh let's run the code gen in the network library it is successful now in the generated you can find the
search garages document okay so in the page I'm going to just
try to access the data to just use this query use Query as a search search GES document from the network the
generated okay and we can also specify the variables everything is available SL Filter 2 okay that does
not make sense to me okay so there is something wrong with the
resolver okay so this comes from the available slots filter the the G the resolver is not a problem but the query
the way we we uh compos this query is a problem so that generated that this variable type
okay so when we had to select we have to select both of them first one and uh we don't want to give
that another name we can just reuse the existing names from here date filter right I'm going to name the date filter
date filter that's what we use here right so that when we pass one thing it will be shared we want that to
be shared right we want we don't want any mismatch between what the search garage is searching for and the
available slots searching for we the available slot is doing the search in the slots table we don't want two
different thing I did not notice that when I composed this query second one the slots
filter let's use that and we will clean up we clean up these types we don't want these variables
okay right now copy that paste that in the query star graph you will replace this
existing query okay this was creating the problem replace
this now the code gen automatically refreshed let's go to the page and now the variable should be
clean let's just give some I'm not sure about the format here but we'll work on
that 12 and 13 so the variables is U guiding us that we miss one more thing which is the
location filter let's create a dummy garage here Gage one we will delete this
use a company here and U let's create an address and attach that to the we will create the mutation
in a bit from the manager console I'm going to keep this 0 0 just for
testing we'll assign the garage to the address and let's also create a slot because we in the query we are also
getting the number of slots back it's going to be $10 per
hour the dimension is optional okay typ his car garage ID we don't have any
bookings also create one for the cycle you can name this anything but um our mutation in our mutation we will
be creating this display name the slot name based on the count of the type of the slot before the creation of that
particular slot so this fictional garage has two slots now let's do the
query so for this set for this testing our lat long exist in the 0 0 right so this is the bound the land Northwest is
going to be 1 one Southwest is going to be Northeast is going to be 1 one Southwest is going to be min-1 -1
one oh this is the de format so
let's get it from 14th December to 4th December okay now let's go to the front end now are we getting we need to
display the response now everything is type save
see gage. ID okay let's just uh do um yes on string ify just that we can just see the
response without having to render them and style them
okay what do we get we have two results let's create some interation I'm
going to use the pre tag and uh
also the spaces okay so this is what this is the response we get back from our graph C we will get the same when we
do this here also I'm not going to again type everything here this is what we will get the response
also so we get this garage we get the ID get the address we don't have any images and this is a resolve
field and this is returning us two objects in the array first one is the car the count is one the price per count
is 10 bicycle count one price per count is three now there is a problem in this thing okay I'm going to add one more
thing I'm not going to solve this problem because I I think the product is already getting too complex and I'm not
going to um make it worse so just um reminder so we have one more bicycle
here with a price of four now the problem is if the three is already
booked the four is empty okay this this is cycle two now let's do the query
again we're going to get the count as two the price per hour is three if there is a
booking if the the three is already booked here if the three is already booked the cycle
one we will still get this no sorry so the garage filter actually we
we take care of that in the available slots we have this condition right this is one query we are not this is one
query we get this bookings okay fine so so sorry I take that
back if this booking is if the three is booked then we will actually get the count as one and price per our
S4 okay so we're not going to have have that problem sorry I don't have the problem
now I was just I forgot that fine now we have made some good improvements
right we started with our back end with good types input types argument types set up with one query and the resolve
field we we compos a query for the Cen here and we consumed that hook here with a
basic variable set up which is a date filter and location filter both are mandatory and we got back the response
on the upcoming rection we will be creating the search page we will create a s schema for searching okay I I I
think that the react hook form is a state state management Library like Redux we're going to have a pro wider in
the search section and we will be manipulating the types we will be we we are we will be using the uh range slider
from the material UI and um yeah I'll will be working on the search page
next okay so one one thing let's go and update this lat long to 0.1
0.1 now they are flat and now they are float when I try to access this the servers are not running I did the
comit I try that again we are going to get a runtime error what went
wrong let's refresh this is the query okay so we got the data but also
if the error is there now I'm actually thinking why didn't the data display got the garage
here you can also get the error and loading States let console
log okay so that is why when there's an error even though we get back this right get the error we get
the data here we get the error here for some reason Apollo is making the data
undefined that's why we are seeing nothing here this problem we created that in the
app module when setting up the graph module I convert this number scalar mode to integer so it is it is Float by
default if I if I commment that and refresh it I have to
U AP is running now we will get get that but I want to for
example okay so let's just ignore that okay um so I I started enabling this number the number scalar mode to integer
because when I was using a lot of integer and the type where
floats okay so yep I think it makes sense I'm going to remove this build scheme
options so that if I'm not removing that we should add in the entities that's for the rest
API in the entities we have to mention the plots with the field of
float okay and the lat long are going to be in a few more places in the front end and
this is going to lead to a lot lead to runtime exceptions so I don't want that to happen
so to be honest I I don't I don't I don't remember why I started using the integer as a number scalar mode in sjs
projects but um we will come back here if you're facing that error again I mean not an error but uh
yep I don't remember why I started using this so now that problem is solved okay let's start with our
forms we're going to have some really powerful search form with the filters the range
filters the radio group we going to use
icons pick any number of I mean uh any number of slot types for the filter and so on so let's start with our
form schema so I'm going to create
a here called search garages. TSX so first let's import the slot type from the
okay fine let's import the Z from the zard let's create a new object thir object first I'm going to have the end
time and uh start time time as strings I'm going to have a location filter which is going to be an object again
it's a nested object right an object ins object we to have not the slat not this well this is exactly what we had in the
garage filter location the common dot PS we have this location filter we have the Yep this is
same and also I'm going to make this optional let's not make that optional and the type is z do VM that's
how we mentioned type okay we are going to get an array of types I don't know why we I have this
error let's import that back problem here okay so we need to set up um this a
TSX because we are going to also create a provider component I need to set up the TS config for the forms
Library first I'm going to extend the root TS config here we have all these default options
so I'm extending that and then in the compiler option that is specific to this Library I'm going to specify the out
directory disc root directory Dot and this option jsx as react jsx and
now okay now the error is fixed I will add the so we are going to create a a few t
tups t t that's basically going to be it's an array with two numbers okay it's a t
tle and let's also have the pagination here skip take and that's it that's a filter right
the the location filter date time filter this a slot filter all these things and then the
pation that's it we have our form schema let's infer the type here using the z. infer and passing the schema type
of that's how we infer the type and we're going to create a few conditions
here few functions this is It's is start time valid I'm passing the whole data which is going to be this
type and I'm just making sure that the start time is greater than the current time we will have one more validation
function called is invalid end time valid we are just getting the start time end time and we are making
sure that the end time is greater than the start time I'm going to create a create custom validation in the form
scheme search garage I'm going to first add using the using the refine option we can have a function here okay that will
get called and if the function returns false we going to have this error message to
this path okay this is a custom validation
function and I'm also going to have this kind of an utility function this basic Al gu the start
time okay 2 minutes okay basically it gets a start time as 5
minutes from now even if the customer is booking right from right in front of the gate this 5 minutes will give that
buffer the end time is going to by default it's going to be 1 hour to ISO local
string that is a custom function I wrote in the U library I'm going to create a date.
TS so basically it gets a date it gets a time zone offset and we are offsetting that to get the local iOS ioso time okay
so that could be a simple way simpler way but we are going to go with this let import that utility function
from the util Library fine so we have the schema we have the type
we have two custom validation functions and we are using that in using the refine from the zard we having custom
error messages the PA this is a utility function we should probably keep that
anywhere else but let's let's just keep it here I'm also going to have this is the
default def value for the slots with the that is going to have the array of all
slots let's create the default values it's going to start the price per hour is going to start from 0
to 200 $200 is huge I think with this um 0 to 20 ft right is 30 ft length is 100 ft okay
now let's create the provider component going the provider is going to get the children so that we can
pass the rest of the application that is going to have the search Logic inside the
provider first let's get the inside the provider first let's get the current time and end time
let's get the get let's get all the methods using the use form hook and passing the type we infered from the
schema and here I'm going to set the resolver so we're going to use a zard resolver from the hook form resolvers so
zard here we will pass the schema file and then we will be setting the default values default values going to be an
object the first we already have this default values actually I think we should type
this the defa values of the okay I'm going to use the defa values
from the react hook form and we can pass this type here okay so that I think I don't want
to now we cannot pass any other values right we going to have type error
there so I going to remove all these type [Music]
assertions we cannot do this okay fine I'm going to first pass all the default values here from here and then I
will pass the date don't know why I'm renaming these things
fix that fine now we get the methods we can import the form Provider from the react
hook form and I'm going to export that I inside the provider I'm going to
return on provider passing the children inside also going to pass all the me the
methods we received as the props this this method is going methods is going to have all the everything like
register set value set errors clear error Etc so we will use the use form context
to get this all all these values okay from the ch children components that is the form
Gema okay let's create the search page in the app directory I'm going to create the search page.
TSX okay now we can navigate to the search
page fine so here we are going to use a map from the react mapg this is this is the package we're going to use we need
to install these two things in the map the UI Library I'm going to install these two okay I've
already done that install and um you also need to get a mapbox API
key this is it so go to account. mapbox.com and uh create an account login
go to the tokens and create a new token and copy the token okay and then come to the
environment variables we have all these things so create a variable name called nextore
public _ mapbox _ token you can give any name you want but it has to start with our next public so that we can access in
the front end copy the token place it here let's proceed so in the UI library
inside the organisms I'm going to create a map directory we're going to have multiple components inside that we are
going to have that actual map component we'll be having a marker component panels to to position
different other components like autoc complete and uh Zoom buttons and so on Zoom buttons also comeing inside that
inside the map we'll be also having a custom but button to position the Mark at the center of the map all those
things we you'll put them inside this organism let's go from the first one is the actual map component from the react
map GL so map. TSX I'm going to import mapg map is map props use map from the react
map FGL I think we already have the types so here I'm going to have this
view state is going to have the latitude longitude and zoom is is optional let's create the map
props I'm going to get this map G okay so I don't want this map props here so basically I'm getting what the
comp the properties of a component using the react. component props I'm passing the type of the map GL which is a
component okay we get the map map props from that and also I'm going to add height
here because we use map in two places and I'm actually passing the height as a property in one place we have a full
screen map and in the booking booking dialogue we have a half map and um I want that to be
customized that's it now let's create the map component by default the height is a
string right I'm passing this uh style text and we will just use that
inside the style property of the component right so inside that I'm going to just R return the mapg
with some stuff like I want the projection Globe so that the user when the user is too far away zoomed out we
show a globe it looks amazing and I created my one map style it has a gray black and grayish
tone I don't want any colors so the gray ones gray maps go with any design system we have for example this product has a
yellow black design scha I mean yeah guide design system the primary colors are yellow and black and the the
yellow and black actually go well with the gray map I'm again passing the height here
the pitch will give some tilt to the map I I initially I liked it but um it was not accurate because we rely on the
boundaries right NorthEast Southwest when we tilt it we cannot get that right so I removed it and scroll Zoom I
may I made it false users have to click the zoom buttons that's it is a simple
opinionated prop so we are just returning that but I'm going to have this style
map with which will give [Music] some we're using the use map getting the
current and I'm setting the Styles here okay Horizon it it gives some fog yeah we will see in the in
action so I'm going to create a search page in the templates let's export that okay let's import the search
page template inside the page fine so this component needs to be a c component because we are
using Hooks and so on the use map fine that is the map and
um if I remove this style map it looks like this okay hence I added a back High color
Horizon blend space color I made it a bit darker and the star intensity right so
it uh will start to look like this what is that and I I have also disabled the scroll and also one more thing we
have to do this is uh this has to come inside the map go inside the map for that we need to add the map Styles so we
have one source of Truth for all our CSS go there I'm going to just
import you going to do two things I'm going to have a separate map CSS file inside the map
there I'm going to import the map G CSS file okay and I'm going to import this map CSS into our Global
CSS let's do in the top fine now looks good now everything is styled
we have this copyright logo everything is working
we'll come back uh to this file to have more styles for the popups and so on so that's why I
have this separate CSS file for the map we have the map ready let's create more components the
next one is the map marker I'm just here importing the map map marker props and I'm exporting it I'm doing this because
as this gives us control to further modify it update it later the next one is a
panel the basically the panel is an absolutely positioned component we have more uh options so
this is a a union of uh string literals where we have the positions
right nine positions starting with a left top left Center left top left left top left
Center left bottom center tops it's not ordered properly but you get the point right the N nine slots in right nine
nine position so it's it's absolutely positioned and based on that based on this we have Tailwind classes position
that okay this is useful we will use this to position [Music]
components on top of the map and finally the zoom controls
here this is the zoom in button we use a use map we get the current the instance of the map we use the map. zoom in so
it's a button we have some Style zoom out again so on looking this actually we can
extract this as a button separate and then we can pass the on click on top of it
fine and then similarly we have this center button again we have the on click here okay let's
just extract a button here let's call it control button our Zoom control button it's
clear it gets children react node then this on
click get the property type from here on click get the children and on click and
assign it so we use three this button in three places actually zoom in zoom out and the
center of map okay so we can add more if we want in the
later so let's modify this let's um fine so that is a zoom control we have the zoom in zoom out Center of map
and I'm creating some composite component here okay attaching the components
inside this map control I'm creating this default Zoom control which has a zoom in and zoom
zoom out button but later whatever children you add will be added under the zoom out button if we will use
this that's the zoom control and finally we have one more thing which is uh current location
button we get the map instance we use a navigator GE location to get the current position so we get the position and we
use map. fight to to pass to that location so on clicking this basically the map will move to that move the move
to the users current location from the browser okay they're
also fine also using these icons I forgot to mention here we are using the icon minus icon parking icon plus this
icon parking is used for the center of map this we use while creating the garage wherever the the map is when the
user presses this icon the the button we will place the Parker the center of the map that is the basic setup we have all
the map the ingredients for creating the map okay first let's set up the map I'm
going to have the nework location as the initial location for the map and also we going to have panels here we going to
have a search bar search box where we are going to actually hit the mapbox API to get the
places and the users start searching typing Al here we are going to have a zoom uh zoom in and zoom zoom out
buttons yep so um okay let's go to the search search page this is what we have
here here when I start using the [Music] panel let's let's just put the default
Zoom controls and we also have to specify the position what is the default position we
have the zoom controls here right by default is going for the left top and I want the the buttons to be
placed here right center position right center you have it right so next one I'm
going to so before going there we we need to set up the on rag end on Zoom
end in those uh also the on load in those functions when that when those actions happen I want to calculate the
bounds okay when I when I drag it I want to get the bounds the Northeast lat long Southwest
lat long I'm going to write a function for that con handle map change equal to I'm
going to put this inside the use call back we have a function here this is going to get the
target target is view State change view state change event from the react map GL and I'm going to
take the target so we can actually get the event here but the uh the function function argument
for the onload and on drag end are going to be different so I'm just getting the target but this target is going to be
same for all these functions now we can get the event here and then
we can call the handle map change and we can pass the e. Target similarly on the on drag end you can do
the same you get that we call the handle map change and we can pass the you can see that the event type is different for
both these functions also we need to do the same thing for the on Zoom
end as you can see when we end up when we finish Zoom the bound changes when we drag the bound changes also when the
whole map loads we need to calculate the bound and we need
to fetch the we need to get the bounce and we need to fetch the garages inside that okay we we will actually implement
this function before that let's change the initial State initial view state so this initial view state I'm going to
create a in the util Library I'm going to create a constants file
constants TTS okay I'm going to have the this is the location of the New York City
latitude longitude and zoom let's import that and when we load the when we now
when we load the map we will we will start seeing the new arc you can also modify the zoom States
when we go higher it will be more zoomed in okay I think this makes a bit more sense or even
12 okay 11.5 I think this is a sweet
spot fine now let's do some calculations and uh we will console log when we drag and when we move we want to calculate
the bounds and we will just console lock it so we will implement this function so we can get the bounce now
bounce equals target. bounds get bounds okay let's console L it now when I drag it so nothing nothing
prints right when I release it we get this information Northeast lat long South W
lat long okay that's data we want I'm going to further simplify it to create a new object with the slat
long this is exactly how we get the arguments in our search garages Page search garages
query and now let's print this instead the location filter when I drag when I remove when I
release the drag Mouse we get this information okay okay now let's create an autoc
complete component actually I'm using I'm going to use the combo box the autocomplete component from the matal UI
there is also an alternative called combo box in the Headless UI so we already have headless UI installed in
this in this this project you can go ahead and use this but I'm going to use material UI because that's what I used
in this project okay um so yes I'm going to um in I'm we are
going to also need the material for a slider and few more components that that headless U does not have
anyways also as I told earlier material UI uses tree shaking so when we import one package we are not
going to import the whole package so yeah let's install the material UI and we
will configure the auto complete to do what we
want want it to do so let's install the requirements inside the UI component I'm going to install the material U emotion
react so these are the dependencies fine so inside the atoms I'm going to create a component called
called Auto auto auto complete
TSX I'm going to just copy paste it and we will go through that component basically we will install we
will import the autoc complete and autocomplete props now I'm going to generate the type for this component I'm
going to remove the render input from this property because this is this is this is going to be custom we're going
to have a lens icon we going to have input box we are going to have some style going on I don't want the consumer
to be replacing that style and also I'm getting a placeholder to provide it to the inner input element
that is the type and let's uh also we are going to get the type of the object we pass type of the
object of array actually pass inside the inside each item right because on clicking a location you're going to have
a dropb and auto complete here with some drop down on clicking that it's not just string we also have to get the lat long
of that location and we will move the map to that location so it's going to be an object it's not just a
string okay so inside that I'm going to return return the material UI component I'm going to
enable the Auto Select handle home end keys and this is the custom render input okay so I'm going to have a flux box
here I'm also setting the ref to this div and inside that I'm going to have an input box input element and a search
icon that's from the Tabler icon search that's from the
Tabler slash icons react okay icon search when I'm having some Styles
here and uh I'm passing the placeholder from here to the input element I'm spreading all the input props okay you
can also destructure to see what this has so this has a the whole thing that an input input
element will need okay let's export this we'll use it from the search page
you will actually come back here to customize the component before customizing I want to actually see how
the component looks like by default so I'm going to have it in the left top and let's have the auto complete
here and import it import it from the atoms not from the material UI and it asks me the options is is
mandatory I'm going to pass a simple um array of strings chenai and New York so this is how it looks like we
have an auto complete and on clicking we have this data instead of this static data we are going to actually hit the
map box element so this actually works we don't have to do much but I am going to configure the Styles which because I
had some time while building this so This Is How We configure a material
UI component using Tailwind CSS okay in say the classes you can
see the individual Parts which we can pass different alen classes to convert to
to reshape it so as you can see I have added a a boundary here and also a
h effect and it's it is also a bit transparent okay you can see this okay so that is the input element
Next Step let's let's do that map mapbox call and we will actually render the actual places names and on clicking it
automatically the map will move to to that location let's Implement that to do that I'm going to create one
more component so here we directly use the auto complete instead of that we will create one more component that uses
auto complete that component will have the mapbox pitching logic so let's create a search Place
box inside the organism I'm going to create I'm going to keep it inside the map because it is related to the map
search places box. TSX first let's go go back to the constants I'm going to have an array
here called major cities locations info also need this location info inside the types I'm going to have this
location info which is going to be placed lat long okay which is say Tuple let's import that here it starts
with Chennai New York London so on
so we are going to okay let's just use this okay that that the idea is to use this array of objects as a
fallback when there are no results okay let's build the search box search places box
component so this is the type the properties of this we're going to get the a function that gets the location
info and also the value okay we don't want that I'm sorry so directly I'm having this okay onet on
location change which gets a which gets a latitude longitude and zoom so this component Works inside the
a map component as a children as a child so that we can use this use map and this component is going to
return back return the auto complete so I'm passing the location info as a type of the data
of the item inside the array which is going to have the place name latlong okay let's create a a hook I'll
use search location I'm going to uh save the search text this is this text that the user types in
the input box I'm also going to manage the loading State also the location info
State this is the state that uh the location of the selected
item I'm also going going to implement uh a use debounce because when the user types we
want to wait for some 300 milliseconds or so to avoid unnecessary API calls so this is the my implementation
of the use de debones we're going to have store the value and inside a use effect we we are having this
timeout and whenever it gets delayed basically and when the component unmounts we automatically
clear that time out as well we can use other libraries like rxjs and so on they have even further
Advanced granular control over these kind of things but a simple timeout will
do basically we pass the value here and we we get back the debounced value with a
delay and when we keep typing it's going to wait for in this case it is th000
milliseconds we will modify that wait for that particular milliseconds and to give back the debounced
value so we get the we have the search text we get a debounced search text and I'm also going to convert this into a
400 milliseconds that delay and then we're going to inside a user effect basically we're going to
hit the API mapbox API basically I'm just going to use the
fetch api. Mbox geoc coding places we are passing the Deb to search text here Json fuzzy match true so this I see that
it um does something interesting with some even with some typos it Returns the places name I don't
exactly know what logic they have behind it it's just a fuz fuz fuz search and I'm also passing the access token we
already saved this access token right we hit that we get the response and
then we filter the data okay so I okay right so let's also
have the debounce to search text as a dependency and finally I'm setting the
load loading state to false so basically what we are doing the return type I'm not I'm I'm not going to handle
that okay we get that we get the place name from that we get the lat long using the X do Center of one and this is going
to be the longitude I think okay we'll see that this is the use search location
hook we manage the search we manage the loading we manage a location info and inside the use we also debounce it
debounce the search text to convert to create a du to search text inside the use effect we are hitting the map box
API we get that and we create we return a new object with a place name and lat long which is exactly the type of type
we are going to pass inside the auto complete we set this here the location info and also we set the false in the
finally now let's use this hook and we get all this information there here we going to get the loading
State location info search text search loading and search so auto complete I'm passing the
location info the options is going to be if the location info has a length we will return that or else we going to use
the major location info from here
okay maybe we just have to display that like no results found but y this is how I'm going
with this equ is option equal to Value this is options this property decides a selected value and since the
the value value we pass inside auto complete is not a simple string right so we cannot directly compare that we need
to compare the place name from the option and also from the value so that's why I had to add this
and this is no options text if the search text is is there and there are no options we're
going to give the no options so this is contradicting this right yeah I'm going to address that and
I'm going to move on if there is no no search Texs and no options we going to tell type
something so the options label the ex is the whole object and we need the place name that is going
to be the option label the input changes I'm setting the loading state to true this load the set
loading comes from the this hook okay also we set the search text the search text gets set it gets it gets debounced
and then we do the API call and we get we set the location info also we see we get the loading and
we set it here and on change you're going to get the value this value is going to have the lat long
and the place name and we got we already got the instance of the map using the use map and I'm going to use the map. FX
fly to to you to fly to this location and I'm also setting a zoom here actually we can go further like the
the places we we get include cities districts States the
location it's going to vary okay so we can set the zoom based on that if we use a select a state we have to have the
zoom in a higher number I mean lower the higher Zoom rate right we can we can do that but I'm going to
keep it simple essential makes makes sure that the animation works it looks cool so I enabled
that and then this is the call back okay the on location change this function is going to set the
form state in the form we want the location we also said that this is the search search place
places boxes box let's import that from the organism that's it now let's give it a
try this is the component when I'm not typing something when there is no result this is the that
major cities list right I can click it oh okay the zoom average Zoom is 14 right
remember Zoom is 14 and that's why it got assumed maybe let keep it as 12 let's also go to can
I take some time maybe in the production in production uh application we should not have this level of
Animation also you can see that the location filter is getting updated so that is the lat long the boundary for
Chennai let's do it once again also yeah yeah we I forgot to actually test the
API uh call so we have this major cities let's go to Tokyo which is not here we get all these places names
okay new some national museum Tokyo City oops that's that's okay that is not Japan
actually that must be a different Tokyo yeah still that is some some different Tokyo that is
that's Japan but a different Tokyo different place okay so when I disable this essential which we should
do I think let's go to Germany Berlin if we already have Berlin
here okay so that's it we when the zoom happens the location filter also updates when the move happens when we move the
map based on the location using the auto complete the location filter updates when we drag the
map we drag the map the location filter updates okay fine so we have set up the map the
upcoming sections we will call our mute the query the search garages
query and we will render the results okay so let's um let's add the start time and end
time and also we'll see how to fetch the data here let's start to use the so remember
we have the schema SE garages we are exporting the provider so first thing we need to wrap
the page the search page first we need to wrap this with the
provider and then here we can we can use the use form context the use form
context comes from the react hook form you also need to pass that type which is the form
type garages you need to get the form type SE garage now we can get the register
set value for example the set value will be used here once we get the location
filter remember we also have uh this here the location filter with the same name so basically we can do this set
value first we pass the KE which is the location filter and then we can pass the data and
it matches okay if I pass something else typescript is going to complain we cannot do that
yeah we have that uh that facility there and we have done one thing so for
the date I'm going to okay so we need to make the page we can do two things one you can
simply make this page a client component this one or else we can can make this
a we can actually export U make this a search page content and we can expose a search page by actually wrapping the
search page content with the with this but I'm just going to convert the page into a client
component now the error goes away have this I'm going for the dates I'm going to do something for like
uh um based on the times I'm going to show the a different icon like sun night sunrise sunset those kind of stuff I'm
going to create a component called icon types I I'll just past that in the molecules and we'll go through
that the icon types let's focus on this one okay based we will pass a time and we get the
hours from that and based on the hours we are basically returning a different icon Sunrise Sun it is from 10: to 4:
and after 10 to 8:00 in the night we'll be having the sunset other than that is night right
22 4 is midnight so moon and the stars so this component is important we'll come here
actually I should have this as a different component you will think about that
later back to the search page component I'm going to so this happens inside the SE search
Place box okay under this we going to have two input boxes with the start time and the end
time I'm going to paste that okay so we're going to have an
absolutely positioned icon drop down icon arrow down the icon type is the component we just create
just created and we also have to pass the start time so we can get the start time
by using the watch from here here we can get the data end time and start time
icon Arrow dams coming from the Tabler icon fine so what happens here is this is that
component this has to extend all the way okay so I'm going to wrap everything inside another div and we
will it's going to be a flex box um Flex column and then I'm going to do the item
stretch so that we get this okay so this is the search bar this is the oh I clicked that
accidentally click CH I accidentally this is the uh start time and the end time we don't actually have
the start and end here but the arrow shows okay you can make it maybe better but if I have somewhat something like
6:00 it will show the sunrise if I do if I select something like
12:00 12 a.m. okay is Sun that is the
component Al we set the date and also we get the register button register function and we are registering the end
time and not time we also setting the set value so right now what we are doing is we are
collecting the let's just watch the entire entire thing let's call this form data and we
will rename this to form data. start time and form data. end
time and let's just console log the entire form data so you you will see the location filter and date filter are
being populated when I load this form data already has the height so these are
coming from the default ones but that it takes the end time that is 1 hour from now start time 1 hour from now the
location filter is already fixed right even before before I start interact it it imagines the start and start and end
at end time to be the current and 1 hour from now and it also finds the bounds in the map and it sets the location filter
actually we have all the information to do the base to do the query and we are going to have the have
all those logic so I need to actually populate the dependencies with set value now
everything is fine I'm going to have an a different component called show garages in here this is going to be an
organism show garages TSX so inside that we are going to actually get all the compose the variables and we will do the
pitching with this show garages Square the component first we are getting getting
the okay first let's we already have in the generat we already have the search garages
document going to use use lazy query because the query has to happen based on the variables okay when the
variables changes we need to refetch that and yeah use lazy query comes from the app client use lazy query and I'm
going to pass the search garage document so the lazy query is going to return an array first one is going to be uh
mutation um the function to query search garages and then we can get all the called loading
data and errors error okay and then I'm going to just return and fragment with uh we'll just
Loop through the search garages and we we're going to have a garage marker that is going to display
the data as a as a parking slot let's do that we also have to do a lot of uh thing with the
variables and whenever they change we have to refresh also for for now I'm I'm just going to use a empty use effect
and I will just all the search garages here let's create the garage marker component let's place it okay actually
we will keep these these two inside a folder called search I'm also going to get the garage
marker inside it so the garage marker it's a dialogue we first we initially we will just show
a marker ID and um actually we will show the parking icon on clicking it we will
display this dialogue okay on clicking it we we render this we switch this uh State popup State and it just theog
opens and it will just show the marker ID or now but actually we are going to have the entire booking flow inside this
dialogue okay we don't have the dialogue okay I think we don't have the
dialog component yet let's quickly create that so this dialogue is very similar to
what the Headless UI gives this is the
dialogue yeah this is the code we just have to do a few changes like because the transition do child is try
is replicated headless panel dialog
panel okay that's it also getting I'm getting the open and set open that's that's okay that we
manage using a simple use dat from the consumer of this component we have we can pass any number of children using a
react node we also passing the title here and the class name and the with the class name so the class
name I think we don't need the class name here okay so I'm going to have the class name
here but I'm not using it here but the with the class name is being used the dialog panel
okay by default it's I I given the max with medium
but we can change that if you want more we have to pass Max withd large or Max width extra large that is the dialog
component it's very similar to what we have here the transition CH transition
child okay finally I also have need a keyboard shortcut that whenever user clicks
presses Escape we want to actually close the dialogue so for that I'm going to create a hook called
use key press I'm going to create a inside the hooks I'm going to create the keys while the use key
press basically gets the keys on the action though we are getting an array so when that keys inside any of
those keys from that array gets pressed we are using the window or add listener ad event listener and we we will also
clean clean that up when the component unmounts and whenever that one of these keys are
pressed we are going to call this action okay it could be anything could be an alert
box be anything but in this case we are going to close the popup fine let's also import the parking
icon okay let's create the working account the items which which is just a p we have a border border black BG
primary there some Shadow with a p okay that's a parking icon okay that is all about the garage
marker now everything is ready let's have a demo I think we already have a park having have a garage
created garages is not defined okay we have to we have to import
this fine so right now we don't have any garages in the nework but we know let's modify that
using the Prisma Studio I'm going to modify the sample garages we
created go to the address is 40 minus 40.7 minus 74.0 okay now the garage should appear
in the nework oh okay so yeah we are not passing the dates so we are not getting
the we could not fix the data let's do that this show garages when we are calling
this let use the use form context again we will get the end time start time location filter and when we do this
we will pass the variables date filter is going to be end is end time let's Al maybe let's rename
this so that we can simply pass and then we also have to specify the location filter which
is I just remove made the made all the with all the numbers the long values
mandatory I don't remember why I made them optional in the first place but now we can directly pass the location filter
we also have pop dependencies fine [Music]
now we are seeing the parking so that is the garage so it happened to fall into the this the
ocean New York Bay into the bay okay on clicking it we we open the
dialogue and it shows the number so we need one more thing we are going to have a u filter icon here okay on
clicking it we will have a sidebar and that sidebar will give us all the options like we can configure the what
height we want what length we can filter basically filter the types of slots filter the price per hour all
those things so this is going to get really complex okay so I'm going to create a create
another hook to to uh to manage all the variabl variables related
things okay so what I'm thinking is let's just go with with this with this in the sense we have a component we
have uh our pitching function we we get the values through the
watch and we are calling that right so later we also have to add more things like the slot filter which is which gets
the height length hype Price Power Hour and so on I think this should do so I'm going to
simplify right we'll just go with this and um we'll see if we need to have a separate hook with all those
functionalities we'll add it okay let's create the advanced filter here the search
page the show garages right now we are simply getting the date and filter and we are using in the PCH function from
the use lazy query but this time it's going to be a bit complicated because we're going to
have filters that include length width height price per hour type and also Skip and take for the
pagination I'm going to create a an an adapter in the forms Library I'm going to create
adapters search form adapter TS first let's specify the
types so I just take the form type from the search garage of schema and I'm going to pick the times height with the
dimensions price for our location filter skip take for the pation you're going to have a hook
called use convert search form search form to variables so basically we are going to return the
variables from this hook so it is going to take some logic and we are
encapsulating inside the say this hook all the logic that goes into creating that filter and it's not
straightforward here we are just giving the end we're just passing the end and start but we
are going to deal with the ranges here like greater than or equal to less than or equal to and we're going to
complicate this this component so that we are taking these complexities out so search garages queries variable comes
from the generated code this is the one which the search garages document uses
okay search garages document and we have it here that is the type of the variables so I set that type to the
use State that's the variables and let's use the use form context let's also pass the type here
which is the form type do garage we going to get the B
State and dirty Fields the important thing is we only also
um we can do one more thing like instead of the watch you can do use watch and you can also pass the type
here and you get get all the data here okay the the thing is we get the dirty Fields so we have the default value set
up in the here right we have the default setup but if the price per our field is not dirty if
the user has not touched it then we are not going to send that in the query that's an unwanted filtering right
that's so we are taking the dirty filters and we are going to just make sure that we only add
those fields to the those filters to the variables if their dtive fields contains that
field so uh everything is a Boolean if the if the value is different from the default value then that is going to be
true fine so I'm going to get this as a form data and I'm going to use the use debounce to
create a debounced form so that whatever we do in the filter the
whole data okay we are going to debounce that whole filter data that's going to include the date location filter the
range filters for the height width so on type is going to be a group group button radio group something like
that okay so we get the form form data for dir FS from the form State we are debouncing the form
data okay now inside the use effect first let's create the date filter const date filter
equals it's an object we're going to they set the start to to
debounced dot start time and end to ebound do end
time okay so I changed the use effect use watch to the watch again and we are
just creating this date filter we getting the start time and end time and uh assigning to the end we are just that
is just an object the next one is the location filter that is going to be of type we
going to get that type from the from here equals let's rename this to location
bounds and we'll use it here and the other ones the slot filter and the garage filter we
are only going to have the pagination for the garage filter let's look at the slot
filter the slot filter we're going to need length
width height price per hour and the type all these five things and the filter is going to be a bit complicated so I'm
going to create a helper function .ts this is the helper function we get
the we give the data in a tuple format and it's going to return back in this format greater than or equal
to so this is going to be the return type okay that's how we filter a
range let's use that I'm going to create a function called U create slots filter and these are optional filters
right let me just copy paste that we have to look for the dirty Fields there how do we get the dirty
Fields field names marked Boolean when we pass a type of the schema so we basically we're going to pass the
dir fields and the form data and we're going to compose an object if the dirs do
length yeah so if the length is there dir do length is going to be true right if it is true then I'm going to
assign this object okay greater than first and first number less than less first number
so we do that for all five times for all five Fields it has to be dirty and if it's dirty we will use it and the type
is different so it needs an in followed by the type and this type is actually an array maybe I should change this to
types okay types and here
types types okay fine so that is the filter function so here I'm going to create a use
that create slots filter function to create the slots filter
equals create slots filter I'm going to pass the dirty fields we got from this um
form State the use form context also we have to pass the form form data I'm going to do that okay
those are the relevant data similarly I'm also going to have a garages
filter this is going to get the Skip and take we may add more if you want have more things to
filter based on the data in the store in the garages table the Skip and title take our dirty
and we are just adding that number okay so let's create the garages filter as
well so those are the four types of filters we use create GES filter and we are passing
the dirty filter and let's also destructure the Skip and take and we'll pass it
here now we have four types of filters let's save them into one V one filter and we have to set the
variables can also do this okay so basically we created these four filters and we are assigning that
to the filters and now we can just export this
and can consume that from that component so here all we need is the [Music]
debounced wait a minute let's call this debounced form data and we will
destructure from the debom form data and we will add the debom form data in this dependency
AR okay that is the hook I'm going to go back to the search garages page show garages component and instead of doing
the this thing here I'm going to Simply use the hook hook from the form slash adapter
slash search bom adapter and this Hook is going to give back the variables and we can just pass the variables
there okay I think we don't have to rename this and assign it again okay this thing will work we just get the
location filter directly from the form data and we attach that to the variables now here it is saying that null is not
assignable to the this thing the basically we assign variable to search gares query variables are null
okay because initially it's going to be null so I'm just going to look if the
variables is not is through the okay if it's through the Then I then I am passing that okay I think we are
good now the page let's first check the Geo query that's the only filter which works right
now Network we have it when I scrolled it we get nothing because we have only one gun gar and it's not inside this
bound I move back now we get that garage so basically the variables thing is now
working let's also quickly see if the I think the start and end time is also matched perfectly fine now let's start
working with our filter it's going to be a sidebar we're going to have
uh this filters the slot filters let's work on that so inside the search I'm going to
create a filter sidebar. TSX this is going to be a sidebar we're going to um manage the open and set open
ourselves and then I'm going to use the use form context Al are the types because we have input
elements we have to actually make it work together I'm going to return a fragment
here first is going to be the button remember the sideb we already have we only expose the button and on clicking
the button the dialogue or anything will open here we will be using the sidebar component icon filter comes from the
Tabler UI Tabler icons puling dot okay so let's create
this a simple component basically it's a puling DOT
and we use this dot to create to show that a particular field is dirty or not I mean accessed by the user or not I'm
going to get the base components types and uh get the children if there are children I'm going to just pass it we
have we don't have yellow we have primary color we have if you don't have children
it's going to be just a width to height to height to actually the rounded full has to be
here and it's it's going to be absolutely position top zero left full and we have we have that
anime animate pulse and if we have children then we have uh almost the same thing with some
padding on the same location absolute top zero left full that is the pulsing dot if the Dirty Field is uh if the
field length so if any one of the if if the dirty Fields is
at least one we are going to have the pulsing dot in the button itself showing that the user has modified something but
actually I did a mistake here in my practice project I was thinking that if the if I if the do Doty fields. length
is there I thought it's the a number of items inside that but it's actually a field basically we have to do object dot
values of so this will convert this object into an array and then we will take the length to be through the that
is not zero okay that is the that is the one and then we will create the
sidebar this is the exact Side Bar we used in in our header also going to have a fleux
okay I think we we have a small problem here we need to keep the set open outside okay we have to update the
header also header component and then we are we going to pass the make it open and set open that's
simpler in the sidebar we're going to update the properties to receive the open and
set open States okay let's modify all these things so actually on clicking this we
now we need to we need to switch it switch the state okay I think we are good what happened
here so we need to update the head open State type to use this so how how did I come up with this property type so I
just hovered over this and I got this type property and um I'm using the type as the property but
now we can switch it that's a change I had to also I have to pass the open and
um set open States it open properties in the header similarly we
will do the same here okay and let's just have a look from the search
page I'm going to have another panel this time it's going to be right top let copy paste that and then modify
the right center to the right top then I'm going to have this filter sidebar
now okay so uh I simplify change a few things so first one I was I created this nav sidebar component so basically and
I I put this button with the icon menu and the sidebar and all the menus inside okay I simplify the sidebar right now
sidebar gets this open set open it won't expose any buttons okay it's just a trans
transition I just divided that into uh two things because in the filter sidebar I Al I already have a button
here okay now this is what we have the sidebar
works and um this is the filter we're going to have more we going to have the sliders
and everything thing inside it we have to create a filter heading basically that gets a title and dirty
Boolean and we we use that we also use the pulsing dot to show that the filter has touched has
been touched the filter heading TSX it gets a title and U dirty Boolean
we are rendering that going to be a relative because it has to be relative because the pulsing dot is
absolute and U okay yeah let's build the um filter
sidebar let's start with the first one the type so for that okay we we have to actually create the range slider and the
toggle button group and then we will come back here so inside the molecules I'm going
to create a range slider ESX so basically I'm getting the slider and the slider props this
component is going to get the slider props the whole thing lives inside a div with the width full with some padding
top ping left and right and we are having some opinionator Styles here with the value label on and then I have some
Styles so this we already did in the auto complete auto complete component also we did the we configured the
component using Tailwind by by pointing to this individual pieces
of the component I did this also you can modify this that is a range slider the next one
is Radio group toggle toggle button group actually let's create
that again I'm just re-exporting it right I'm renaming the it I'm renaming the toggle button to toggle button mui
I'm re-exporting that by having some styles here okay I'm making some giving some margin top making it
block similarly here also I'm having some Styles and then I'm having some open props like disabled
Ripple disabl touch Ripple and focus Ripple so these are the two components let's import them from
the from the filter sidebar fine so the first one you're going to create the a
type toggle buttons we going to have a use this is a controlled
element I'm going to use this controller from the react hook form and I'm giving the type and uh
since I renamed this to types it is complain so when I change that it it is fixed I have to pass the control from
the use form context to the controll element and now we get the values here values and that particular so we have we
get this dirty Fields Collective that has everything but that it has everything right booleans for each field
we have in the form schema but inside a controller it's a controll component we can get is dirty
that is going to be true if the types is dir I mean touched by the user Modified by the
user you can also get the default values value onchange so we're going to have the
filter header we have imported the hugle group tle button group and uh okay so basically in the on change
when it changes actually I have to get the value from
here what do I get oh fine so I was not importing that
correctly it is two step out fine now the toggle button group will work basically on change I'm going to get the
the first one is going to be event and the second one is going to have the value
and that's what I going to use we don't need to get the value from
here okay sorry I have to set this here okay we setting the value here and then this value is this
value and then I'm I'm going to proceed to display all the so I have this icon types comp it's an array
basically it returns back an icon based on the enm type for the bicycle I'm using icon bike bike motor bike car and
this is for the heavy heavy Vehicles okay let's have a look at the filter
now okay that's because the the the default values we still I did not fix that type to
types I have fixed it now we get the vehicle types and we can toggle and when we
toggle we see this dot which is not a DOT so let's uh see what's wrong so I have this rounded
full it's absolutely positioned what's wrong rounded full okay you might have seen that but
actually I'm setting the color to the parent okay sorry so now we have the dot which is
animating so yeah so I'm going to give the animate here because if I add something some
more children everything has to animate the pulse fine that is one filter now I need to
see oh you saw that the filter is actually working you can also see the network
uh cycle you remember our garage actually has a few slot slots for bicycle and car okay one car and to
Bicycle what happens if I toggle the cycle okay the the rork call did not
happen because that combination of variables is being cast let's try that
again okay we get the graph qu in the payload you can see that the slots filter the
types the ones that are there right if I check the bicycle again actually did not make
the APA call because we already did that we already did that very query with all these combination let's try with the
car I this deselect the car now we get this and uh I'm actually looking for I'm
actually trying to demonstrate that when everything is selected which is this we are not going to see the slots
filter at all that's what I wanted to show you and when I when I update that you will see the slot filter with the
updated with the selected ones and also you can see the dirty marker the dot being and also this is client s side
caching okay so it is going to save a lot of performance so let's create other ones with the slide range
slider okay let's are the other ones the second one is price it is also a controlled
component let hide that this is also a controlled component I'm using the controller and we it knows
what values it can get it's a tuple an array with two items passing the control again and inside the
render the props we can get the value onchanges dirty default values
and in the render I'm going to return a div with a filter header with the title and the is3 I'm going to get get the is3
from the field State this field State this is3 belongs to the price per hour field and in the range slider I'm
setting some steps this depends upon the range right we can have some other field which can
can be in thousands for those fields we cannot have the step as five it's going to be a lot more granular and we will be
doing a lot of API calls so I I I kept the steps outside you can also have some property set here okay if you think all
the rain slers will be using the same properties same value for the for the particular property I'm also making the
min max from the default values getting the value and down change as it is and I'm also adding rupees but actually I'm
going to make this a dollar because this is a New York related
product dollar okay let's have a look at that this is the range slider so the maximum is 200
that's what we gave the pick is five I'm going to change this to 10 okay five would
work this is casted as well okay so I drag when I'm dragging the network call is not happening so it is waiting for
me okay maybe I'm dragging okay actually this okay it's
just a debounce okay it's not it's not waiting for me to remove my mouse pointer from that it's just a debounce
that V setup we have a debounce for 400 millisecond okay when I'm doing this no network all is happening but when I
stop happens fine and I wanted to prove that there is caching going on here here now
we get the price per hour also with a less than 125 and I move this and come back to the
125 nothing happens but when I do the 130 we do the API call okay so I think you get the point like
debouncing debouncing and local caching I keep explaining that let's do the other ones it's going to be very similar
to the price per hour also you can see the dirty ones okay dirty Fields the third one is withd it's going
to be very similar to the price per hour so with get the control from the
use form context we get the value on changing state is dirty default values similar one maybe I think we should get
this become make this uh a component but fine we getting the Min ma min max from
the default values we passing the value and change as it is and um here we are going to add
feet okay and step is going to be two because the range is smaller here going I think
0 to 20 the width okay so the step is two fine and also we have the caching going on if I do this and get back to
the zero you don't do any network calls when I set that to 10 Network call happens when when I move this to get put
back to the 10 nothing happens Let's uh do the for the high height and uh length they're going to be
very similar to this width okay again we are getting the setting the height setting the control
getting the value and change from the field dir default Fields this component we passing the dirty and title to the
field header we setting the min max from the default values value non change from field and um same feed here step is two
same thing goes for the length also that's it we have one more thing to do which is a reset button here in the
use form context it also gives us this reset the form State I think there is the
reset okay I have already restructured it I I did not see that so let's create the
button under all our filters I'm going to place the a button in the reset I'm actually we have
to reset back to the default value right so this get values is an alternative for the watch and the use
watch we used it basically gives the values of the form
uh actually I'm confused why I added this I'm going to remove this for now and we will see the reset button in
action you can see there our uh pulsing dot is there that means that we have we have one field at least one field
dirty go back here not there we can also use the reset to reset
the pal State when I click this it resets so we have all the data set in the default
values okay yeah the point is we want to retain the location data and the time data right that's
why I had to also give the get values this this get values is going to have the date and location
filters and the form the default ones have the price so these are these are the things are going to be reset back to
the default values and we will retain the start and end time start end time and location
filters okay now I'm actually thinking I should only have the reset button when the when there are dirty Fields right so
the filter sidebar we already get this dirty Fields here and let's use this object do
values do length there are any dir Fields I'm going to display that or else the
resarch field won't be there okay we don't have a resarch field now and now we have the reset button on clicking it
it will disappear you can also install of just removing the button all together
you can also disable that the length is not Rudy then we will
disappear disable the button and now it looks like this also we have some hover animation going
on to fix this we can H we can add this enabled colon how colon the color so now we won't have
that H animation if the button is disabled but we we will have the hover if the button is
enabled and I think we have we have to add it to the other buttons as well okay that is the filter now we are
doing the we can filter the results now the the garage is
gone similarly the garage we don't have any slots that are bigger than 10 so that is
also every filter is working okay filter is working the resar button is working
and that is the advanced search filter using S react hook form we'll see in the next
one okay so in this section we are going to deal with the we're going to build the booking slot flow so basically we
are going to get the start and end date from here end time from the from the form the search garages form form
data and we are going to have another schema form schema here we're going to have a booking form inside here right so
we will transfer those information into this and we will let the user select the type of the plot and
also we have something a valy management section where people can optionally add valys for picking up dropping or both
let's get started with the schema inside the form schema going to create
a book slot. TSX so the form schema book slot it's going to be an object this is
going to have start date and end date start time and end time vehicle number and phone number
number okay so I I kept the validation to a really simple one here we are just checking for that the phone number has
to be at least one character but we can have more can further strengthen this validation and we are going to use we're
going to get the type of the slot because that garage can have multiple slot
types so that's it and then we going to have an internal a nested object here so this nested object is going to
have pickup info drop off info and different locations the Boolean and let's get the location
info location info is going to have lat long the distance We Will We Will calculate this distance at the time when
the user fix this location we calculate the distance and we will store um yeah also optionally we have
the notes I'm not sure if we will use in this project or I mean
um the notes is for the delivery notes in the in the food food applications right we have notes I added this in the
schema but uh I did not Implement that and this is the schema and as usual I'm also going to
infer the types using the Z infer anding the schema here we get back the type form type book
slot and also I'm going to have just like how we did in the search garages I'm going to have a further
validation here using the refine so schema. refine here we can actually pass a
function you might have you might remember we already used this a similar thing in here okay I'm going to reuse
this functions I'm going to copy this put inside the util TS we also have to export the problem here
is previously I kept the type of the data to the form type search garage but this
time it is different here this is form type books slot so I'm going to get only the
required data just start time for the E start time valid function and here I'm going to actually
pass an object because we have more than one argument so it's going to be confusing start time and the end
time we D structure that start time and
time those are the two functions first let's fix the search garages first I have to import
this and also typescript understood that the types don't match okay
so we can basically get the values from here and I will pass the start so the first one only
requires the start time the second one requires both fine similarly yep we can just copy
this paste here different different schema fine let's also import those
functions from the UIL okay so we have created the schema we also added this
custom validation using the zine I'm going to create this use form this we have been doing for a lot
for everything right so keep doing this we use use form we pass the type as a generic Al we use the
Zord resolver from the hook form resolver SL we pass the schema here and we get the form management hook that's
what we are doing but additionally I told you right we have to actually somehow pass the start time and
end time in the form search garage schema to the form book slot schema that's
why that's why I'm getting the default values here okay and also I'm going to create the use of the form provider book
slot is going to get the some children and the default
values fine now remember right now we have um what okay right now we are just
displaying the garage ID we will go back to the garage card garage marker this is the dialogue here I'm
going to use my provider F provider book slot not helping me I need to import it myself book
slot provider and here I'm going to create um we have to do two things one we have to pass the
default values the default values are going to come [Music]
from yeah we going to use the use watch use watch from the react hook form and we can Al we also have to pass
the type this is form search form type search garage we can get the end time
and the start time and we pass both the values as default values
here F so we need to have some [Music] children okay typescript is happy now
I'm going to create a component called book slot popup inside the organisms I'm going to create book plot popup do
TSX but this this thing gets the garage information first the garage information we the type we get from the search
garages query because this is exactly where we are using that book slot
popup also I have to pass the garage the garage information we get to the garage marker is named as marker I'm
passing it and okay I have at least return some
something here return n fine now now the typescript is Happy let's continue to build
here and just pasting the let's let's um use a pre- tag and uh we will display the whole
Jon gage. Gage two places when I click here so this is the garage
information okay we get the address have the available slots we have the car bicycle we have two slots for bicycle
one car we we don't have any images it's not verified so that's
information okay so we are inside so both you you may think like we are inside two form
providers we use hook form for managing the states the filters and so on and we have this form provider for the book
slot but the thing is the form provider exists inside the dialogue so basically we cannot
access we cannot access this use watch with this type inside this dialogue okay it's a different context
okay so here I'm going to start using the use form context okay so we just got the control
register handle submit uh set value errors everything for the book slot form and let's match the we have the set
value we have the start time and end time and I'm going to use a use effect
to sync those values um I think we don't have to do it we
already have pushed it I'm not I'm confused okay this is not
required let's create the form I'm going to have a flux box with some Gap text left with some
border with some background blur and so on let's create um I think we can delete
this get the form so in the top I'm going to have some
information about the verification verified State and the garage name need to add the display name from here
and also let's start the network let on the code gen the network and
uh fine I can get the display date display name from here we also have to create
the simple badge component let's let's do it the organism I'm going to put the
batch component so basically it's a Spam element span element and we have some
variants here basically we get the variant variant here and based on the classes we assign that okay that is the
badge component and we also have this Union types we cannot pass any other in string
other than what we have here and that that helps us really manage this let's import the badge
from the atoms now we get this information okay we had the garage name and the verified
or not verified state after that let's have the address
okay 1 2 three nework the style looks a bit weird but I'm going to just go just go with
that we can increase reduce the size and I'm going to have a simple carousal
here I I wrote a simple gel Auto Image changer that's what I'm going to call this caral autoimage
changer TSX we're going to get a string of IM the images duration
per minute aspect ratio or no Auto change let's export the
component I st store this current image index in use State and inside the use effect I'm
going to have a set interval use set interval to change this index so basically we know the length of the
images array right so basically I increment it and then I use this modular to reset it right if there are four
Images we want the index to be 0 to three when it goes to four it it it this will reset that index to back to zero so
that the image will keep changing keep Loop looping [Music]
through and if there are no images I'm going to just return no images with a photo cancel icon from the
Tabler icon icons that's it and I'm going to return if not if the images array is not empty
I'm going to return this so basically this is the image we're going to have we going to get the current image using the
current image index we are giving that and we going to have the arrows yeah so this is the dots we have
in the corosal right on clicking it also yeah so this will show what which
index of image is actually currently is showing and then we have two arrows the Chevron left and Chevron right on
clicking it we will update the indexes proper appropriately both both are buttons absolutely placed
buttons that is a simple carousal now let's go back back to the book slot popup and we will Implement
that after the address I'm having the Auto Image changer we are passing the images and
also if there are no images we are passing the Mt array the duration per image is 10 seconds this is in
milliseconds okay and the aspect ratio is aspect video here if we put a square one it
will take a lot of space so I'm having a landscape um
Dimension Moree aspect sorry landscape aspect and no Auto change wow
okay maybe that's distracting I think so the auto Chang is disabled the arrows will still show up and the customer can
navigate between other images right and if it auto changes in the booking slot it's going to be
distracting so I have disabled the no Auto change and I'm also going to create one
more component which is called date range booking in date range booking info so this
component we look at the start time end time it gets the difference it sets the duration the duration is the difference
okay and we have a flex box here first we have the start time we're going to we'll show the time format time with
the for with the larger text and font Bold and the date say will smaller with muted
color we need to create this uh functions let's create that we're going to use date FNS
inside the util I'm going to create a date we already have it let's add
the format date is going to use this format is going to come from the DAT FNS so let's
install that library inside the utils Library also we use the form time so the difference is the format we pass in this
is the format of the format date this format of the format time now let's import the data fness from the format
from the data fness and we also have to get the difference in
time okay so this we're going to use a switch case okay so we get the difference in
milliseconds and we will generate okay so based on the required unit we are returning the that
okay and the last one is get time units so this basically returns you just get the time I mean the time in
milliseconds the duration and we will return number of days hours minutes and the final time
string and also for this Pro for this we need to use the pluralize pluralize Library let also import the types type
definition for that and a Dev dependency okay uh I I did not add the TS config for this
project let's add that I'm going to copy some configurations from the forms Library maybe we don't want that but we
don't we want add the yes module interop true okay now
okay we have we have all these date manipulation functions we wrote a few things uh we got help from the data
Fess format basically this gets the start time and end time it gets the difference
in time and it sets the duration here and we have a flux box we have the start
time where the time will be bigger here and the this format time and format date and the date will be smaller we'll be
having an arrow here with the duration and uh the end time let's display
this the booking book plot after the auto changer I'm going to just place it passing the start time and the
end time now we can see this okay that that this is the component so it
automatically identified it the duration is 1 hour we can have I'm going to change the end end time now it says 2
hours and 4 minutes it also shows the time date time end time and the end date okay now let's
have our form information first one is selecting the slot type we already did this the radio group with the form
filter while selecting the types of forms so this is again we are doing controller okay so this time I'm using
the radio group group directly from the Headless UI basically we this is a controlled
component we going to pass only one type the last filter form we used types we could we were we were able to pass an
types inside an array but this time we're going to pass only one type this is for the booking
information so we get the control you pass the control to the controller we get the onchange and value here and in
the radio group we pass a on value on CH just works as it is and we get the available slots because we want to
display only the slot types available inside that garage then inside the radio this is the component sample
one okay [Music] so we wrap the entire thing with the
radio group and we will create radios okay those are the like options and I also we can we can Che
this is um a render prop but the radio
passes uh properties like checked autofocus disabled Focus however and based on this I'm changing
the style here I'm also rendering the slot price per hour price per hour and you also
rendering this different icons based on the slot types that is the radio group I'm also
giving the number of count we have now that is the
component okay I think we are passing the different color here yeah we don't have the b yellow
color we we have we will use the primary one okay when I select that is the component also I'm
going to listen to the values we already doing it let console log it so that we will know that we are actually writing
to the form management wow okay
so I actually found an found an interesting thing if I conso log these values I'm getting an infinite Loop
okay this is a bit weird for me but if I comment it down comment it out the infinite Loop stops okay I I
need to open this okay okay the infinite Loop stops that's uh something is new for me okay
I'm not changing the anything and I'm just putting a console log and uh I don't understand I don't know why that
happens let's keep moving our dialogue as plot type and I'm going to add the time also because people yes people use
this to search the St start time and end time they come here they will see the exact
same time from here but still I'm going to also have a start time and end time input boxes here
so that people can change their decisions later okay also I'm going to have a
custom error message here because a lot of time I come here I come over open the dialogue and I I forget to select any
types okay actually we can have the the other form elements to depend upon this value and we may Design This flow in
such a way that none of the other form elements show up until I select the type but I want to simplify that I I'm I'm
going to just have a a simple form error comp component which
is just some exclamation Circle and red gr text red text with an error okay just the exclamation Circle has a
red text and the error message is going to have the gray 800 900 if there is error basically if the title type is not
there we get the type from the use SWAT and if the type is not there I'm going to have this error set type
okay and I select it it goes away let's Also let's add the dates now that's the times start time and end time
we need to get the HTML input to Local Host ioso string basically I set this the type as
the date time local okay and these are not synced when I change this this de is not going we
don't have any connection there the connection happens only when we open the dialogue when you open the dialogue the
dates are all synced with what we had earlier and when I modify this it won't actually go back and modify this
okay that's how it is and then I'm going to get the phone number and the vehicle
number I'm going to have this two don't understand why do we want
this okay start time end time vehicle number phone number also we have to set this
type these are basic form elements we have seen a lot of times title error and we are using the register function to
register this phone number similar thing happening here we are making sure that the minimum is not
below the current time it cannot be in the past other than that we just have some
class names I think the class names they don't this this works fine as
well then I'm going to create simple cost title value it's going to get the title and
price and it will just display along with the dollar symol then we are going to you will need
this component title space dollar it's a flex box it's going to be a justify
between and um we will use this okay so we have our input elements
we have the date the duration the number and then we will have also create a valy management in the upcoming
section uh now we have to display the total value and then we will start working with our stripe payment button
and so on before that I'm we need I'm going to create a hook to to create price to create
prices so this is the type you're going to get the price per hour uh we we create a hook called use total
price hook I'm going to get the Val start time and end time okay so again I have some
difficulty importing the jsx that has a provider actually so I have to configure the jsx in the ud Library also the jss
is is equal to react jsx now the typ will error will go away so here we are going to have a
couple of three parking charge valid pickup charge and valid drop drop
charge first let's generate the parking charge so we have parking slots have uh charge price per hour so basically we
take the start time end time we calculate the difference in milliseconds we calculate the difference in hours
then we just calculate the price parking charge and we set that here difference in time comes from the
date here we already used this function in another place here right date range booking info we can we use the same
thing to create the difference and uh we display we display
here same function we are using to get the millisecond difference in millisecond and we are just
calculating that to the price and the second one second UC effect we are calculating the valy charge so this has
to be saved in a constant we already have a constants file in the util I'm going to place it here so this is a
charge I came up with okay so this is value charge per me that is $5 per
kilom and let's import that that's it so after the two use effects I'm going to
just return the parking charge Valley pickup charge and Valley charge drop off now in the book up hookup book slot
popup I'm going to use that hook okay let's also restructure the price per hour from the use
effect oh sorry so the price per effect comes from the garage value garage that is when the
properties. price per value oh okay so actually uh the slots have
the price per value it is we calculate that by going into all the available slots and we already have this this is
the picked type okay so we find inside the garage available SL array we are finding one
item based on the selected type and we are getting the price per hour from that and we get the total price object that
has the parking charge parking charge valy charge drop off Val charge pick pick up now we have all the required
stuff to display the the total price so after the after this going to we already
created this use cost title valueing the title parking valy pick up value drop off and I'm passing all the charges
there let's also calculate the total price after this I'm just counting
everything so let's look at the interface nothing is showing up why okay because we haven't set the type when I
click the type it is 17 days and uh 1 hour $10 if it's for the bike it's $3 and um
keep this St okay so it's 25 hours and it gets $75 it is
$250 okay so for the first iteration I'm going to just continue to work with the swipe and
payment and then we will come back here and we will create the valy setup till that it's not even showing
the valy cost because we don't have a valy okay so I have to Let's uh fix this finish this
booking yeah so we need to create the mutation okay actually we are going to do the booking through a rest API
Endo so we need to we need to manage the booking status ourself so here we are not going to use uper client so we won't
have the loading error States okay we have the
booking to select that we we see the parking charges
clicking okay so I have not we have not set up the on submit here on submit use the handle submit
that gives the data let's just console log it okay let's look at
that have the dates on clicking okay so the form did not submit because I have to enter the vehicle
number T 001 now there appears to be an error still
an error let's look at the errors oops
okay so I select this I we have the okay so again we got the infinity I have to set this Val form
schema as optional now let's try that select the type we have we already
have the give some vle number some phone number we already set that start time
and end time on clicking it we get the form data so the form is getting submitted now we have to collect this we
are going to hit the rest API okay so we will set the rest API in the back end and we will come back here
to continue with the righte payment so before we need to First install the stripe requirement
stripe package in the back end on ADD stripe in the models I'm going to create
a stripe module stripe. module. TS we're going to have a stripe
controller just like the resolver and then we will have the business Logic the code in the service file
also we are getting the booking service we adding the booking Service as a provider because we are going to
actually hit that when the payment is successful we are going to use the booking service to create the booking
this is the module let's compost the controller create the
controller let's create the controller and I'm going to decorate that with the controller decorator I'm going to call
this this stripe import the uh the controller from the next common and I'm going
to Let's also quickly create the stripe service
TS this is an injectable let's import the stripe create a public
public class property and in the Constructor I'm going to initialize the
stripe okay so you need the so you need to set up the stripe you create a stripe account and
you in the environment variables you have to create these envir variables right publishable key create
the copy that paste it here get the stripe key from your stripe account SEC and then the success key is going to be
3,000 SL stripe SL success we will be passing this checkout session ID to this stripe SL success route okay end point
and from that we will uh retrieve the session information and then we will if the session is information is valid then
we will actually go go ahead and create the booking also the cancel URL booking failed we will create the a simple page
in our front end 31 booking fail and that will render the failure message go ahead and do
this okay let's have a simple get route for the URL SL 3000 SL stripe Local Host
3000 strip okay so I have to add the stripe module in the app
module now can we get the hello stripe okay so that's working let's create other routes
we're going to have a post route that will create the session basically we're going to hit the
same thing with the post route let's get the create strip dto inside the strip I'm going to create
this D folder we going to have this uid total price object on the booking data we need to have
the total price type which is this parking charge valet charge drop of valet charge pick
up and the that is a dto this the information we are going to call when we hit the we are going to pause when we
hit the stripe post route get
this now we have to create a create stripe session in the stripe. service so we create this method we
destructure the total price object uid and the booking data now we can start the
session we get the Stripe from the here checkout. session. create I'm going to add the payment method as
card in the line items I'm going to the object this is an object object with three keys three properties like the
payment the parking charge valid pick up and valid drop charge I'm using U object or entries to convert
that into a key value pair of arrays first thing I'm going to filter that the price has to be greater than
zero because we can send a value charge of zero and we don't I don't want to show that in the payment
page and then I'm going to Loop through using a map I'm going to get the name and price
here and getting the quantity as one product data so I'm going to create the a say
the common I'm going to create a UIL file here put this title case so this thing
will just convert the string into a title case that all the beginning words the first letter of the beginning words
will be capitalized the currency is USD the unit amount of amount is price into
100 okay the mode is payment here we are going to set the success URL and the cancel URL
right just to remind you you have to you have to use this so that stripe will be
redirecting calling the access route along with the check out session ID and the session
ID and then I'm also going to set up the meta data this is the data which we will pass and in the success route we will
get this data and U we'll create the booking that's it so we create the session and then I'm going to
return the session. ID so that is the create session now it's almost ready the back end is
almost ready we can create a session we'll come back here to to handle this success one but before that I'm going to
go back to the book slot popup and we will set up our stripe in the front end so in the UI Library that's where we
have this components I'm going to install stripe at stripe SL stripe Js in the book slot popup in the on
submit we have the data that was getting submitted properly now I'm going to
create the booking data the object so we basically getting the okay
we need the U ID so this is a client component we have to mark this as a use Cent
and we can access the use session from the react um next O next o/ react so from this you can we can get
the session session. data do user. uid and this this U ID can be undefined as
well yeah fine now conditionally I'm going to add the value assignment okay so we have
seen the syntax I'm spreading it and only if the payment info is valid payment info and drop off info are valid
if both are valid I'm passing the information here and I'm spreading it if not we are going to just assign the
empty object or we can even do null when we destructure we will get
nothing okay so that's how we generate the booking data once we generate booking data I'm going
to manually I mean everything okay it's inside a program but still we are handling it ourselves right in the
inside with our logic handling the loading state so here we are going to call
create booking session we are going to generate the looking session let's uh create write that function and we'll
come back here I'm going to just keep the function under under the component the same
file total price we need to use the total price from the util SL
types okay so this is the type we are actually using in the back end also booking is coming from the generator one
create booking do input first let's just hit the rest API we just created right API URL SL stripe
a post that's we that we did here stripe controller we have a post route we can hit the create stripe session and we
also know what the DT is U ID total price object and booking data here basically we are hitting that rest
GPI using FH and I'm also passing the body by syn by um stringifying it once we get that we are going to
assign that get a session check out session I'm going to assign the
publishable key from the next public typ publishable key so you have to save your publishable key in the en enir
variables of the front end the back end requires both the secret key and the publishable key the
front end only requires the publishable key okay so let's load the stripe now load stripe comes
from the stripe package we installed um I don't know why I have let's do this so I'm I'm loading
the stripe there and then I'm going to redirect the checkout so this checkout remember this
returns back a session ID right so since we are handling with rest API we don't have any type safety we don't know what
this session is going to have it's any and then I'm just going to return the result fine now let's go back to the
onsubmit and uh we will continue the process here I'm calling this create booking session we have we can mark this
as async the booking data has a problem here lot instat
okay so we have to modify this okay um initially we have like um we added everything other than the
cre updated updated and ID so we need to modify this so I'm going to use the pick type I'm going to pick the customer ID
End Time start time and vehicle number and I'm also going to add the Okay so phone
number okay so we here we are also creating the slot right we need we also need the slot
information so I'm going to this is the custom create booking input okay so we're getting the customer
ready End Time start time vehicle number phone number garage ID type price per hour price per I mean total price price
per hour so I have updated that now we have to okay so
now the booking service is creating a problem since we updated the create dto it does not have the all the type
vehicle number phone number EXC right I am going to restructure the values here these are
the values we received from the dto first I'm going to make sure if the customer it could be it it is possible
that the customer is doing it for the first time probably we have to do something like this in the onboarding
page and after the user registers in the onboarding page we may have to um allow customer to create a
customer account in our database but um we have some rough edges in this
project so I'm making sure that we have the customer here or else I'm going to create a customer entry for the
uid so once the customer is created I'm going to generate a passcode I wrote a simple function for
this let's put that this util function util file it basically it's the random this and we will get the
floor it generates a generates a six digigit number that's what we going to use as a
passcode and then we get the date as uh time as string in the DT so we have to convert that into
dates then I'm going to we need to create a we need to find a slot right the user only mentioned the garage
ID I'm going to create a function get free slot which gets a garage ID start time end time and type here we are going
to look for find first okay this this query is going to return a lot of slots we going
to get just get the first item the conditions are it has to be from the same garage ID it has to be the type the
user mentioned with no bookings overlapped with the time that the customer
mentioned with these three checks we get the free get free plot
method let's go back here and continue the process after we manage get the start
start and end dates we're getting the free slot so this slot has this ID okay that's the picked
slot if there is no slot if something went wrong meanwhile when the user is booking someone else booked already then
we are going to return this error no slots found that's it now we can proceed to
create the booking I'm going to return this. promise of create booking I'm just
passing the end time start time vehicle number all this information other than the slot ID comes in
the dto and we find a free slot ID and we are just storing the ID here while
creating the booking that's it now it everything should be
working still the booking ID is complaining okay so the U ID it is expecting an a string
but here I'm having the uid that that is string or undefined
okay so if the uid is not TR the I'm going to just open an alert okay you are not
logged in and I'm going to return that now the error will go
away hper independ wow okay let's go here and see so this is uh interesting like uh
the type is is required in our schema here type is required we are not making
it optional everything is required by default and we are not making it optional if I make it optional then the
error makes sense like it's saying the slot type slash slot type Union undefined is not assignable
to type slot type so this when we get to this point this
data type is notot type here also the type is notot type yeah so I was actually getting the
type from here here yeah so type from the use watch okay got
it also everything else must come from the data not the watch watch
data fine everything is fine now let's do it I was actually trying that
from the logal h 3001 search let's do the
booking so car let's do the cycle one it's for 3
hours there is one more problem here minus 27 okay so even though we can select that
and it is giving the wrong value here but when I click it we get the validation there okay at least we cannot
submit the form with uh with this data I abdate that every 2 hours $6 I'm clicking the book
now we get to see this okay and uh let's give some user we have not yet created the
oh we have not created the success end point yet but
still I'm going to just give it a try United States of America fine
01 clicking it's processing it's successful and it's going here right 3,000 stripe SL success and the
session ID we are getting this now what I'm going to do we're going to set up the sess the success end point in
the tripe controller here we have to set up the success and inside that we will validate
the session information um do the booking and redirect the
URL all those things and we'll set up that and we'll come back here we we can just refresh this URL okay so that
everything will just go on the session ID will carry the cycle booking information okay let's build
it the controller I'm going to create this the success it's going to be it can be called like URL / strip / success
it's a get route and we can get the retrieve the success ID the session ID by this query
parameter Al we get the response if there is no session ID I'm I'm just going to throw an
error and I'm going to retrieve the session information that is happening by getting this
stripe class variable check out sessions. retrieve and passing the session ID I get from
here and from inside this session idea we can get the uid and booking data from the from the session.
metadata let's then um create the booking in Booking input I'm going to type this using the create booking
input I'm going to pass the booking data we received and then we can create the
booking using the booking service. create so we just wrote this service right that generates this passcode we
make sure that the plot is available all those things so once we finish the booking we
are going to redirect the bookings redirect UR create this inside the environment
variable of the back end this is where we are going to redirect to to the bookings
page okay so we have to import the response from the express okay so that we can do the rest
start redirect to the URL I have already saved it now we go back and um okay let's just
um create the a simple page for booking bookings SL page. TSX create a dummy page and then we will
come back here to to fetch all the bookings for the user and we will display that we will we
need we also need a bookings failed booking failed booking failed we will also quickly test
that page booking failed okay we have both these P dummy Pages now I'm going to Let's also look
at the database quickly so that we can see the data getting populated the booking
information right now we don't have any bookings okay going to just refresh this this session ID is going to
be still valid I'm
refreshing fine so we are directed to the bookings that means that the booking has happened price per hour three total
price six start time end time the vehicle number the phone number
um passcode status is booked the slot ID is two there is no value assignment here
and also I wanted to show one one more thing now when we go back click this we are going to see one
car and one cycle opening previously we had two cycles opened right I booked one and with this within this period there
is a overlapping booking here and hence the count has reduced this count has reduced
to from 2 to one okay let's quickly check the booking
failed okay so I click this the remaining yeah and also one more thing did you see the previously the cycle
price was three right because that is the minimum cycle slot available for the customer at that
time and that is booked now now the minimum price is $4 per hour and that is getting fetched now okay that is a
business logic that we are going for okay okay so I'm going to book that does do Cycles have vehicle numbers
I'm not sure I'm just going to give the give it a
number give it a phone number going to book this and then going to cancel the booking back now we get to
the booking failed page so here we can show some messages like well the booking has failed or something like that you
can book it again you can search for again you can have a search link all those things so we just
successfully did the booking we went through the payment the upcoming sections we will um we we
actually have to introduce the valy management section and we will set up the bookings page and so
on okay so um we have we can now do the booking without the valid assignment yeah we are going to do that
before that the pack the the parking slot I created exist in the water
so I'm going to go to the address and um so I manually created this so basically we just have to H in minus 74 we have
to increment that maybe a bit let's increment up further
okay so that's our parking flat and uh also I forgot to add the loader on the search
page two garages here we have the loading and we are we have to manage
that let's create a component called loader I'm going to create that inside the molecules
basically I'm going to Icon rotate clockwise okay so we I'm exporting two
two two components from here one is just the loader which is the icon with the animate Spin and the other one is um
with along with the panel the alert panel alert section is again just
[Music] some okay box with a fixed height with a background with some Flex box to the
children all those things this a layout component we can also optionally we can
pass the title and the body has a fixed height has a BG white FL flux call with item
Center item Center and justify Center Height full okay so when it's
loading so we have to keep that inside the show garages when it is loading if it's loading I'm going to use a panel on
the map panel the position is going to be Center bottom and I'm just going to add the loader which is the icon with
the animate spin okay so it's happening quickly we are not seeing that also we
have I'm going to add um another condition here if there are no
results I'm going to return early I'm just going to use an icon info
Circle along with the message no parking slots available if the data. search garages. length is zero
let's import that from that Tabler icons now when I move somewhere else okay
now when there are no markers available we will be showing this error message and also there is a loader which quickly
happens okay yeah so with that let's move on to building managing our
Val assignment in the on submit in the book slot popup I have already added this
information okay even though we already we also have the value assignment information stored in
the EM also here right we already have that we are already sending that but now we just have to get the
value from the user so in this form we're going to have a section here with a map with draggable markers
where users can customers can uh pick the pickup and U Mark the pickup and drop off
locations okay so first we have to update the API this is the booking input we have to now pass the valy assignment
so I'm going to create going to go to the create value assignment input I'm going to create a
new one here okay since the default number here number scalar mode is
float I don't have to add this right so this is what we are going to get it's just the
location pick a lat long return L return lat long maybe I should call this drop off flat long there is some
inconsistency in the naming but I'm going to just move on yeah so we have updated the create
booking input next we have to update the booking service the booking service we are going
to restructure the value assignment and when we create the booking
here I'm going to again use that spread syntax so if the value
assignment is true I need to add this object value assignment create and then I'm going to
pass the value assignment object which I got if not I'm going
to you can do just do null so basically when you destructure n you will get nothing but when destructure this object
you're going to basically add this also see we can do this right assignment
create this is exactly what we are doing in the create I'm just passing that the object we we
get but we want to add this only if the value assment is is valid the object is valid that's why we have we use this way
of adding that back end is ready now let's move on to create the a component called
directions so this directions is responsible for getting An Origin destination lat long lat long and then
we will use the mapbox API to create a a path directions just like Google directions uh it generates that and we
will render that in a map inside the organism I'm going to create a directions.
TSX this is going to get origin destination Source ID so this is um something
the react map GS source and layer tags require it's like a key property when you Loop through and when we create
items we have to pass we have to try to pass unique Source IDs I think we have the latlong okay I'm
going to create this lat long in the types in our util we have a types file here I'm going to create this lat long
which is flat number long number lat long tub yes number number is just an array with two
items let's import that let's store the coordinates and set coordinates using U State we also need
to import the lat long tub from the types we going to get the previous reference
inside a reference so that it won't trigger reenders I'm also going to debounce the
original and U the dist destination so that when the person moves the marker we will take
some time uh which is by I think by default it is th000 maybe let's reduce it to 400
milliseconds so we debounce that and inside the U effect we are going to look for the
changes in or in origin debound and the destination debound if one of them are not set we
for a direction to work we want both the origin destination we need two points to create a direction if one of them is not
there I'm just going to set the set coordinates set the coordinates to an Mt array and this I'm and just I'm
returning I'm ending the use effect there if not when we have both the origin debound and
destination debound time basically I'm hitting the ap. mapbox directions ver five mapbox walking so
that's by that's what I'm going with you can we can further tweak it actually so we have different vehicle types like
cycle heavy car right bike so we can actually get the type and we can pass it here but I have I'm just simplifying the
process that would be the right way to do actually based on the vehicle we have to actually pass different in the method
of um directions and I'm passing the latitude longitude of the origin and destination I'm also
passing the access token and steps yes I need steps and also over viiew
simplified I'm going to use an if okay immediately invoked function execution I think basically you can create a yesing
function like this and you can execute it okay and inside that you can
do synchronous operations that's how you can do uh you can use a inside a use effect so we get
the response get the data back and we get the
coordinates so I was like going through the documentation and doing a lot of trial and error looking at the data
consoling log and then I came up with this okay l. routes legs do steps Dot and we map
through that and then you go through manuver and then I get this okay I was not so I took a lot of a bit of trial
and error to know where the how how to get that particular information which we want for this
case we got the coordinates I'm setting the coordinates and I'm also getting the distance from the
data remember first we have for getting the coordinates we did all these things and for getting the distance uh I'm
going I'm doing this we already have the the distance stored in the US basically I'm making
sure if it's different if it's different I'm setting the new
distance okay that's it and then I'm going to create a line string a sequence of line
string so after the use effect I'm going to create this using an use memo so only when the coordinate
changes we will just return we will generate this object it's a feature with the geometry of line string
and I'm passing the coordinate okay that is going to draw the directions for us
okay and finally I'm going to return a source source from the react map GL and then a
layer again from the map G since The Source I have to pass the
source ID as the ID and type as geojson and data is data
one and then we will create the layer so here I need to pass the same ID The Source
ID type is null here have a line Source I'm going to give a name here called my
data and then I'm going to set the line color and the line withd using the paint option okay
basically we are just creating a layer I'm I'm generating this uh coordinates into a l line string geometry and I'm
passing that inside a layer I'm also modifying the paint modifying the line color and the width using the paint
and in order to satisfy the typescript I'm going to set this as as const so we cannot pass any other value
there other than this particular string okay it's not just a string but a feature and line string now typescript
is Happy the directions is completed right so we get the origin destination and the
set distance a call back function to to return um to set the distances distance between the two points that that is a
calculat distance that's not just a distance between two lat long two coordinates it's the distance that the
map box returned this using the directions now let's create a manage
value component which is going to use this directions component
I'm going to create a component inside organism manage val. TSX so this is also going to get the
garage information from the search garages query first I'm going to have a date
called use show wet going to get the lat long from the garage value and if there are no G no
value of the garage that that must there must be something wrong right and also I forgot to add that react toasttify so
let's go and uh create that install that and uh we will set that up so we have been
using the alert alert for now which is not a bad thing but a toast is much more modern in the UI I'm going to install
the react postify package and inside the molecules I'm going to create a toast file.
TSX I'm going to import the toast container toast and slide I'm going to export the toast
container with the transition of slide I think we can also have other transition like
bounce flip I think so so you can um and go through the documentation of
react toasttify to see what other transitions they have and you can use them I'm also re-exporting the toast
function this is what we will use to actually create the toast okay
and fine so in the layout I'm going to add this as a the body I'm going to add the toast
container is it is easy to set up inside the molecules to
tost I'm going to import the tost [Music] container and
now we can call this toast function to create that toast message from anywhere we want so I'm going to import that from
the molecules you can directly import that it does not make any sense but any difference but
[Music] um okay yeah we need to get the set
value this is what we will set value using the use form context so we are still inside the
provider the form provider for that particular booking book slot EMA we get the this this is what we will
use to set the locations the pickup locations drop off locations and also we need to listen to the value information
using the use watch use watch from the react hook form that's it
so we're going to have a simple box with with some padding and um some BG gray very
light going to have a title valot some paragraph text or Val with Will whisky your car away to its reserved
spot and bring it back when you are ready it's like magic but with cars something like
that and also we need a switch component I'm going to uh modify the
switch from The Headless UI go to the items we going to create a switch
component import the switch as H UI switch because I'm exporting that in the name of switch is going to get the label
children checked on change class name I think the Headless UI wait a minute let's let's look at the
look at what code they have so this is the component this is the the code sample
switch okay actually it looks much simpler okay yeah so U when I buil this project
U was not in version [Music] two now it looks a lot simpler actually
I'm going to quickly just use this as an example Hy switch and I'm going to pass the check
down on on change and uh switch group do we have a switch
label okay so yeah switch label is again duplicated I'm just going to have
a div here and U use the label that we got let's give some class name to the
label this is the component let's TR let's use that and uh see how it
looks okay so this switch statement will be managed with the use show valy the state we store here and on change we see
the value and if it's false we are going to set the value to undefined okay the whole the value in the sense let's go
quickly go look at the book slot here this whole value like this is
optional so we will just nullify that when the person clicks that show valid disables the show Val then we will just
set undefined to this whole part in the form data about these things and if not we
are going to get the lat long from the garage and we will set that to the pickup and drop off location so when the
user enables the show valy we're going to create two markers in above the garage
itself okay and then the user will drag from that garage to wherever point they want that's the manage Val I'm going to
quickly see how the switch component
looks let's import the manage valets valys and before the
total cost total price I'm going to use that let's have a look at that know to solve manage
why okay it's Val is right now it should work here is our thing okay
[Music] the there is a okay
so the switch button is not working properly I'm going to copy my earlier the switch component from here and
U I'll just replace it there are a few few things which are deprecated are
defined let's define that oops fine and uh the label is depricated use label instead of okay
let's use the label from The Headless UI fine others are looking good going
let's look at the switch component okay so this is the switch component looks
good okay let's proceed with the manage valy
component after the switch I'm going to see if the value is true so the show value is set up we are
going to display a map with directions and and everything I'm going to have one more a
description want your code delivered somewhere else no problem choose a different drop off location drop off
point and we will make sure your ride is there waiting for you so I'm going to have one more switch component so this
will make sure that um this is to enable users to select two different pick of pickup and drop off
points we have another one here the checked one is the valy we are getting from the form State itself val.
different locations and on change when it changes I'm going to just set that value and
also we have to update the drop off info based on this state yeah so when I select it this pack
this uh we see we see the that description and add a different drop off location
this will actually manipulate the form data and uh it will reflect in the map the the markers location in the map we
are going to create after that I'm going to create a map let's wrap the entire thing with
another div let's have the map here we're going to have the initial
position initial view state is going to be in the lat long the lat long is the location of the
garage and we going to have the fixed Zoom of 13 and I'm basically passing the height as 50 VH so I want a landscape
Moree first I'm going to have the marker for the garage this is not draggable okay I need to import the
map also the parking icon this is the garage location garage marker and
then we will create a few more markers to display a draggable markers for the pickup and drop of
locations okay first let's deal with the inside the map first let's deal with the pickup info so if the pickup info is
valid there is a location there I'm going to have a
fragment inside here we're going to use a marker
so getting the location of the pickup location latitude longitude latitude longitude it it is dra dragable on end
I'm going to set the new location to the valid pickup dolat long if the different location is not
set right that is a Boolean if the user does not want different locations for the pickup and drop I also have to set
the same location to the drop off also that is the first Mark the first marker let's create the content of the
marker we're going to use a user icon because this is is what that is the pick up location icons
that is the first one let's have look at that need valet yes that is the map and you can see the marker here which is
dragable when I drop off somewhere oh I have to add the directions also
that's why I added this fragment to have the marker and also the directions component
after the marker I'm going to put this directions I'm passing pickup route just a a unique
string and the origin is going to be lat long which is location of the garage the destination is the valley.
pickup actually this thing does not have to be optional because we are already checking that
here so the destination is the pickup info the location stored in the pi pick up info the set distance is I'm I'm
passing the set value from the use form context and we get back the distance I'm setting that so that is
the we are dealing with one thing now pick up only yes we need valy we need this thing
is not it there because we only have one okay that is the directions and it has like 400 milliseconds
delay and we see the directions so now we have to add the other um marker which is for the drop
off this going to be very similar I'm going to just copy this paste
it drop off lat long drop off lat lat long and this is not going to be optional I
mean undefined it's going to be trly the value here it's going to be a bit different on drag we just have to set
the we don't have to set the yeah we don't have to set the pick up pickup location it is just going to
be drop off again we have to set this the span to just have drop off last time
there is a need that if the if the different location is set up I need to actually give both these things pick up
and drop off but this time this this is simple we are only dealing with the drop off and let's also rename the source
ID and the flat long and the distance yeah think that's
all okay one more thing we also have to make sure that the different location is selected
okay only if the user wants different locations we are going to show that now we have like two
markers overlapped on each other so we have to do it individually the idea is
I think we should also have the zoom buttons inside the map going to enable create a
panel and default Zoom controls the panel is going to go in the right
center okay now we have this buttons I need a different location I'm
going to set the drop off here and uh pick up needs to happen here so the story is like the user is going to drop
the it is it starts maybe tomorrow at u 2 p.m. 2:42 p.m. tomorrow 242 p.m. come here to pick my vehicle
okay it's a car okay so and I want it to be delivered
on 16th 1 a.m. so it is 1 day and 11 hours on on 16th 142 a.m. I want the vehicle to be
dropped off at this location so the customer actually won't even look at the won't even go to the
garage that is the idea you can update the location if you want okay and also we are looking at the
um charges it is 1 hour and 1 day and 11 hours which is 35 hours $350 for the parking for the value pickup charge is
$19 and the drop off if is 22 and the total is $391 let's enter
the vehicle number and the phone number let's book and also in the stripe page also we can
see the parking Char parking charge valy charge and drop off charge separately
okay fine let's do the payment also remember we have I think we have one booking here and that booking
did not have any value assignment let's do the booking okay the booking is done and we will be
read okay we are we are redirected to the bookings page which is empty for now we
will create so we are seeing the second booking here they have the total price price per
hour the vehicle number phone number passcode status is in booked we have U slot one this is a car slot and we have
the value assignment here this is the pickup location pickup lat long return latl
and the pick a valy idea and return valy IDE are not set so these things will be we will be set we will set these things
from from the valy application it's is a different application fine so that's how we do the
valy management and the upcoming sections we will uh start to create this bookings we will create this bookings
application and then booking page and then we will move to the manager value application admin application
okay so we are actually working uh we have to finish this booking Pages booking page bookings page for the user
but I'm going to continue with uh creating the manager application which is going to we are going to run that on
Local Host 3002 we will set that project we will have um some condition in the homepage
that only managers can proceed so all that's what we I'm going to work on now basically from the inside the apps I'm
going to create a new next application called Web hyund manager
okay going to enable typescript es Lin Tailwind SRC app router and no for the customizing import default import
areas fine I'm going to rename the package to autospace SL web manager
right now I have to set up the okay first let's run it I'm going to mention the port number as
3002 and I'm going to run the application so it runs on port number 3002
okay let's clean up in the page going to clean everything
hellow and I'm going to delete the globals do CSS remember we did the we did similar thing here also we actually
have one CSS file which is inside the UI Library so that's what I'm going to put inside the
layout and also in the TS config in the Tailwind config so we have all our source of
Truth for about the design inside the UI and um/ T.C config I'm going to just copy
that and in the Tailwind config I'm going to replace the config with
that now I have to I have to delete this fine now we have the hello and the our
um styles will also work here for example we can have the have some padding and uh background of
primary we are going to get this okay so same designs different
applications let's also add the now bar and uh everything into the managers layout page so there the menus
are going to be different I'm going to get this from here we're going to have two menus for
creating a garage and um or managing the valys similarly I'm going to just copy
paste all of the uplo provider and so on copy everything this is I'm
just using the same layout file okay with the different menu items that's the only
difference and I'm actually we also have to manage this metadata right now it is saying create
next app here the title Let's uh change that to autospace manager here it is
autospace and now it now it says autospace manager okay now we have the nowar and
everything now let's add the Au Pages it's not going to be any different it's the same uh register with
the same layouts the same um components for the out layout on the register form nothing changes
here I added one more thing I have to also add this token and next to other routes okay we already went through that
in detail the last video the register Pages here then login Pages
here technically there is the same database okay we have the same database for these applications and
people can actually login login fail why also I'm seeing this optional for the first time password optional
why for some reason I okay maybe I was testing playing around okay that is gone now what I'm
thinking the problem is I miss an environment variable in the manager application that's what I'm guessing
okay so I'm going to create a EnV file the root of the manager application and I'm going to create this environment
variables API URL is still 3,000 next Au URL is 3002 for this application next OD secret is secret okay so I'm this is
local development so when you push to production you have to be careful mindful about having a really
complex strong secret so that then I'm going to try to log in with the with the user that I
created in the previous application okay I'm logged in you can see the the image is missing because I
have to populate the public that is we don't have user image this is the fall bag image I'm going to copy that into
the public public directory and now when you refresh you will see that image maybe I should work on this this gu is
um that is the basic application that is ready now let's work on we're going to work on something called a render props
we're going to have a component so let's first create a component called is logged in that is
the component name so the is logged in is going to block is going to have render a fallback
component when the user is not logged in if the user is logged in it will continue to render the
children let's go to the organism in the UI Library I'm going to create that is logged in.
TSX okay this is the props I'm going to first create the the
render prop child the children is going to be either a react node from the react or the react
prop child which we created here which is a function which gives a uid okay you will see it in action in a
bit inside the component I'm going to use the U session from the next o so if the status
is loading okay you can see these three statuses authenticated unauthenticated
loading if it is loading I'm going to just use the loader panel which we created in the last
session okay next if the data do user. uid okay one more
thing we will face a error about this uid okay remember that typescript is going to
comply and inside that so this this condition is the user is not actually logged in but we are also I want to we
can have a fixed uh component here some js we can return some GSX saying that wow you're not logged in something but I
am getting a property here okay it is optional I'm going to make sure that we render that
component if the consumer of this component passes that okay else I'm going to have the default jsx using the
alert section alert section it is you're not logged in and we are just giving the
link for loging login page so we have handled the not logged in state now we can put
proceed I'm going to return a fragment and inside the fragment I'm going to test the type of the children
past the type of the children is function and this if this is a function if that is the children which got passed
to this is logged in then I have to oh I have to put this inside the only
braces okay if the children is function I'm going to pass the children
and pass the uid the children is the function here right basically we are invoking the
children like this okay we can do that when we invoke the children this uid will get passed to
here okay so I'm going to keep the assertion there as render props and this is the is logged in so how to use that
in the page of the manager I'm going to use
that is logged in now let's just test that okay we can do this
here I'm going to get the uid and I'm going to render the uid let's
see so I have to set mark this as a client component okay I think um we also have
to mark the page uh use client also the manager homepage is not static or it's not static so it's it's
going to have a data dependent upon who is accessing so that's also a c component now you can
get the uid there how cool is that this uid is passed by the is logged in component and we are rendering that
in the children fine so I have a similar component
again actually I don't I don't want to get the uid here but I just wanted to show you the example that we can
actually pass properties like this into a component into the children okay so I'm going to create a
similar component called is manager so just like how we use the use session to get the user information in
the use use manager component I'm going to hit the back end to see if the manager has a
company so first let's go to the company resolvers I'm going to create a
query called this is going to be authenticated I'm going to write a query called my
company this is going to return a company sorry this is at
query my company we're not going to get any arguments but we're going to get
the get user so when you use this all authenticated you can get access to the authenticated user information that is
going to be of type you get user type here I'm going to just return this do primma dot you can also use the company
service let's use that company service do find one and I'm going to pass the ID from the user user user. ID so this ID
gets oh I'm sorry actually yeah so this ID is received from the header so it is
reliable the header the token we did everything in the O guard right okay so the company service find
one is not that um is a bit constrained so I'm going to directly use the Prisma
client here so this do Prisma do company. find first I'm going to pass
the manager where managers Su uid is the user. uid we we are going
to return a a company okay so back and the API is ready uh now let's create
the generate the code for this okay so my company I'm getting the so actually you can use the
Explorer follow to create this query to compost this
query basically in the my company I'm getting the ID inside the garages I'm getting a few things so that's how I
compose you don't have to pass any argument any variables this in this query Also let's run the
Cen in the network library that's it now here let's import the generated code from the gql do/
generat I'm going to get the my company's company document that's
it so the manager is just going to get the um base component and I'm going to import the
use Query from the polo client I'm going to call get
that get the data if it is loading I'm going to render a loader panel loading company if there is data if there is no
data I'm going to return just a alert section with saying that you don't have a company
yet so here we will come back to have a button uh that will probably that will open a dialogue that get some
information for the manager to create a company and then it will create a company if everything is successful we
are going to allow to we will show the children so this is a bit simpler than the is logged in component okay here we
are doing a lot more I wanted to show this this could be this U could be a useful pattern some situations this is a
simpler one we are doing this and uh we are rendering different things based on the this query
result fine now let's go to go back to the manager page and is logged in I'm not actually we don't want the uid into
the component also just wanted to show you that low
manager fine now when I go back to the manager page this should not happen
actually something is wrong okay so this guy is already a manager okay so got
it the dummy uh garages we created right so I used this account to create that let's uh change
that I'm going to Let's register from beginning okay why
confusion I'm not logging so that this is the is logged in page okay one more thing I wanted to do in the layout page
I'm going to add some add some background color which is a very light P Gray okay so I like this
when you have um White cards on top of it top of a mildly gray background I like the style I'm going to do the same
thing for the for this one also for the user okay
yep we will come back actually I I left the background uh transparent for the form but actually we will have some 3D
scene as the background in the login page for the login form okay so here we are I'm going to
register a new one with a simple the email of manager email manager
guy registered redirected to the homepage now I'm getting this thing okay you
don't have a company yet so that error message is coming from the is manager component okay this is the error message
so here we have to um create a dialogue on clicking it it opens a dialogue and we will do the company creation inside
the dialogue the manager guy is also showing up I ask you to remember that we will
get an error about that uh uid from the use session data that happened in the
page thing in the is logged in okay so we are getting that the problem is we modified the type
definition of the session information using the using this okay so it had this ID I
did not like this I wanted to make the ID to into uid because that's what I call we call in the back end I modified
it in the front end I imported that type definition like this okay this is okay this is the UI
Library the web also the app / web also I I included I added this so basically you have to just copy this and paste it
in the manager application and now when you do the Yon validate you're going to not get that
error okay okay now let's continue with the creating the company from here before
that we have to set up the so this is like we are combining two mutations okay we are making we are passing we are
going to pass the manager ID along to um the create to the create company
mutation right now we are only getting the display name and the description of the
company I'm going to modify this okay so I'm getting the manager ID and the manager display name along with
maybe let's just use the pck type it is a bit confusing for me I'm going to pick the display name that is the display
name of the company and the description so display name description manager ID and the manager display name
those are the things we are going to get in the company create input and then we will create the we already have created
the manager right okay so this is for creating the company only and we get the manager and we just add that manager in
the array of managers for that company this is done let's move on to the resolver in the
service we are getting the reading all this information yeah so we don't want the
manager name sorry because the manager is already created here and the manager has a name here which is manager
guy so okay there was a small mistake we get the manager ID and in the resolver the service first we check if the
manager already has an account uh is already assigned into another okay first check is if the ma if
the manager has a manager account so actually this part needs some
clarifications if there is no manager we're going to return a bad request
exception no manage account found okay and then if manager. company do
company company ID this is you need to await this I'm sorry if the manager company
dot Company ID that means that the manager is already part of another company so we cannot that person cannot
create a create a company bad request exception manager is already part of another
company yeah so if everything is fine we are just creating a company passing the description display name and the manager
ID that is we have updated that now let's create that mutation through this I'm going to
create go to the mutation create company um just the ID this has all the three information
that is actually enough going to the input file for the code gen pasting that now the network is running okay so it
created the create company in document that's all about the back end and the Coden now let's focus on the
UI first I'm going to create a f schema let's call this create company.
TSX yes is enough because we are not going to have um provider component here I'm importing the use effect from the
react hook form Z from the zard and the zard resolver from the resolver zard and the
schema schema create company we're going to have the company name first so so we make that mandatory by making it minimum
of one adding that validation that the string has to have at least one
character and the manager ID which is again Z string and it needs to be not
null there used to be um conditions functions like not non empty and so on but they were replicated so we have to
follow this rout message manager ID is required fine so that is a schema I'm
going to infer the type from the schema using the Z infer type of I'm passing the schema
name then I'm just going to create the use form use form create company use form create company I'm
passing the type as a general the resolver I'm using the Z resolver anding the schema
here just for the naming convention I think all the schema starts with form schema so I'm going to add
that form schema create company and then we will rename this so that is the form schema and the use form
hook next time I'm going to create an organism a component called create company.
TSX export const create company I'm going to import the form the use form hook use
create use form create company let's import
that use form create company and get the register handle submit form state where set value
Etc so know before continuing I think we already have the dialogue
component right let's set that up so we manage the open close States for the dialogue and inside the div let's return
a div we're going to have a button first that that will open the dialogue this is just
a default primary button then I'm going to have the dialogue
here right now let's just have create company that is a content of the dialogue going import that from the
atoms let's also import the use it now let's use it in the page here instead of this I'm going
to oops actually this is inside the use manager okay here we have to use the create
company take that remove that too now we get to [Music]
see okay so we get to see that and on clicking it we it opens a dialogue okay so now let's let's
continue working with the create company dialogue first we need to have the form first let's uh get the company name
using the HTML label and the HTML input this gets the company name and also the register is fly type save so we
can only assign the properties that we have mentioned in the IMA similarly I'm going to also add
the HTML text area I think I have we have not created the HTML text area I'm going to create this
HTML fixed area. TSX again we just have some opinionated Styles here and then I'm just forwarding
the ref this is what we did for the other components as well the label is a bit more complex that we are getting
this optional Boolean getting a title children and the form error and so on but
yeah text area is a bit simpler we have created these two now now I want to talk about one one thing
like in the comp in the the com the company resolver here we are actually getting
the manager ID right but actually we can get the manager ID from
the so here how how do we get the manager ID from the token right this is the decoder information of the token we
get that from through this but but here I wanted to I wanted the user to send the manager ID so that if an admin wants
to create an account for a manager the admin can do that if I just play on the header token when the admin tries to
create a manager account for some other guy the account will be created for the admin right the admin's U ID will be
there in the token so that's why we get the manager ID and also we have to do some checks
here here so we get the manager ID here we will make sure there is a function here called Low R level
permission yeah this lower check R level permission what it does is it gets this this is a
uh decoded information from the token this is the requested ID okay if the admin is there we are going to bypass we
don't just U bypass that admin can bypass this function so we have to get this this is
all authenticated we have to get the decoded information from the token and then we going to pass
this and the manager ID okay if a non-admin user accesses this token access this
mutation the ID inside the user and the manager ID are going to be same if the admin accesses it admin calls this
mutation the IDS are going to be different but the request is an ID so that request will get bypassed that is
that's what happening here let's focus on the create company we got this but I'm not going to ask the user to type
the uid right so we need to intelligently populate that because we know that this is the ID
on session equal to use session you session comes from next
Au react okay so the uid here is session do data. user.
uid okay what I'm going to do going to use a UC effect
and when we get the uid there I'm going to use this set value only if the uid is valid I'm going to use a set
value so everything is typed okay and I'm going to pass a u ID there
now I will make the other one read only okay we'll do that I'm just going to copy the first
one and this time it is it is manager ID okay manager ID is manager
ID this is manager ID and I'm going to make this read only okay now let's look at the so this is
already is is populated but the user cannot modify that okay um
okay you can either do this or you can just remove this from the form schema you can remove the element and in the on
submit here you can add the manager ID directly to the mutation but this is more transparent the user can make sure
that wow this is my ID it is here and uh yeah this increases some transparency
that's it then let's just add a button create company the button type is going to be
submit that's it let's just do submit because the user already create
clicks this create company and uh submit makes sense here okay so now let's uh do the
mutation we get the use mutation from the Poo client and I'm going to pass that create
company document that is going to give back an array the first one is going to be a mutation mutate function the second
one will have the this loading data and so on let's ass the loading to the button
loading equals loading okay so let's use this create company in the
onsubmit the unsubmit we already get the data here we can also destructure it but that is fine we can simply pass the pass
that let's make it asynchronous because we are going to do an asynchronous operation await create
company the variables I'm going to just pass the data not working
it's okay now yeah now it's working and um we also need to refetch that right when I submit this when the
mutation is successful I want the data behind this data to be refed and refreshed right let's do that refetch
queries and then we can we can I also added this plugin right code gen plugin called named operations do query do my
company now everything should work let's try that the parking
company working company description I'm going to use y to write
that okay so I have uh a randomly came up with this name Big Apple Parking Solutions
description Big Apple Parking Solutions Solutions is your trusted partner for affordable and convenient parking in the
heart of the New York City okay um let's submit before that I'm
also I I want to see the network tab submit oops
errors create G invalid value company name description what is wrong did you
[Music] mean display name oh okay but I did not get that get any
error in the when I'm doing this I'm not getting any
error okay so I have the company name this is actually this should be display name but I have that as a company
name display name description manager ID but in the forms that create company I have the company name description so
this has to be display name but nowhere I got the type error so in the code gen also this is the create company
document okay so Coden has the right um display name so actually I expect a compile a
typescript error types typescript error here here we get the company name description name and manager ID but the
company input requires the display name so previously it was not complaining okay I'm a bit confused
there okay so basically I'm uh um I'm going to go back and I'm going to rename this to display
name because the form the name says it's create company so display name the name should belong to the company now we get
type error here right um let's rename everything now the mutation has to
work Big Apple paring Solutions this is read only forbidden
resource okay the create Company the company resolver
has can be accessed by the manager but this guy is a manager let's
just fine so actually we are combining both company creation and manager Creation with in that one mutation so
why have to here I also have to create a manager let's do it here so clearly this blow needs to be um
we have we have to probably should do something like is loged in is manager as company so we can have this those three
nested checks and we may actually create a manager in the Second Step okay it could be like onboarding process
based on the stage we will render a different page but here I'm going to simplify the
process so basically I'm going to get the in the create company I'm also going to get the manager
name manag your name maybe it's optional and in the create company
going to have one more field here this is manager name but this is not read only because
the manager has already already has a name in the user and the manager may want to use a
different name for the manager account this is the manager
name fine and here here I'm also going to get the display the name here so this is the
name of the logged in user call this manager name fine and
here H value manager name name Yes actually manager
I have mention this as optional what okay
null so optional will make the string string um or optional we also have one more thing called
nullable now this this is happy right let's look at the dialogue now now we can see the manager
name that's not read only they can update that the manager ID is read only and um okay now in the company
resolver I'm going to we have to change this I'm going to make it anybody can create a company anybody logged in can
create a company that is uh that's what we are going with now as as I told you this flow has to be for the are
strengthened um it could be an onboarding process with with more calls to the back end and in an actual product
in an actual company we may also have to verify that that means that a company representative has to give some input do
some mutation from their end so that the manager can proceed from the M create manager page to create company page all
those things but I have simp I'm simplifying this process now let's go to the service first first
step we are we know that the manager in this flow the current flow we know that we don't have a manager so we are going
to straight away create the manager we can also get the manager name from here okay we are going we we need to
update the D2 also so we get the manager ID manager name we get the manager name here and we are going to create the
manager okay for this we need to pass the uid is manager ID and the name display name is
manager name that's it so we have created the company and
then actually we can do in one go like here we can create the
manager pass a display name is manager name and the uid is manager U ID manager ID we don't want anything here we can
just delete them okay now let's try the mutation Big Apple Parking
Solutions okay this is read only this is manager name good
now it is successful and hence we got this hello manager uh
message you can see that the newly created companies here we have created the
manager this guy the manager also has this company the Big Apple Parking Solutions
fine okay so here let's uh list the garages that belong to the manager and also we will have buttons to um to this
create garage page okay I'm going to create a new component called list garages inside the
organisms going to create G list garages. TSX the list garages is going to get the
company company ID basically the east manager I decided to actually make this use the render
prop child concept here the child can be render child which is
here this a function right we exactly did this in the is logged in component it could be this or a simple
render react node now everything is same but when we return the children I'm going to return
like this okay and
um we get the company ID here instead of this let's return the my company. ID okay so that is a change I did and
that's how we pass the company ID here let's do it in the manager page here we are going to use
the we get the company ID here from the East manager component and then we will just pass the company ID like
this we'll finish the list garages and we will come back here okay so we're going to do some page
ination I'm going to create a simple component called show data okay that is going to
get the error message data loading State and that component is also going to manage the pagination
we're going to use the pagination component from the mui
so we'll keep it here and uh so we will create that show data component and we'll come back to the
list garages show data. TSX this is the property this is the um property type
we're going to get the error as a string it's optional loading should also be optional the for
page ination I'm going to get the set skip take skip skip take result count total count okay all these information
are required to do the page Nation so we are going to use the page Nation from the material
UI muui page Nation okay so this is the component we are going to
use let's get the props err loading page generation title children
and I'm going to destructure the set set skip set take take result count and total count from
the page Nation function here handle change page change we going to get the IM um event
and page number and we are just okay this is the this is how the pagination the on change in the page
component help works the on change here this handle change okay so that's how it works so it
it gives an event event first and then the value and we set that page like this and in in
here we are actually making the first page into zero right zero into take the first page has to be zero and
for the first yeah so for the first page it has to be zero into take if if the take is 12 for
example first page where it's going to be skip is going to be zero second page is going to be 2 - 1 into 12 12 that
that that number of results we need to skip so that is the logic here let's calculate the total pages so
we get the total count from here and we calculate the total Pages for example if there are like
337 garages we divide that by 12 and we calculate the total Pages that's it now we return the
div I'm going to have a title here with some text large margin bottom and so on and for the loading I'm using the loader
panel which has this alert panel and uh alert section with a loader so
if if it's not loading if if the error is undefined but if the result count is zero I'm going to give the no
results let's create that no results it's a simple component let's create in the molecules
no results. TSX basically it's a flex Flex box with a everything in the center item Center justify Center
with a background I'm having his icon box to show empty no result so no results let's import that we are
basically we I keep doing this for for whenever I fetch information that's why I decided to
create this component that manages a loading State no result State also the error
State okay if there is an error I'm Usinger section
I'm this is development purpose right actually I'm actually printing the error there okay hope something went wrong and
then a small text we're going to like do this and then tell the error you can comment
this and then I'm going to grid grid calls three and GAP three I'm going I'm going to render all the
children we can further work on that we can make it um responsive maybe let's do it for a
smaller screen let's have like grd calls 2 and then uh for the mid screen we'll have grit calls
three or extra large let's go for GR calls four but that's sufficient I think that will
work finally in a flex box of justify center with some margin top I am going to use the
pagination from the mui okay here as far the count as
oops count equals total pages that is the number of pages I'm going to enable the show first button and show last
button pages skip divided by take + one yeah right so if you are skipping
550 the take is 10 then the page is five and in the on change I'm passing the handle page
change that is the show data component now let's go back to the list garages which is here
the list GES is going to use the show data let's pass the error message loading
message loading State uh the page Nation okay um one more
thing I'm going to create a hook so in the hooks we going to create a file called page nation. TS
and this is the hook a very simple one I I am tired of using the two lines in every component
which which requires regation so I just we create two use States we return return
everything in one go so that we can get everything in one go in the constants I'm also saving the
take count which is 12 here I'm going to use the use use
take skip the use T take skip comes from the UT hooks page
Nation right so this guy gives back the all the pagination related stuff now we need we need to write the
garages query in the graph C input I think we don't have the garages query yet we have search gares okay let's
create the garages query always use this while composing Airy we have this garages I'm going to
enable all these things filtering sorting dist distinct cursor even and I'm going to add the
ID display name description images verification verified address which is um ID lat long
address okay I'm going to paste it here Network um code gen is running so
that will generate the code for the garajes document so I'm going to add a few things for the
for that query we need two things one I'm going to get the slots count basically we are going to group
byy all the slots that belong to the garage basically I want data like cycle 7even car 14 so how many slots total
slots available in that garage so I'm going to create a resolve field the garages resolver
I'm going to create a Sol field called slots count we need to create also create um
entity for that I'm going to create an entity here in the garages entity file CL count type is going to return back
the type on the count okay this is cycle bus car bike heavy along with the number and
this let's create the resolve field so this all field is going to return back an array of
slot type count this is Sol field so we get back we get the parent information here and
I'm going to use group bu in the group by I'm going to group by type
where yeah we can filter based on the garage ID we get from the parent garage. ID then I'm also I need the count based
on the type that's it now I'm going to go back here I'm going to add that slots
count okay so basically we get an array of type and accounts where garage that's not it we also have to do
pay ination so we need the total number of garages let's go back to
the gares resolver and I'm going to maybe I think we should just return it
okay I'm going to create this query called garages count it's an async
one so we get the we condition because when the user filters we need to filter the total filter and get the total
updated total count also basically I'm using the garage. aggregate I need the count of all and we are passing the we
condition the we condition is going to have the address verified Etc fine so those two difference I wanted to
do now let's also add the garage count to the for and input file this wear is what we get here okay
this is the wear we are passing that to two queries both these queries and um the other stuff like
um order distinct distinct actually probably can be um I'm going to remove the
distinct the where reduces the total count okay so we have the query ready now let's go back here I'm going
to import the use Query from the Apollo
client use qu I think we we should use use B query because we
are okay let's just um stick to the use Query later if you are if you are going for some searching filtering those kind
of thing when we have you remember how we did with the search garages right search page we did we use the use in the
show garages we use use lazy quy because we are we have this complex variables going on we were getting we were having
this filter sidebar and so on We Gather all this information so I whenever this changes we wanted to refetch so I used
use lazy query this time I'm not seeing that maybe we'll simplify the process so I'm
just using use Query we need to pass the garages document garages
document generated file W okay so I did not name name that properly the when I was composing
this it was just called query I want I want to rename that to garages now we will get that gares document okay
fine here we get the data loading error so on here we can pass the
variables I'm going to pass the skip take the be condition I'm going to pass the company
ID Company ID equals Company ID we get from the property
that is it now the show data is actually complaining that we don't have any children let's add some
children I'm getting the data. garages I'm looping through that I'm just rendering a div with the garage ID
that's all we are doing now when I go to the manager page we
have no results okay this is the no results component and also we are seeing this component the pagination all the
buttons are um disabled so now we are going to have a
new garage button and we will create a new garage and we'll come back here
to uh to view all the garages and also we will have links for viewing all the bookings per
garage so see you okay so let's create a new garage in this section before that I'm going to
add the title to this saying garages with a link to the new garage page let's go to the list garages
component so this is what we are this is where we are fetching all the garages that belong to that particular company
and 're also doing the pation the set show data actually gets also gets this title which is a react node
you can pass jsx there and that will be rendered in inside this so in the
title I'm going to pass a div it's some class name next item Center so we're going to
have two things one is the title garages then the link I'm just going to use the icon plus
from the Tabler Tabler icons then the link from the next
link and now we get this no results and users can actually create click this to go this to go to
this new garage page and they can create the new garage fine now let's um start from setting up the back end so right
now our API goes like we just get um the garage we're getting the display name IM
description images and Company ID so that's what we are getting right now that is not sufficient we are going to
how in the last time we merged two mutation into one right based on the access pattern we have in the front
end uh we were doing the creation of manager and Company together in one mutation similarly I'm going to combine
a few things together here the create garage we're also going to create the address of the garage and the
slots Let's uh start from man from updating the create garage
input let's do the pck type which is clear I'm going to pick the description display
name and images also remember I am not getting the company
ID that's because I'm going to get the company ID from the manager ID that is in the
header that's what I'm doing and then I'm we also going we also going to get
the create address get the address so right now we have in the create address we
have address SL long and the garage ID but we don't want the garage ID right because the garage is getting
created now before that we won't have the garage so I'm going to update I'm going to actually create
another address input which is I'm going to man modify the existing create address okay so I'm creating
address create address input without garage ID I'm extending that this um create address input and I'm picking the
address that and long in other way we can omit the garage ID but picking look simpler so this is
the input type we are going to pass in the create garage input here let's pass this
fine the next one similarly I'm also going to get the slots here in the cre create slot
input we have the display name price per hour length width Etc with the garage
ID if a garage has like 500 slots I don't want the front end to actually pass 500 items with the height
height um height width length and so on so I am going to do some simplification
there so here in the create slot input I'm going to create another input input type called create slot input without
garage ID so I'm omit so I'm taking this input type I'm omitting the garage ID I'm also adding the count there so
basically in the resolver we are going to Loop through and we will create plots that's another input type
and um yeah so we can get n number of that so this array is there because while creating a garage users can create
like 100 Cycle slots 200 car slots so those items are going to be inside this array okay car count five then the the
next item bicycle count 12 something like that so this is the garage input we have now let's go and um work on the
resolver first let's make sure that the manager belongs to a company we're going to basically get the
company ID first we get the user information from the
token and we use that U ID to fetch the company ID so we basically looking for company at find first where managers
some of managers should have this ID right so so we get the manager ID and if we don't get any man
company I'm going to throw this error so here I'm going to add Company ID the
arguments which is a number so let's spread all the arguments and then I'm going to add the company ID
which is company. ID so that's all about the resolver now let's go to
the service file and Implement that first I'm going to have a check here slots so let's destructure the
arguments slots. sum slots is an array and sum of slot. count we get an array which says like
type cycle count five type typee car count 12 so I'm making sure that people are cannot create more than
20 I'm actually planning to deploy this okay for public uh so I'm having a few I'm going to have a few restrictions in
production we can uh deal with this in a much more intelligent and andan Tob Okay so
first I'm going to create the garage I'm going to pass pass the address the address
information goes perfectly well here so we just want the address lat and long those are the mandatory fields and those
that's what we have here address slat long so we can just take that and uh pass here and typescript is happy I'm
passing the compan description uh display name and images so this last information we needs
to prepare that to suit what uh the garages take right here we can create actually we can um create many
here okay so actually we can also create an um array of stuff here but the data we received is different we have the
account and then the type so we have to generate that array I'm going to create a new
method create it here basically I'm going to call this group slots by type it gets this type remember
this is the input type with the account array it's going to return back this slot create many input so
that's what Prisma is looking for okay I'm going to create an
object then uh I'm going to Loop through the slots array we going to get the count and then uh D
structure collect everything using the rest operator into the slot if slots by
type as a type if you don't have that type in that object we going to create a new array for that that basically the
return return type is going to be an array of this okay we are putting the type we're putting the garage ID all
this information inside then I'm going to Loop through the count
we got from here and I'm going to push the information inside it and we will
return the object. values now the typ script is Happy actually okay the return type is
now the return type suits that return type we mentioned the update is actually
complaining so I'm going to just remove the slots and address from there and now it works
fine as I told you yes uh we have a huge prog huge product and it's going to take um every path every mutation every query
needs a lot of care I would say we are we are like U doing the best 80% we can do in a
product you may ask then how can I change the address of the garage right so yeah so we have to handle those
things those N Things we are finishing 80% and we are going okay now let's we have already
created the garage I'm going to create the slots array using the group slots by type basically it returns an array of
this data then I'm going to create the slots so you can use the create minu and
I'm passing the slots by type that's it so after that I'm going to return the garage so that's all about the back
end now we have again um go to the front end create the form schema for that and then we'll create them forms and we'll
proceed with that before that we always go from the back end to the bridge which is the code gen and then the front end
right so let's uh go to the Apollo Explorer and we will compose a query for create garage
mutation create garage I'm just going to get the ID that's it
the progress I'm wasting that and also going to modify the mutation name and there is one um one thing wrong
about the for we use in a few mutation or queries I'm using a camel case like this
okay that is by mistake okay that is I think till now we have only one thing that is in camel case
I'm going to modify this to Capital let run the Goen to run the network it is successful now we have
the create garage document here fine now let's move on to create the form schemas in the forms
Library I'm going to create a create garage. TSX because we going to also have a
provider okay actually I'm not sure if you if we will use a provider so we will just stick to the
RTS okay schema let's call this um form schema create garage going to import the
Z from the zard we're going to get the display name I make it mandatory by make by
adding this U condition here it at least has must have one character so the images is um
y u so we are going to get multiple images and U using the input input element we're going to set the multiple
to True type to image and that uh the type is going to be file list and I I don't know how to exactly use that type
into the Zod schema that's why I just I go with the
any and location um actually we already have a similar schema
somewhere create company search garage okay maybe let's create a new schema I
remember using the same schema somewhere else also I'm going to create a form IM
address equals z. object flat long address and we can use it here and then we are going to get n n
number of plots for that I'm going to create another schema
this is create I think create plot form
schema create slot so we are going to have the get the height width
length price per hour count and Native I'm going to keep it 10 minimum uh
maximum let's also give the minimum to one and now here I'm going to add this s array
dot array oops sorry so we have to add that as C do
array and then pass this now let's create the info the type form schema create
garage then create the use form hook use forms from the create react hook form s resolver from the hook form
SL resolver SL zard then this is pal schema react or create garage I'm going to call this slots and
by default I want this to to be an array empty array otherwi I don't don't I don't want
to set any default values it's uh user will create them in the form okay so this is the use
form U the hook we can further create this provider okay basically it
gets um some children it wraps some children in inside and then we get all the methods which include the register
set value and so on we get everything and we are passing inside the form provider form provider again comes from
the react hook form the problem is I'm not sure if we so when we have like
nested uh components we need to do this we need to have Pro um WRA the entire children with a provider and we can use
the exact register function value function everything inside the children but I'm going to start building
using the hook and when we want to Nest the children we will come here we will create a provider we will wrap the
the wrap the create garage component with the provider and then we will use the use form context instead of this
so let's first create the page the web manager the page is new
garage inside the app I'm going to create new garage / page. TSX new
Raj okay now I'm going to create um create garage so the file is not there
yet you will create it and I'm going to just return that this
page F so let's go to the template templates create a create garage
dotx Cod con garage first let's import the hook
use use form create garage I'm going to extract all these um form management
functions like register handle submit everything from the use form garage and I'm going to use the create garages
mutation using the use mutation that is from the Apollo client these two are going to come from
the generat file generat graphical generator from the code gen the network library
fine now let's start creating our form so the whole form is going to we going to have the map in the right side and
the form in the left side it's a uh two column grid let's create the
form first one going to set the display name let's import the HTML label HTML input um this is a display name and you
cannot go wrong here you have to select one of these you cannot give any other names having some
title this is the error message the label button yes error message you will we will see this I think we did not see
the error message happening in the label this has to be a client component we have
this let's quickly have a look at the error message the type is going to be
submit and in the AR on on submit I'm going to just use the handle submit this won't get called right now
because we have not implemented the mandatory Fields yet but still when I click it the error message shows
up okay the problem here is a lot of times when I do not use the minimum one let's
go to that schema so here for in Zod if I'm not mentioning itable
or optional it is mandatory okay but an empty string is still a valid string so
I removed the the Min zero Min one right I come back here and submit you don't have the error anymore you will have
other other errors but that error is not anywhere that error is not there so if you want to make a
a string mandatory before that uh I told you I I showed you in the last section there
used to be something called non mty and they replicated it okay let's continue building our UI
next thing is a text area I'm adding the column five I'm registering the description
describe and passing in the error for the description you get two
errors let's go fast similar similar to this description we have the address
here and we're setting the U error for the address it's a bit tricky we are going inside the location
you may give that like this but actually this particular field is for the the inner one the address.
message we have to be precise about that and also here you get this U suggestion even
for the nested ones like this you can select the location. address which is a string
field I'm having some placeholder okay now we are going to create a component called image preview
we're going to set up cloud inary and um we will upload multiple images let's create the image preview
component so basically this is again an OP um like a branch component okay if the user select
some Source sources the image sources we are going to render the image even before uploading we going to use cloud
inary even before uploading it will render the images before render before selecting the pictures we will be
rendering the children which is the HTML input element with the type of uh image and uh multiple
true and I think uh rendering the images before uploading is important because if something is wrong the user
can reselect right we going to get the SRC which is file list that is the e. Target do files
from the um HML input element and also I'm going to get a call back where we will
clear the image so there are two things possible one is when the
SRC is there so remember we had an imagees any property in the create garage we have
this images any so that's what we are going to use store a file list image which is
an array of images if the that is true if the length is more than more than
zero I'm going to just create a grid of images render them let's say grid with a two column
I'm going to have an absolutely play button this is an absolutely placed it's going to be placed in the center okay
like left half top half and also I'm going I'm making the translate adjusting that to the X and Y
so that it will be like in the absolute center of the parent also I'm making the parent
relative let's import the icon trash from the Tabler icons react okay that's it now we get this file list
how to render that in an in an actual image component let's do that after that let's
just render them okay here I'm going to render an image
component from the next image I'm passing the key because we are rendering we are looping
through having some class names which is object cover aspect square and taking the full height and
width of the current whatever space available for that having the um alt an empty string
and then width and height now how to pass this SRC pass it like
this it won't work typescript is also complaining that is the file right in order to do that I'm we have to
do this URL dot create object URL and then you can pass the file now the typescript is happy we will render the
image from the file if not before the user selects the files
I'm going to just return the children I'm going to have a file Flex item Center justify
center with a minimum height so that is the component image preview let's add
that before adding that we need to get the listen to the value of images we get the watch and we can listen to the value
of images and then then I'm going to use the image
preview this images is whatever we pushed inside the form data and in in the clear image I'm using the reset
field from the use form hook and I'm resetting the field resetting the field of images here
also we can SP we can we have some type safety there and inside it I'm going to have a
control component the controlled component I'm using the controller from the react cook
form I'm doing that for the names but for the images I'm passing the control from the use form hook
here and then accepting the image file type is is actually file it's going to accept the
image any any type of images and I'm setting the multiple true so that we can select multiple images
and on change I'm actually getting the e. target. files that is a file list okay so I can click through and that is
the file list I'm just setting the file list into this
images and I told you uh I don't know how to exactly use file list here that's why I just go with the y in the s
that's it this is how it looks I am also adding the Z border
zero because the border is um a bit distracting for me okay let's um have a
demo I'm going to get some images from the unsplash.com and let's give shout out to
John not going to read that I don't know how to read that okay John for this image this image and then let's um get
this from igore
mnik and this one is amazing looks good this is from the Rabon
hijek I think they are sufficient also get this one from the from
Polo C and let's test the
images I'm selecting it and that is the image preview component okay you can further polish this
component you can actually have a independent delete button for images and uh I don't know how to do that even
so here we are simply using the reset reset field I'm resetting the whole thing and I don't know if I can do
a particular index inside that array um it's possible if I in the schema if I
have an array instead of uh any here if I have Z do array of string and if I push the push the URL inside that the
file file type inside that then um I hope we can do that but um I am cutting Corners
here you can clear it in one go and you can select them if you want three you can select
three okay the good thing is we have not uploaded the image yet the image gets uploaded when when we submit submit
that rename that so submit when we submit the image will get up uploaded to the cloud inary and then
we do the mutation we we we upload the image to the cloudinary we get the URLs and then we do the
mutation how does it look if I select two images yeah that looks
good and here also I have to add this minimum of one so because I did not see the error here okay two pills are
showing error and uh let let's set up cloud in Array go to cloud.com and U log
in it's free you have ample free free usage and you need the cloud name there okay copy this and paste it inside
create an environment variable called next public cloud inary cloud name that is the first one
the second environment variable which we want to work with the cloudinary is next public cloudinary upload
preset click the settings upload presets and uh add upload preset and just copy the
name so when it asks uh signed or unsigned go for unsigned we're going the we're taking the the easier path for the
tutorial signed cloudinary is better it has it is safer but we are going with unsigned
one so let's proceed I'm going to create a hook let's create in the util library
inside the hooks I'm going to create create a file called cloudinary dots import the use State going to
create a hook called use cloudinary upload so this Hook is going to return back an upload function and the loading
state is a Boolean now I'm going to create a function which gets the file list okay
that's what we store in the form schema also first I'm going to set the loading State Let's uh and then I'm going to
start a TR cach block and I'm going to create I'm creating an array from this
file list and I'm looping through that getting individual file and then for each file I'm going to
create a form data first I'm going to upend the file itself and then I have I have to open
the upload preset which we just created right with this name of key upload preset and then I'm going
to use the fetch to actually push this form data into the using the api. cloudinary version onecore one I'm
passing the cloud name here image upload this is unsigned so it's not a safer way but it works for the
demo once it's done sorry I'm inside the catch block
okay if the response is okay not okay it has to be inside the promises if it's not okay I'm throwing
an error if not I'm getting the data back and this data is going to
have okay so we don't have types type safety here and if you remember we did not install
anything that is related to the cloud inary so basically we don't we are actually hitting the AP as it is just
having the cloud name and the cloud pre the upload preset
so there is no type safety here and in the image image I'm going to get the secure Ur secure
URL once everything is done I'm going to return the image URL
now let's that is the promises now we have to await all the promises that is going to return
back okay that is going to return back this an array of promises and I'm resolving them in all in one go and I'm
returning the uploaded images so this is going to basically return back and array of
strings so in the catch I'm I'm going to just throw an error something went
[Music] wrong Lo failed and
finally going to set the loading to false okay that is the hook and um we're going to return the
upload and loading fine let's use this in the create garage
component let's import The Hook from the util SL hook SL cloudinary and we we can get back the
uploading and the upload we are going to have two kinds of U two things going on one we have we
have a loading for the mutation maybe let's rename this to uploading why don't we return that
uploading set uploading okay now in the button we have to set
this loading State it's going to be uploading or loading so this is for the loading State for the mutation this is
uploading that we that happens when we upload the image to our Cloud inary fine let's
continue we have um so it's a two two column grid okay okay so I'm going to have a map here
with a movable marker draggable marker so the first item is a form the second item I'm going to use the
map okay let's import the map from the map map from the organism and the initial value from the
initial view state from the constants that is pointing to the nework okay AP access token is required
to use the map G we did it in the last last application right the consumer facing web
application you have to copy that map next public map boxcore token you have to put that inside the
environment variable of the web manager okay we got it we got the map let's add let's add a
panel let's have a panel in the left top I'm going to have the search box search Place box remember
so that basically we uh just use the mapbox API yeah we use the mapbox API to get uh the
suggestions based on the type uh based on the text VI type along with some fuzzy
match that component oops okay this view view state is
different okay I have to import it from our types not from the react
mapg a simple import it from the autospace util types so we have this now we can
select we can type anything so this looks bad what if I
wrap with a dip okay so that looks better so the choose files was ragged for the
remaining space fine we are working on the map and next
one in the same panel inside the same panel I'm going to add the default Zoom controls okay so this one it is working
but remember I told you that we can add more buttons here as children I'm going to add we also have
the center Center of map component this one I'm just going to add that
component simport that that is a center of map component and center of map requires a latl a on
click the on click is going to give us a lat long I'm going to just call it lat long
or okay that long and we have um okay let's parse
that and use a set value from the use form hook set value set the location. lad and location do
longitude using this actually I'm going to also render under this lat long in the UI okay here
why am I like truning reducing the uh Precision here I'm going to actually have the lat long
rendered here and I don't want it to be too long maybe let's increase the Precision
a bit now we need a marker on clicking this basically we get the center of the
map and we set that to the location. lat long now somebody has to listen to that
and they have to render themselves here right in the center for that I'm going to create a
component called garage map marker in the organism I'm going to create a create
garage components file this is going to have multiple components that we need for creating the
for writing the create garage component template this guy takes initial location it's a view State lat long
Zoom um which also gets the location information using use watch use watch from the re hook form
and um the form type okay okay so I initially I did not create the
providers right in the create garage I did not create the provider but we we want this form is going to need a nested
forms we are going to have children like this one right the marker is going to listen to the location and um it renders
itself and also we are going to have ADD slots component going to have n number of slots getting created that component
is going to live separately as a child compon onent of the the template so we need the
provider so Yep this is going to be similar to what we did earlier with the providers and also here I have to do
something with the es config before that yeah the provider gets the children which is
react node we can pass anything it's going to WRA the entire template and then I'm going to get all the methods
from here and I'm passing them inside the P provider so that we can get back in the use form
context here it is complaining that okay so I have to convert that into a TSX file okay now it's
happy I have created the provider now let's go to the create garage first I'm not going to export
this I'm going to convert this into a create garage content so this is a opinion create garage content then
export const create garage this is the file we are going to component we're going to exp export here I'm going to
have return use form the form provider garage create garage and then inside that I'm going to use the create garage
content okay this we are not go nobody else can access this we going to export this and
we are wrapping the entire thing with the provider you can also just go to the the
page you can import the P provider here and we can W the entire template here but I want to like en consulate or keep
everything together inside that one template so I like this format okay now we are working with the
create garage components oh also one more thing the create garage now we cannot directly use
the we can use but it won't be remembered we want the same state right the
location information for example in the form schema has to be same here also inside the nested components here
so we have to use the use form context instead of the use form we
created I have to replace this with the use form context and also you have to pass the use form type create garage
okay now everything should work let's continue with this uh garage marker so we get the initial location we
get the location we are also getting the set value because the
location the of the marker the dragable marker are set from different places when the map moves we get the center of
the map we want the marker to be there right when the user selects the city
name when the map navigates to that location we want the marker to be there so that's why we U get this
location and this marker is draggable when we drag the marker we have to also let let the form State know that the
location has changed so let's import the marker from the map marker
and let's um return that I'm going to use a parking icon yeah which is just a
p some BG primary border and so on oh here I'm going to add the pitch alignment to
Auto latitude and longitude from the from the location information going to set this this is
draggable and also when the drag ends on drag end I'm going to use the get the lat long and I'm going to set that
value fine now we can just use that in the create garage so inside the map this does not go inside any panel
panel is for the overlays the marker exists right inside the map okay I also have to pass the initial
State initial location to does not make sense to me I'm going to remove this basically we
get the this marker lives get the location information set value information and uh we use the location
for setting the location and set value in the on drag end so this should work work
actually where is the marker here is the marker I can drag it now but when we open the
page nothing is there maybe let's have a fallback like marker location equals
location or initial view State then we take
this so the pl the problem here is when the map loads we are not seeing the location we are not seeing the marker
straight away so I'm actually setting onload I'm setting location lat as lat inside the
onload we get the event from the event we can get the center using the e. target. set get
Center okay so that should work now this marker gets the location and then I don't want to do any of
this now the market should appear okay yeah fine now when I move the map okay the marker goes there as
well I don't I don't precisely remember how the marker went there because I only had
only added this on the on load I was expecting to do some on zoom and on drag end
and on mov end I did not do anything but okay okay okay got it so I actually update do the same thing here in the on
location change of the search map box search Place box so I it gets a call back and um we set the location lat long
there and hence when we move somewhere like let's go to Paris the marker already waits for the
user and then user can drag this get wherever they want and um one more thing is that
we can do something like um when the user types the address here we can technically do it now we can
hit the mapbox API and get the lat long for that address that would be impressive but I cut that corner for the
project and now we have the location we have the all the important stuff we have the
images the next one is um slots
Heads up!
This summary and transcript were automatically generated using AI with the Free YouTube Transcript Summary Tool by LunaNotes.
Generate a summary for freeRelated Summaries

Build a Modern Frontend Developer Portfolio Using Next.js, Tailwind CSS, and Sentry
Learn to create a stunning developer portfolio with animations, responsive layout, and performance tracking.

Unlocking Microservices in the Browser with Single-SPA
Explore how Single-SPA enables microservices in JavaScript applications effortlessly.

Implementing Your Own Design System in Next.js
Learn how to efficiently create a reusable design system in Next.js using Tailwind CSS and other modern tools.

Unlocking Startup Potential: Building a Social Media App for Entrepreneurs
Discover how to create a startup idea community app using AI tools seamlessly.

Creating Spaceships Using Photoshop and Stable Diffusion: A Step-by-Step Guide
Learn how to design impressive spaceships with Photoshop and Stable Diffusion. Enhance your digital art skills!
Most Viewed Summaries

A Comprehensive Guide to Using Stable Diffusion Forge UI
Explore the Stable Diffusion Forge UI, customizable settings, models, and more to enhance your image generation experience.

Pamaraan at Patakarang Kolonyal ng mga Espanyol sa Pilipinas
Tuklasin ang mga pamamaraan at patakarang kolonyal ng mga Espanyol sa Pilipinas at ang mga epekto nito sa mga Pilipino.

Pamamaraan at Patakarang Kolonyal ng mga Espanyol sa Pilipinas
Tuklasin ang mga pamamaraan at patakaran ng mga Espanyol sa Pilipinas, at ang epekto nito sa mga Pilipino.

Kolonyalismo at Imperyalismo: Ang Kasaysayan ng Pagsakop sa Pilipinas
Tuklasin ang kasaysayan ng kolonyalismo at imperyalismo sa Pilipinas sa pamamagitan ni Ferdinand Magellan.

Ultimate Guide to Installing Forge UI and Flowing with Flux Models
Learn how to install Forge UI and explore various Flux models efficiently in this detailed guide.