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