Building the Ultimate Auto Space Parking Application
Heads up!
This summary and transcript were automatically generated using AI with the Free YouTube Transcript Summary Tool by LunaNotes.
Generate a summary for freeIf you found this summary useful, consider buying us a coffee. It would help us a lot!
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.
Stay tuned for next sections, where we'll dive deeper into backend integration and UI enhancements.
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
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
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
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
actually another form but we we get the time started start time and end time from the search
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
charge for pick up and drop off you may select a different location for the drop off okay so what happens is that the
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
okay let's log in with our valet account also we have I use reuse the same 3D scene here but this is not
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
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
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
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
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
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
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
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
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
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
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
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
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
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
development let's clean up the terminal let's allot some terminals specific specifically for the web
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
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
maintain a naming convention I'm going to have a spa at Auto space before the our applications and uh
typescript I'm going to install typescript as a depth dependency but we also have to specify this hyph W that's
root instead of going inside and inside the library application so they have this U feature so I have to mindful
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
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
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
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
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
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
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
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
the prettier configuration so um njs already came with this preter RC I'm going to just drag that into the
check to see any formatting issues in the whole monor repo there are a lot of issues you can now run the
controls that will be fixed but here actually there is a problem with the es lint es L is uh struggling to work with
particular thing off about the Prett I'm going to inside the rules in the es land I'm
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
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
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
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
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
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
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
script so it runs the formatting first and then it started yeah and then it ran the TSC 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
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
log the API one did not generate much Nest build and then it just done this is also the sample also simple
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
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
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
can have the error in the sample lib can have the error let's put the let let's put this
oh yeah find that yeah the error is here okay cannot assign num because it's a constant remove that now you can commit
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
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
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
a container with the name same name I'm going to delete that let's run the docker compost once
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
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
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
password okay the password is going to be hashed it's we don't we don't save plain passwords in the database the
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
okay as we can because I'm actually uh forgot to clean up the volume we deleted the existing service
it okay so the the database migration happened and also it generated the Prisma client now we can open the Prisma
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
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
and inserted in the schema so that's why I'm adding this fine we have we have set up
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
automatically because the server was running it was stuck in an error and when I generated what happened is in the
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
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
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
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
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
Explorer and you specify the URL here which is Local Host 3000 SLG graph but it's giving me an error you can just
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
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
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
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
generate all these commonly used uh types Prisma service with a Prisma Global module common input types and all
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
graphql and rest modules okay actually this is one module with both the graph qu and rest rest
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
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
focus on that in an upcoming section so in order to satisfy the typescript I have to install njs
to sign and verify the JW tokens okay we have all our dependencies ready now let's create I'm going to use
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
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
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
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
to be in sync with the database you cannot remove a class you cannot add an additional class okay types scpe won't
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
API this syntax we cannot use so for that we have to use the nullable field field decorator with the nullable
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
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
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
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
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
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
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
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
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
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
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
different last time I was using field with a nullable property remember but this time I have to use the is optional
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
omitting Ty you can ask pck type but this pck type is coming from the njs Swagger not the njs graph
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
uh Swagger UI this will be an drop down okay you cannot pass anything else for the search by or sort by
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
is valid if it's not null or undefined I'm creating this object and I'm spreading it if the skip is null
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
models I keep saying that fine I have worked with all all of these things now let's just have a let's just
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
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
hours maybe let's quickly have a to-do move move this to util Li library library fine I have
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
except this one this does not know what is this so that's what is saying that the object
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
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
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
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
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
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
so I'm just using uh contains here again just not completely we're not worried a lot
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
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
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
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
okay aut of space this is the head this is the doc this is the description but I don't know why this
use a Explorer I'm clicking this it will open a new tab the URL will automatically be populated 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
02 order by string I'm going to order everything by descending let's try it so it gets two items it's descending
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
here let's do something else car okay we don't have that okay so user okay so we have four items the uid
ganguli okay I think okay this has to be this has to stop actually we are going to get um unauthorized okay no token
this let's do this we will come back and um go through that yeah authenticated authentication in sjs in
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
response okay maybe let's create let's delete one user this also needs this authentication I'm going to quickly
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
uses now let's come back to the let's fetch all the uses the interface is actually a bit
interface so one problem is I I make sure that it's uh is optional but that is not being reflected
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
something but functionally it works good maybe I have to add I have to decorate more to satisfy this but I'm
API uh is working good the rest is also working good now let's have a quick walk through about
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
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
authenticate user I'm getting the header the token first I'm getting the header I'm getting the token from the bar
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
request I'm giving another error which is different right this is no token this is invalid
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
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
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
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
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
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
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 okay now I'm going to just go through the uh look at the graphql let's go to the users resolver
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
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
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
okay let's fix it get the right one now the third Let's uh let's try for the to third token
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
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
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
token we get back the user user we are expecting the user to have the uid this is the payload maybe
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
throwing an error the uid is there we are getting the user from the database if the user is not there we are
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
people finding a loopholes in the system now I just patched the problem okay so the uid the payload now has the uid if
then we are throwing other eror okay now I I not change the bur token but I changed the logic now I'm trying
sorry now I'm getting invalid token okay so actually I have I have to rethrow that error from inside
database when I try access invalid token no user present okay now let's um do that check that other one with the wrong
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
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
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
Gangi the header is already populated Kung can access the data but if I want to access the data of
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
decorators s the RO level permission okay so our graph C first API are ready along with the authentication
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
we going to get name email password and optionally an image the second one I'm going to rename
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
so basically we are getting this input type we are calling a service method that's all this mutation is
similar this is register with provider okay actually let's just simplify I don't want to have a try
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
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
user we can add the image image here okay must we have to add the entity also when you restart when you
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
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
let's implement this register with credentials next this is a bit tricky we are going to create a uid we are going
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
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
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
be credentials fine so for this I'm so in the return type I'm also going to after the data
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
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
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
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
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
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
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
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
created user I'm seeing the Google name here there the credential is null we don't have credential there but we have
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
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
the query is the user row you get we we include the credentials when we query the user and we can get the password
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
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
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
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
okay there are some drawbacks like people can this is an unauthentic route registration usually is
okay but we are not sending back anything we are not sending a token or so people won't get access but they can
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
modules instead I'm going to just switch the package manager it has something to do with how pnbm stores the node modules
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
so basically I deleted the pnpm workspaces and lock and I added the workspaces here along with the packages
a shot for y install no lock file found it's going to take some time to create that log file
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
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
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
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
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
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
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
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
okay let's start building autospace so go to the Prisma schema file right now we only have the user
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
may have a manager may have an admin may have a valy customer table relationship but the customer is going
user have the uid as a string and that that is the uid that is a foreign key that's a primary key that
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
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
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
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
provider okay so the valy is going to have the user so we cannot create an item here without having the uid that
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
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
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
companies that is possible also but it complicates the system further so this is this is what we are going
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
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
the back end but I don't know if we can implement we will have time to implement that particular feature in the product
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
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
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
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
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
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
the customer requires a parking parking slot so in order to do that I did some performance clicking tuning so we we
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
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
because what if we have the pickup plat long and not the pickup valy that will create inconsistency we may
validity or all mandatory right and that joint will be optional from here so yep so I'm going to keep this a
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
okay we have the booking here have the valy here the manager ID manager and valy can update the can
model the ID and dates rating is a number comment is a string and uh who gave the rating which garage the rating
you can see Prisma is um showing the error the admin can give a number of Val verifications and uh garage is going to
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
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
assignment so one thing we can do here is we can actually have two properties here like pick up valy drop valy and
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
running okay this is the database running at on output number 2010 I'm going to do the database
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
working with our graph Q API okay we already have a base for our API the back end API the back end is ah
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
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
passing the flag graph K and for the rest I'm passing the rest flag and for complete I'm passing the complete flag
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
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
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
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
entity I skip the PR my schema nearby so we are working with the let's start with the admin
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
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
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
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
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
comprise of all the filtering and sorting pagination capabilities okay in the cursor even though we are going to
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
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
filter from the common you can have a look at this okay this is this is inside the common this is autog generated as
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
this so I have I'm just creating this uh Network all these things I'm importing are from the other modules I
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
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
I'm looking for the ID in the update admin but we updated this to U ID so I have to modify
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
imported all the modules that we generated okay now we have to 2 70 errors and 's keep going the graph part
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
from the ID number to the ID string U ID string same thing happens here okay I'm going to select all the
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
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
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
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
modules and I have based on the christma schema I have updated our modules for example this is the
properties you can see the nested parting and filtering also okay and all the rest JS and rest
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
Google password is okay our registration is successful now we can go back to see the the data
hashed and uh basically the user is created okay um now let's try to login with the same
create company mutation I think it's going to be a bit different from it's somewh in India we I
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
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
generated right this is actually the generator is going to be typescript code but we are going to generate it using
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
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
okay so it's asking for a token because the company's resolver I'm ask I'm telling that only
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
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
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
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 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
um let's D structure the values and um ins the data I'm going to give the description display name and then the
be string because that's a uid fine let's delete this uh company let's create it again now but
saying we need to pass the manager ID let's pass it going to get the manager ID from here
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
id2 and U we got these things back you can do some filtering sorting I'm going to sort by
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
ID so the manager uid has 23 that's not a problem but um I am worried why I getting only one
the manager can be a part of the demo did not go as planned but still the manager can be a part of only
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
switched to the newer companies that got created now if I passing same manager ID with another company I'm going to get
you the filtering and sorting capabilities and uh yeah in the next section we will be able to create create
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
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
information okay this one there are few things which is not protected enough okay at comp time can user be user is
error you have to make this nullable true when you try that you get the user and the admin is is
when we fetch fetch back we are going to fetch the admin fine let's do that for the manager
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
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
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
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
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
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
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
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
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
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
this is the input file document pattern going to have the plugins typescript typ operations named
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
output file path the documents we have to mention the input file path which is we going to have an SRC here and
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
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
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
TSX okay because we are also going to have export the Apollo Provider from here let's install the Appo
simple this is the interface for the provider because we are going to get the children we need to
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
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
work okay I'm sorry I have to this is hyph I Pier to save the perer dependency the network now we have react
link and I'm just exporting the provider by passing the Appo client as a client this provider is Appo
this provider and uh inside that we can just install Apollo client as a dependency in our application and we can
before that we have to set up some TS config stuff here you we are using jsx but um it does
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
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
import autospace Network SL src's config Apollo I'm going to import the Apollo provider and I'm going to wrap the
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
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
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
have a query like this companies I'm going to just paste it here and the network is not running okay
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
now the we and so on okay here also you can do this nested filtering whatever we saw here is
3001 since we are using hooks here I have to men mention this as a client component yeah that's not the problem
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
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
Way okay in this section we going to proceed to build uh the next o we're going to set up authentication and also
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
library and then I'm going to export the Handler as get and Handler as post and now let's go to the network
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
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
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
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
document so let's make sure that your network Cod is running and in the okay so um I have to enable
fine okay now it's watching in our graphql queries or graphql this is this is our input input file right when we
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
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
okay I don't remember installing that I think this will do us okay this should do so this is the document we are
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
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
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
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 the function knows the type of type of the return return type this is the gra graph let's use it in
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 user information in the login Also let's go to the user service here we get this user right I am
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
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
received from the credential itself right so because we use that email to login so this is going to be that email
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
just return null that is how we authorize when the user enters the credentials email and password that's
error now we can remove this and uh typt is happy you know and that's how we handle the
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
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
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
locally so I have a weak password weak secret there but you can have other harder ones we will use the same
there okay now we have the token we can just return it fine that is the encoding logic let's
string okay this object is going to have the ID and other token props that we used to create and return
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
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
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
into a database when they registered but that won't happen in the Google Google sign in so we have to when the
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
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
user there is no account there we going to create create a new user if there are no existing user then
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
true basically in the call back sign in call back we uh made sure that the provider is Google and if there is no
session object and passing the image from token picture passing the uid as token. uid email as token. email name
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
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
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
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
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
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
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
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
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
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
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
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
animations for spinning spin ders wiggle slide we yeah all these things you can use also we have to create the key
starts at zero it starts somewhere and then it goes parks and then it it returns we don't need yellow because the
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
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
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
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
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
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
which divides the components into templates organisms molecules and atoms inside the SRC components I'm going to
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
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
impulsively don't have reasons why I do that okay let's remove the brand color here so that we can
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
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
the Yeah so basically we have to mention the variant and the color and I'm just using the basic
have the loader there let's check this button first I'm not going to do this for every
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
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
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
file Let's uh build our schema first we need import the zard first let's create the form
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
resolver is going to be zard resolver have to import that from the hook form at hook form resolver
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
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
created is efficient right I mean U at least in the type safety way right now we have the schemas we
form inside the templates I'm going to create the login form. TSX F this is the interface it's going
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
energy okay let's uh get the form from the atom I'm going to have the HTML label inside that HTML
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
contains some error errors so that we can get from the form States errors I'm going to console log that as
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
okay the we if we pass error we will render the error below the box like this this is the exclamation mark follow by
worked the password is not optional but you can specify that okay also you can you have to specify
password Al I have quickly have some placeholder yeah so when you start typing oops the type is type has to be
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
here that's it I'm going to have a text here saying if you already have the account you can go to SL
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
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
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
page this is the page okay we're going to have some 3D scenes side by side also you can see the your
and we are redirected to the homepage now you can go to the application you can look at the
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
there okay so before that we need to create the mutation right so in the user resol we have this register with
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
credentials okay yeah so already we already have this so y we don't want this we don't want to create it
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.
util let's also install dependencies similar to what we did earlier I'm using the use form
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
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
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
form um let's uh just duplicate the login I'm going to replace with the register rename the to register and we
have remember we created that get o function this is a client function okay okay so if it's a client component we
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
out on click let's just call it we don't have to do anything or else I'm going to maybe
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
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
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
button and look at the session cookies when I sign out the session will go oh actually I'm
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
you're going to get this alert upcoming sections I will be creating I will be setting up
page again register form has to be a client component and let's do some register Let's do
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
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
header okay I'm getting the headers I'm splitting everything inside and I'm passing the authorization header based
nothing okay that's the link now we have to concat that maybe I think a better syntax would
it Al so we need the comma fine that's how we add the header in our header Quest now when you go
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
right so that's that's a strting you will get here now once you fix it you are we are getting back the
remember the company's resolver we have the find all only authenticated people can get it so we have our authenticated
authenticated graphql query from this section we're going to create a Navar a header with a sidebar
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
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
and we will actually customize the look to match our style okay there's nothing here but we are going for an yellow and
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
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
here at the end of right the right corner we will be having this uh hamburger and clicking this
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
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
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
this side uh sidebar in a header component so before proceeding with the header let's we need a brand icon brand
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
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
okay let's uh we also need a let's see a type here called base component I use this in a lot
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
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
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
this kind of type declarations and when you use the same package in another Library you have to
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
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
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
content behind the underneath the now bar I'm going to use a shortcut which is this is a fixed layout
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
going to display a sidebar which is the hamburger menu and clicking it we will show the Side Bar sidebar if
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
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
image so that's what even in the user info I'm using this user.png I'm going to copy that user.png
bad Al I want the log out in the bottom header Mt Auto but still it did not listen it has to be
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
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
are going to close the sidebar that is setting the open state of false and then we are assigning
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
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
keep the search garages very so before creating the uh query I'm going to create some input items input
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
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
get the date filter that gets from the date filter input which we just created location filter is going to come from
to just use a basic wear condition to look for the latitude and longitude that exes inside 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
called enam slot filter type says equals that is the equivalent of this right we can pass one slot type so this slot type
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
this is already an input type so next nextjs will recognize that that one I I wanted to do then let's proceed with
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
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
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
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
actually we have to do this here because we have moved the start date so we have to move the end data
fine let's get the filters from the garages I'm I'm extracting the garage filters and I'm making the wear
that that's it now let's uh return this. Prisma do garage. find many spreading all the
function fine so we have so inside the we condition first I'm going to spread the we i d structured right
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
longitude and greater than Southwest longitude fine and that's not it we also need to filter based on the slots the
many relationship right garages slots have one to many each garage is going to have multiple plots that's why I we have
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
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
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
end that is the search garages we have one more uh query which is available slots this is what is going to get as
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
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
hour okay there are going to be different types and the same type can have multiple prices so I'm going to
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
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
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
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
resolver okay so this comes from the available slots filter the the G the resolver is not a problem but the query
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
filter let's use that and we will clean up we clean up these types we don't want these variables
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
use a company here and U let's create an address and attach that to the we will create the mutation
testing we'll assign the garage to the address and let's also create a slot because we in the query we are also
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
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
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
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
we take care of that in the available slots we have this condition right this is one query we are not this is one
back if this booking is if the three is booked then we will actually get the count as one and price per our
S4 okay so we're not going to have have that problem sorry I don't have the problem
right we started with our back end with good types input types argument types set up with one query and the resolve
basic variable set up which is a date filter and location filter both are mandatory and we got back the response
on the upcoming rection we will be creating the search page we will create a s schema for searching okay I I I
think that the react hook form is a state state management Library like Redux we're going to have a pro wider in
the search section and we will be manipulating the types we will be we we are we will be using the uh range slider
0.1 now they are flat and now they are float when I try to access this the servers are not running I did the
if the error is there now I'm actually thinking why didn't the data display got the garage
log okay so that is why when there's an error even though we get back this right get the error we get
app module when setting up the graph module I convert this number scalar mode to integer so it is it is Float by
example okay so let's just ignore that okay um so I I started enabling this number the number scalar mode to integer
options so that if I'm not removing that we should add in the entities that's for the rest
this is going to lead to a lot lead to runtime exceptions so I don't want that to happen
so to be honest I I don't I don't I don't remember why I started using the integer as a number scalar mode in sjs
projects but um we will come back here if you're facing that error again I mean not an error but uh
yep I don't remember why I started using this so now that problem is solved okay let's start with our
icons pick any number of I mean uh any number of slot types for the filter and so on so let's start with our
okay fine let's import the Z from the zard let's create a new object thir object first I'm going to have the end
time and uh start time time as strings I'm going to have a location filter which is going to be an object again
it's a nested object right an object ins object we to have not the slat not this well this is exactly what we had in the
garage filter location the common dot PS we have this location filter we have the Yep this is
same and also I'm going to make this optional let's not make that optional and the type is z do VM that's
how we mentioned type okay we are going to get an array of types I don't know why we I have this
TSX because we are going to also create a provider component I need to set up the TS config for the forms
Library first I'm going to extend the root TS config here we have all these default options
so I'm extending that and then in the compiler option that is specific to this Library I'm going to specify the out
tups t t that's basically going to be it's an array with two numbers okay it's a t
tle and let's also have the pagination here skip take and that's it that's a filter right
pation that's it we have our form schema let's infer the type here using the z. infer and passing the schema type
here few functions this is It's is start time valid I'm passing the whole data which is going to be this
type and I'm just making sure that the start time is greater than the current time we will have one more validation
function called is invalid end time valid we are just getting the start time end time and we are making
sure that the end time is greater than the start time I'm going to create a create custom validation in the form
scheme search garage I'm going to first add using the using the refine option we can have a function here okay that will
function and I'm also going to have this kind of an utility function this basic Al gu the start
minutes from now even if the customer is booking right from right in front of the gate this 5 minutes will give that
TS so basically it gets a date it gets a time zone offset and we are offsetting that to get the local iOS ioso time okay
so that could be a simple way simpler way but we are going to go with this let import that utility function
we have two custom validation functions and we are using that in using the refine from the zard we having custom
anywhere else but let's let's just keep it here I'm also going to have this is the
slots let's create the default values it's going to start the price per hour is going to start from 0
now let's create the provider component going the provider is going to get the children so that we can
provider first let's get the inside the provider first let's get the current time and end time
let's get the get let's get all the methods using the use form hook and passing the type we infered from the
schema and here I'm going to set the resolver so we're going to use a zard resolver from the hook form resolvers so
zard here we will pass the schema file and then we will be setting the default values default values going to be an
from the react hook form and we can pass this type here okay so that I think I don't want
assertions we cannot do this okay fine I'm going to first pass all the default values here from here and then I
methods we received as the props this this method is going methods is going to have all the everything like
Gema okay let's create the search page in the app directory I'm going to create the search page.
page fine so here we are going to use a map from the react mapg this is this is the package we're going to use we need
to install these two things in the map the UI Library I'm going to install these two okay I've
public _ mapbox _ token you can give any name you want but it has to start with our next public so that we can access in
inside the organisms I'm going to create a map directory we're going to have multiple components inside that we are
going to have that actual map component we'll be having a marker component panels to to position
different other components like autoc complete and uh Zoom buttons and so on Zoom buttons also comeing inside that
inside the map we'll be also having a custom but button to position the Mark at the center of the map all those
things we you'll put them inside this organism let's go from the first one is the actual map component from the react
view state is going to have the latitude longitude and zoom is is optional let's create the map
props I'm going to get this map G okay so I don't want this map props here so basically I'm getting what the
comp the properties of a component using the react. component props I'm passing the type of the map GL which is a
here because we use map in two places and I'm actually passing the height as a property in one place we have a full
inside the style property of the component right so inside that I'm going to just R return the mapg
with some stuff like I want the projection Globe so that the user when the user is too far away zoomed out we
show a globe it looks amazing and I created my one map style it has a gray black and grayish
tone I don't want any colors so the gray ones gray maps go with any design system we have for example this product has a
yellow black design scha I mean yeah guide design system the primary colors are yellow and black and the the
the pitch will give some tilt to the map I I initially I liked it but um it was not accurate because we rely on the
boundaries right NorthEast Southwest when we tilt it we cannot get that right so I removed it and scroll Zoom I
current and I'm setting the Styles here okay Horizon it it gives some fog yeah we will see in the in
action so I'm going to create a search page in the templates let's export that okay let's import the search
page template inside the page fine so this component needs to be a c component because we are
it uh will start to look like this what is that and I I have also disabled the scroll and also one more thing we
have to do this is uh this has to come inside the map go inside the map for that we need to add the map Styles so we
import you going to do two things I'm going to have a separate map CSS file inside the map
there I'm going to import the map G CSS file okay and I'm going to import this map CSS into our Global
we'll come back uh to this file to have more styles for the popups and so on so that's why I
have this separate CSS file for the map we have the map ready let's create more components the
next one is the map marker I'm just here importing the map map marker props and I'm exporting it I'm doing this because
panel the basically the panel is an absolutely positioned component we have more uh options so
Center left bottom center tops it's not ordered properly but you get the point right the N nine slots in right nine
nine position so it's it's absolutely positioned and based on that based on this we have Tailwind classes position
here this is the zoom in button we use a use map we get the current the instance of the map we use the map. zoom in so
fine and then similarly we have this center button again we have the on click here okay let's
just extract a button here let's call it control button our Zoom control button it's
later so let's modify this let's um fine so that is a zoom control we have the zoom in zoom out Center of map
inside this map control I'm creating this default Zoom control which has a zoom in and zoom
zoom out button but later whatever children you add will be added under the zoom out button if we will use
this that's the zoom control and finally we have one more thing which is uh current location
button we get the map instance we use a navigator GE location to get the current position so we get the position and we
use map. fight to to pass to that location so on clicking this basically the map will move to that move the move
also fine also using these icons I forgot to mention here we are using the icon minus icon parking icon plus this
icon parking is used for the center of map this we use while creating the garage wherever the the map is when the
user presses this icon the the button we will place the Parker the center of the map that is the basic setup we have all
going to have the nework location as the initial location for the map and also we going to have panels here we going to
places and the users start searching typing Al here we are going to have a zoom uh zoom in and zoom zoom out
have the zoom controls here right by default is going for the left top and I want the the buttons to be
end in those uh also the on load in those functions when that when those actions happen I want to calculate the
bounds okay when I when I drag it I want to get the bounds the Northeast lat long Southwest
going to put this inside the use call back we have a function here this is going to get the
target target is view State change view state change event from the react map GL and I'm going to
take the target so we can actually get the event here but the uh the function function argument
for the onload and on drag end are going to be different so I'm just getting the target but this target is going to be
we can call the handle map change and we can pass the e. Target similarly on the on drag end you can do
the same you get that we call the handle map change and we can pass the you can see that the event type is different for
end as you can see when we end up when we finish Zoom the bound changes when we drag the bound changes also when the
to fetch the we need to get the bounce and we need to fetch the garages inside that okay we we will actually implement
this function before that let's change the initial State initial view state so this initial view state I'm going to
when we load the map we will we will start seeing the new arc you can also modify the zoom States
when we go higher it will be more zoomed in okay I think this makes a bit more sense or even
spot fine now let's do some calculations and uh we will console log when we drag and when we move we want to calculate
the bounds and we will just console lock it so we will implement this function so we can get the bounce now
bounce equals target. bounds get bounds okay let's console L it now when I drag it so nothing nothing
lat long okay that's data we want I'm going to further simplify it to create a new object with the slat
query and now let's print this instead the location filter when I drag when I remove when I
complete component actually I'm using I'm going to use the combo box the autocomplete component from the matal UI
there is also an alternative called combo box in the Headless UI so we already have headless UI installed in
this in this this project you can go ahead and use this but I'm going to use material UI because that's what I used
going to also need the material for a slider and few more components that that headless U does not have
anyways also as I told earlier material UI uses tree shaking so when we import one package we are not
want want it to do so let's install the requirements inside the UI component I'm going to install the material U emotion
react so these are the dependencies fine so inside the atoms I'm going to create a component called
TSX I'm going to just copy paste it and we will go through that component basically we will install we
will import the autoc complete and autocomplete props now I'm going to generate the type for this component I'm
going to remove the render input from this property because this is this is this is going to be custom we're going
to have a lens icon we going to have input box we are going to have some style going on I don't want the consumer
to be replacing that style and also I'm getting a placeholder to provide it to the inner input element
that is the type and let's uh also we are going to get the type of the object we pass type of the
object of array actually pass inside the inside each item right because on clicking a location you're going to have
a dropb and auto complete here with some drop down on clicking that it's not just string we also have to get the lat long
of that location and we will move the map to that location so it's going to be an object it's not just a
string okay so inside that I'm going to return return the material UI component I'm going to
enable the Auto Select handle home end keys and this is the custom render input okay so I'm going to have a flux box
here I'm also setting the ref to this div and inside that I'm going to have an input box input element and a search
here and uh I'm passing the placeholder from here to the input element I'm spreading all the input props okay you
can also destructure to see what this has so this has a the whole thing that an input input
you will actually come back here to customize the component before customizing I want to actually see how
the component looks like by default so I'm going to have it in the left top and let's have the auto complete
here and import it import it from the atoms not from the material UI and it asks me the options is is
mandatory I'm going to pass a simple um array of strings chenai and New York so this is how it looks like we
have an auto complete and on clicking we have this data instead of this static data we are going to actually hit the
map box element so this actually works we don't have to do much but I am going to configure the Styles which because I
h effect and it's it is also a bit transparent okay you can see this okay so that is the input element
Next Step let's let's do that map mapbox call and we will actually render the actual places names and on clicking it
automatically the map will move to to that location let's Implement that to do that I'm going to create one
more component so here we directly use the auto complete instead of that we will create one more component that uses
auto complete that component will have the mapbox pitching logic so let's create a search Place
box inside the organism I'm going to create I'm going to keep it inside the map because it is related to the map
search places box. TSX first let's go go back to the constants I'm going to have an array
here called major cities locations info also need this location info inside the types I'm going to have this
location info which is going to be placed lat long okay which is say Tuple let's import that here it starts
so we are going to okay let's just use this okay that that the idea is to use this array of objects as a
component so this is the type the properties of this we're going to get the a function that gets the location
info and also the value okay we don't want that I'm sorry so directly I'm having this okay onet on
location change which gets a which gets a latitude longitude and zoom so this component Works inside the
a map component as a children as a child so that we can use this use map and this component is going to
return back return the auto complete so I'm passing the location info as a type of the data
of the item inside the array which is going to have the place name latlong okay let's create a a hook I'll
use search location I'm going to uh save the search text this is this text that the user types in
item I'm also going going to implement uh a use debounce because when the user types we
want to wait for some 300 milliseconds or so to avoid unnecessary API calls so this is the my implementation
of the use de debones we're going to have store the value and inside a use effect we we are having this
timeout and whenever it gets delayed basically and when the component unmounts we automatically
clear that time out as well we can use other libraries like rxjs and so on they have even further
milliseconds we will modify that wait for that particular milliseconds and to give back the debounced
value so we get the we have the search text we get a debounced search text and I'm also going to convert this into a
400 milliseconds that delay and then we're going to inside a user effect basically we're going to
fetch api. Mbox geoc coding places we are passing the Deb to search text here Json fuzzy match true so this I see that
it um does something interesting with some even with some typos it Returns the places name I don't
exactly know what logic they have behind it it's just a fuz fuz fuz search and I'm also passing the access token we
load loading state to false so basically what we are doing the return type I'm not I'm I'm not going to handle
that okay we get that we get the place name from that we get the lat long using the X do Center of one and this is going
hook we manage the search we manage the loading we manage a location info and inside the use we also debounce it
debounce the search text to convert to create a du to search text inside the use effect we are hitting the map box
API we get that and we create we return a new object with a place name and lat long which is exactly the type of type
we are going to pass inside the auto complete we set this here the location info and also we set the false in the
finally now let's use this hook and we get all this information there here we going to get the loading
State location info search text search loading and search so auto complete I'm passing the
location info the options is going to be if the location info has a length we will return that or else we going to use
okay maybe we just have to display that like no results found but y this is how I'm going
with this equ is option equal to Value this is options this property decides a selected value and since the
the value value we pass inside auto complete is not a simple string right so we cannot directly compare that we need
to compare the place name from the option and also from the value so that's why I had to add this
and this is no options text if the search text is is there and there are no options we're
going to give the no options so this is contradicting this right yeah I'm going to address that and
I'm going to move on if there is no no search Texs and no options we going to tell type
something so the options label the ex is the whole object and we need the place name that is going
to be the option label the input changes I'm setting the loading state to true this load the set
loading comes from the this hook okay also we set the search text the search text gets set it gets it gets debounced
and then we do the API call and we get we set the location info also we see we get the loading and
we set it here and on change you're going to get the value this value is going to have the lat long
and the place name and we got we already got the instance of the map using the use map and I'm going to use the map. FX
fly to to you to fly to this location and I'm also setting a zoom here actually we can go further like the
location it's going to vary okay so we can set the zoom based on that if we use a select a state we have to have the
zoom in a higher number I mean lower the higher Zoom rate right we can we can do that but I'm going to
keep it simple essential makes makes sure that the animation works it looks cool so I enabled
that and then this is the call back okay the on location change this function is going to set the
form state in the form we want the location we also said that this is the search search place
places boxes box let's import that from the organism that's it now let's give it a
try this is the component when I'm not typing something when there is no result this is the that
remember Zoom is 14 and that's why it got assumed maybe let keep it as 12 let's also go to can
I take some time maybe in the production in production uh application we should not have this level of
Animation also you can see that the location filter is getting updated so that is the lat long the boundary for
API uh call so we have this major cities let's go to Tokyo which is not here we get all these places names
actually that must be a different Tokyo yeah still that is some some different Tokyo that is
that's Japan but a different Tokyo different place okay so when I disable this essential which we should
here okay so that's it we when the zoom happens the location filter also updates when the move happens when we move the
map based on the location using the auto complete the location filter updates when we drag the
query and we will render the results okay so let's um let's add the start time and end
time and also we'll see how to fetch the data here let's start to use the so remember
filter remember we also have uh this here the location filter with the same name so basically we can do this set
the date I'm going to okay so we need to make the page we can do two things one you can
a we can actually export U make this a search page content and we can expose a search page by actually wrapping the
search page content with the with this but I'm just going to convert the page into a client
component now the error goes away have this I'm going for the dates I'm going to do something for like
uh um based on the times I'm going to show the a different icon like sun night sunrise sunset those kind of stuff I'm
going to create a component called icon types I I'll just past that in the molecules and we'll go through
that the icon types let's focus on this one okay based we will pass a time and we get the
hours from that and based on the hours we are basically returning a different icon Sunrise Sun it is from 10: to 4:
and after 10 to 8:00 in the night we'll be having the sunset other than that is night right
later back to the search page component I'm going to so this happens inside the SE search
absolutely positioned icon drop down icon arrow down the icon type is the component we just create
component this has to extend all the way okay so I'm going to wrap everything inside another div and we
accidentally click CH I accidentally this is the uh start time and the end time we don't actually have
the start and end here but the arrow shows okay you can make it maybe better but if I have somewhat something like
component Al we set the date and also we get the register button register function and we are registering the end
collecting the let's just watch the entire entire thing let's call this form data and we
time and let's just console log the entire form data so you you will see the location filter and date filter are
coming from the default ones but that it takes the end time that is 1 hour from now start time 1 hour from now the
location filter is already fixed right even before before I start interact it it imagines the start and start and end
at end time to be the current and 1 hour from now and it also finds the bounds in the map and it sets the location filter
actually we have all the information to do the base to do the query and we are going to have the have
everything is fine I'm going to have an a different component called show garages in here this is going to be an
organism show garages TSX so inside that we are going to actually get all the compose the variables and we will do the
document going to use use lazy query because the query has to happen based on the variables okay when the
variables changes we need to refetch that and yeah use lazy query comes from the app client use lazy query and I'm
going to pass the search garage document so the lazy query is going to return an array first one is going to be uh
mutation um the function to query search garages and then we can get all the called loading
data and errors error okay and then I'm going to just return and fragment with uh we'll just
Loop through the search garages and we we're going to have a garage marker that is going to display
the data as a as a parking slot let's do that we also have to do a lot of uh thing with the
variables and whenever they change we have to refresh also for for now I'm I'm just going to use a empty use effect
and I will just all the search garages here let's create the garage marker component let's place it okay actually
we will keep these these two inside a folder called search I'm also going to get the garage
marker inside it so the garage marker it's a dialogue we first we initially we will just show
display this dialogue okay on clicking it we we render this we switch this uh State popup State and it just theog
opens and it will just show the marker ID or now but actually we are going to have the entire booking flow inside this
dialogue yeah this is the code we just have to do a few changes like because the transition do child is try
panel okay that's it also getting I'm getting the open and set open that's that's okay that we
manage using a simple use dat from the consumer of this component we have we can pass any number of children using a
react node we also passing the title here and the class name and the with the class name so the class
name I think we don't need the class name here okay so I'm going to have the class name
here but I'm not using it here but the with the class name is being used the dialog panel
but we can change that if you want more we have to pass Max withd large or Max width extra large that is the dialog
presses Escape we want to actually close the dialogue so for that I'm going to create a hook called
use key press I'm going to create a inside the hooks I'm going to create the keys while the use key
press basically gets the keys on the action though we are getting an array so when that keys inside any of
those keys from that array gets pressed we are using the window or add listener ad event listener and we we will also
box be anything but in this case we are going to close the popup fine let's also import the parking
icon okay let's create the working account the items which which is just a p we have a border border black BG
primary there some Shadow with a p okay that's a parking icon okay that is all about the garage
marker now everything is ready let's have a demo I think we already have a park having have a garage
this fine so right now we don't have any garages in the nework but we know let's modify that
this let use the use form context again we will get the end time start time location filter and when we do this
we will pass the variables date filter is going to be end is end time let's Al maybe let's rename
mandatory I don't remember why I made them optional in the first place but now we can directly pass the location filter
now we are seeing the parking so that is the garage so it happened to fall into the this the
dialogue and it shows the number so we need one more thing we are going to have a u filter icon here okay on
clicking it we will have a sidebar and that sidebar will give us all the options like we can configure the what
height we want what length we can filter basically filter the types of slots filter the price per hour all
those things so this is going to get really complex okay so I'm going to create a create
things okay so what I'm thinking is let's just go with with this with this in the sense we have a component we
watch and we are calling that right so later we also have to add more things like the slot filter which is which gets
the height length hype Price Power Hour and so on I think this should do so I'm going to
simplify right we'll just go with this and um we'll see if we need to have a separate hook with all those
page the show garages right now we are simply getting the date and filter and we are using in the PCH function from
the use lazy query but this time it's going to be a bit complicated because we're going to
have filters that include length width height price per hour type and also Skip and take for the
pagination I'm going to create a an an adapter in the forms Library I'm going to create
types so I just take the form type from the search garage of schema and I'm going to pick the times height with the
dimensions price for our location filter skip take for the pation you're going to have a hook
called use convert search form search form to variables so basically we are going to return the
encapsulating inside the say this hook all the logic that goes into creating that filter and it's not
straightforward here we are just giving the end we're just passing the end and start but we
are going to deal with the ranges here like greater than or equal to less than or equal to and we're going to
complicate this this component so that we are taking these complexities out so search garages queries variable comes
okay search garages document and we have it here that is the type of the variables so I set that type to the
use State that's the variables and let's use the use form context let's also pass the type here
um we can do one more thing like instead of the watch you can do use watch and you can also pass the type
here and you get get all the data here okay the the thing is we get the dirty Fields so we have the default value set
up in the here right we have the default setup but if the price per our field is not dirty if
the user has not touched it then we are not going to send that in the query that's an unwanted filtering right
that's so we are taking the dirty filters and we are going to just make sure that we only add
field so uh everything is a Boolean if the if the value is different from the default value then that is going to be
true fine so I'm going to get this as a form data and I'm going to use the use debounce to
whole data okay we are going to debounce that whole filter data that's going to include the date location filter the
range filters for the height width so on type is going to be a group group button radio group something like
that okay so we get the form form data for dir FS from the form State we are debouncing the form
data okay now inside the use effect first let's create the date filter const date filter
just creating this date filter we getting the start time and end time and uh assigning to the end we are just that
bounds and we'll use it here and the other ones the slot filter and the garage filter we
width height price per hour and the type all these five things and the filter is going to be a bit complicated so I'm
the we give the data in a tuple format and it's going to return back in this format greater than or equal
range let's use that I'm going to create a function called U create slots filter and these are optional filters
right let me just copy paste that we have to look for the dirty Fields there how do we get the dirty
Fields field names marked Boolean when we pass a type of the schema so we basically we're going to pass the
length yeah so if the length is there dir do length is going to be true right if it is true then I'm going to
so we do that for all five times for all five Fields it has to be dirty and if it's dirty we will use it and the type
is different so it needs an in followed by the type and this type is actually an array maybe I should change this to
form State the use form context also we have to pass the form form data I'm going to do that okay
filter this is going to get the Skip and take we may add more if you want have more things to
filter based on the data in the store in the garages table the Skip and title take our dirty
here now we have four types of filters let's save them into one V one filter and we have to set the
variables can also do this okay so basically we created these four filters and we are assigning that
destructure from the debom form data and we will add the debom form data in this dependency
AR okay that is the hook I'm going to go back to the search garages page show garages component and instead of doing
slash search bom adapter and this Hook is going to give back the variables and we can just pass the variables
there okay I think we don't have to rename this and assign it again okay this thing will work we just get the
location filter directly from the form data and we attach that to the variables now here it is saying that null is not
assignable to the this thing the basically we assign variable to search gares query variables are null
variables is not is through the okay if it's through the Then I then I am passing that okay I think we are
good now the page let's first check the Geo query that's the only filter which works right
now Network we have it when I scrolled it we get nothing because we have only one gun gar and it's not inside this
working let's also quickly see if the I think the start and end time is also matched perfectly fine now let's start
uh this filters the slot filters let's work on that so inside the search I'm going to
create a filter sidebar. TSX this is going to be a sidebar we're going to um manage the open and set open
ourselves and then I'm going to use the use form context Al are the types because we have input
here first is going to be the button remember the sideb we already have we only expose the button and on clicking
the button the dialogue or anything will open here we will be using the sidebar component icon filter comes from the
and we use this dot to create to show that a particular field is dirty or not I mean accessed by the user or not I'm
going to get the base components types and uh get the children if there are children I'm going to just pass it we
it's going to be just a width to height to height to actually the rounded full has to be
here and it's it's going to be absolutely position top zero left full and we have we have that
anime animate pulse and if we have children then we have uh almost the same thing with some
padding on the same location absolute top zero left full that is the pulsing dot if the Dirty Field is uh if the
at least one we are going to have the pulsing dot in the button itself showing that the user has modified something but
actually I did a mistake here in my practice project I was thinking that if the if I if the do Doty fields. length
is there I thought it's the a number of items inside that but it's actually a field basically we have to do object dot
values of so this will convert this object into an array and then we will take the length to be through the that
okay I think we we have a small problem here we need to keep the set open outside okay we have to update the
header also header component and then we are we going to pass the make it open and set open that's
now we need to we need to switch it switch the state okay I think we are good what happened
here so we need to update the head open State type to use this so how how did I come up with this property type so I
just hovered over this and I got this type property and um I'm using the type as the property but
page I'm going to have another panel this time it's going to be right top let copy paste that and then modify
now okay so uh I simplify change a few things so first one I was I created this nav sidebar component so basically and
I I put this button with the icon menu and the sidebar and all the menus inside okay I simplify the sidebar right now
transition I just divided that into uh two things because in the filter sidebar I Al I already have a button
and everything thing inside it we have to create a filter heading basically that gets a title and dirty
Boolean and we we use that we also use the pulsing dot to show that the filter has touched has
we are rendering that going to be a relative because it has to be relative because the pulsing dot is
sidebar let's start with the first one the type so for that okay we we have to actually create the range slider and the
to create a range slider ESX so basically I'm getting the slider and the slider props this
component is going to get the slider props the whole thing lives inside a div with the width full with some padding
top ping left and right and we are having some opinionator Styles here with the value label on and then I have some
Styles so this we already did in the auto complete auto complete component also we did the we configured the
that again I'm just re-exporting it right I'm renaming the it I'm renaming the toggle button to toggle button mui
I'm re-exporting that by having some styles here okay I'm making some giving some margin top making it
block similarly here also I'm having some Styles and then I'm having some open props like disabled
Ripple disabl touch Ripple and focus Ripple so these are the two components let's import them from
element I'm going to use this controller from the react hook form and I'm giving the type and uh
since I renamed this to types it is complain so when I change that it it is fixed I have to pass the control from
the use form context to the controll element and now we get the values here values and that particular so we have we
get this dirty Fields Collective that has everything but that it has everything right booleans for each field
we have in the form schema but inside a controller it's a controll component we can get is dirty
filter header we have imported the hugle group tle button group and uh okay so basically in the on change
correctly it is two step out fine now the toggle button group will work basically on change I'm going to get the
here okay sorry I have to set this here okay we setting the value here and then this value is this
value and then I'm I'm going to proceed to display all the so I have this icon types comp it's an array
basically it returns back an icon based on the enm type for the bicycle I'm using icon bike bike motor bike car and
toggle we see this dot which is not a DOT so let's uh see what's wrong so I have this rounded
full it's absolutely positioned what's wrong rounded full okay you might have seen that but
actually I'm setting the color to the parent okay sorry so now we have the dot which is
animating so yeah so I'm going to give the animate here because if I add something some
uh cycle you remember our garage actually has a few slot slots for bicycle and car okay one car and to
the APA call because we already did that we already did that very query with all these combination let's try with the
actually trying to demonstrate that when everything is selected which is this we are not going to see the slots
filter at all that's what I wanted to show you and when I when I update that you will see the slot filter with the
updated with the selected ones and also you can see the dirty marker the dot being and also this is client s side
caching okay so it is going to save a lot of performance so let's create other ones with the slide range
component let hide that this is also a controlled component I'm using the controller and we it knows
what values it can get it's a tuple an array with two items passing the control again and inside the
and in the render I'm going to return a div with a filter header with the title and the is3 I'm going to get get the is3
from the field State this field State this is3 belongs to the price per hour field and in the range slider I'm
setting some steps this depends upon the range right we can have some other field which can
can be in thousands for those fields we cannot have the step as five it's going to be a lot more granular and we will be
doing a lot of API calls so I I I kept the steps outside you can also have some property set here okay if you think all
the rain slers will be using the same properties same value for the for the particular property I'm also making the
min max from the default values getting the value and down change as it is and I'm also adding rupees but actually I'm
product dollar okay let's have a look at that this is the range slider so the maximum is 200
that's what we gave the pick is five I'm going to change this to 10 okay five would
work this is casted as well okay so I drag when I'm dragging the network call is not happening so it is waiting for
just a debounce okay it's not it's not waiting for me to remove my mouse pointer from that it's just a debounce
that V setup we have a debounce for 400 millisecond okay when I'm doing this no network all is happening but when I
125 nothing happens but when I do the 130 we do the API call okay so I think you get the point like
debouncing debouncing and local caching I keep explaining that let's do the other ones it's going to be very similar
to the price per hour also you can see the dirty ones okay dirty Fields the third one is withd it's going
use form context we get the value on changing state is dirty default values similar one maybe I think we should get
the default values we passing the value and change as it is and um here we are going to add
0 to 20 the width okay so the step is two fine and also we have the caching going on if I do this and get back to
the zero you don't do any network calls when I set that to 10 Network call happens when when I move this to get put
back to the 10 nothing happens Let's uh do the for the high height and uh length they're going to be
very similar to this width okay again we are getting the setting the height setting the control
getting the value and change from the field dir default Fields this component we passing the dirty and title to the
field header we setting the min max from the default values value non change from field and um same feed here step is two
same thing goes for the length also that's it we have one more thing to do which is a reset button here in the
button under all our filters I'm going to place the a button in the reset I'm actually we have
to reset back to the default value right so this get values is an alternative for the watch and the use
uh actually I'm confused why I added this I'm going to remove this for now and we will see the reset button in
action you can see there our uh pulsing dot is there that means that we have we have one field at least one field
values okay yeah the point is we want to retain the location data and the time data right that's
why I had to also give the get values this this get values is going to have the date and location
filters and the form the default ones have the price so these are these are the things are going to be reset back to
filters okay now I'm actually thinking I should only have the reset button when the when there are dirty Fields right so
resarch field won't be there okay we don't have a resarch field now and now we have the reset button on clicking it
disappear disable the button and now it looks like this also we have some hover animation going
on to fix this we can H we can add this enabled colon how colon the color so now we won't have
enabled and I think we have we have to add it to the other buttons as well okay that is the filter now we are
one okay so in this section we are going to deal with the we're going to build the booking slot flow so basically we
are going to get the start and end date from here end time from the from the form the search garages form form
data and we are going to have another schema form schema here we're going to have a booking form inside here right so
we will transfer those information into this and we will let the user select the type of the plot and
also we have something a valy management section where people can optionally add valys for picking up dropping or both
going to have start date and end date start time and end time vehicle number and phone number
number okay so I I kept the validation to a really simple one here we are just checking for that the phone number has
to be at least one character but we can have more can further strengthen this validation and we are going to use we're
types so that's it and then we going to have an internal a nested object here so this nested object is going to
have pickup info drop off info and different locations the Boolean and let's get the location
info location info is going to have lat long the distance We Will We Will calculate this distance at the time when
the user fix this location we calculate the distance and we will store um yeah also optionally we have
um the notes is for the delivery notes in the in the food food applications right we have notes I added this in the
schema but uh I did not Implement that and this is the schema and as usual I'm also going to
infer the types using the Z infer anding the schema here we get back the type form type book
slot and also I'm going to have just like how we did in the search garages I'm going to have a further
function you might have you might remember we already used this a similar thing in here okay I'm going to reuse
this functions I'm going to copy this put inside the util TS we also have to export the problem here
required data just start time for the E start time valid function and here I'm going to actually
pass an object because we have more than one argument so it's going to be confusing start time and the end
time those are the two functions first let's fix the search garages first I have to import
so we can basically get the values from here and I will pass the start so the first one only
custom validation using the zine I'm going to create this use form this we have been doing for a lot
for everything right so keep doing this we use use form we pass the type as a generic Al we use the
Zord resolver from the hook form resolver SL we pass the schema here and we get the form management hook that's
what we are doing but additionally I told you right we have to actually somehow pass the start time and
why that's why I'm getting the default values here okay and also I'm going to create the use of the form provider book
displaying the garage ID we will go back to the garage card garage marker this is the dialogue here I'm
going to use my provider F provider book slot not helping me I need to import it myself book
slot provider and here I'm going to create um we have to do two things one we have to pass the
from yeah we going to use the use watch use watch from the react hook form and we can Al we also have to pass
I'm going to create a component called book slot popup inside the organisms I'm going to create book plot popup do
TSX but this this thing gets the garage information first the garage information we the type we get from the search
popup also I have to pass the garage the garage information we get to the garage marker is named as marker I'm
here and just pasting the let's let's um use a pre- tag and uh we will display the whole
information okay we get the address have the available slots we have the car bicycle we have two slots for bicycle
providers we use hook form for managing the states the filters and so on and we have this form provider for the book
access we cannot access this use watch with this type inside this dialogue okay it's a different context
okay so here I'm going to start using the use form context okay so we just got the control
register handle submit uh set value errors everything for the book slot form and let's match the we have the set
required let's create the form I'm going to have a flux box with some Gap text left with some
information about the verification verified State and the garage name need to add the display name from here
variants here basically we get the variant variant here and based on the classes we assign that okay that is the
other than what we have here and that that helps us really manage this let's import the badge
okay 1 2 three nework the style looks a bit weird but I'm going to just go just go with
here I I wrote a simple gel Auto Image changer that's what I'm going to call this caral autoimage
component I st store this current image index in use State and inside the use effect I'm
going to have a set interval use set interval to change this index so basically we know the length of the
images array right so basically I increment it and then I use this modular to reset it right if there are four
Images we want the index to be 0 to three when it goes to four it it it this will reset that index to back to zero so
through and if there are no images I'm going to just return no images with a photo cancel icon from the
Tabler icon icons that's it and I'm going to return if not if the images array is not empty
I'm going to return this so basically this is the image we're going to have we going to get the current image using the
current image index we are giving that and we going to have the arrows yeah so this is the dots we have
index of image is actually currently is showing and then we have two arrows the Chevron left and Chevron right on
clicking it we will update the indexes proper appropriately both both are buttons absolutely placed
buttons that is a simple carousal now let's go back back to the book slot popup and we will Implement
also if there are no images we are passing the Mt array the duration per image is 10 seconds this is in
okay maybe that's distracting I think so the auto Chang is disabled the arrows will still show up and the customer can
navigate between other images right and if it auto changes in the booking slot it's going to be
component we look at the start time end time it gets the difference it sets the duration the duration is the difference
okay and we have a flex box here first we have the start time we're going to we'll show the time format time with
color we need to create this uh functions let's create that we're going to use date FNS
install that library inside the utils Library also we use the form time so the difference is the format we pass in this
is the format of the format date this format of the format time now let's import the data fness from the format
milliseconds and we will generate okay so based on the required unit we are returning the that
okay and the last one is get time units so this basically returns you just get the time I mean the time in
milliseconds the duration and we will return number of days hours minutes and the final time
string and also for this Pro for this we need to use the pluralize pluralize Library let also import the types type
project let's add that I'm going to copy some configurations from the forms Library maybe we don't want that but we
okay we have we have all these date manipulation functions we wrote a few things uh we got help from the data
time where the time will be bigger here and the this format time and format date and the date will be smaller we'll be
this the booking book plot after the auto changer I'm going to just place it passing the start time and the
automatically identified it the duration is 1 hour we can have I'm going to change the end end time now it says 2
hours and 4 minutes it also shows the time date time end time and the end date okay now let's
have our form information first one is selecting the slot type we already did this the radio group with the form
filter while selecting the types of forms so this is again we are doing controller okay so this time I'm using
component we going to pass only one type the last filter form we used types we could we were we were able to pass an
types inside an array but this time we're going to pass only one type this is for the booking
information so we get the control you pass the control to the controller we get the onchange and value here and in
the radio group we pass a on value on CH just works as it is and we get the available slots because we want to
display only the slot types available inside that garage then inside the radio this is the component sample
radio group and we will create radios okay those are the like options and I also we can we can Che
passes uh properties like checked autofocus disabled Focus however and based on this I'm changing
rendering this different icons based on the slot types that is the radio group I'm also
component okay I think we are passing the different color here yeah we don't have the b yellow
color we we have we will use the primary one okay when I select that is the component also I'm
going to listen to the values we already doing it let console log it so that we will know that we are actually writing
so I actually found an found an interesting thing if I conso log these values I'm getting an infinite Loop
okay this is a bit weird for me but if I comment it down comment it out the infinite Loop stops okay I I
need to open this okay okay the infinite Loop stops that's uh something is new for me okay
I'm not changing the anything and I'm just putting a console log and uh I don't understand I don't know why that
happens let's keep moving our dialogue as plot type and I'm going to add the time also because people yes people use
same time from here but still I'm going to also have a start time and end time input boxes here
custom error message here because a lot of time I come here I come over open the dialogue and I I forget to select any
types okay actually we can have the the other form elements to depend upon this value and we may Design This flow in
such a way that none of the other form elements show up until I select the type but I want to simplify that I I'm I'm
is just some exclamation Circle and red gr text red text with an error okay just the exclamation Circle has a
red text and the error message is going to have the gray 800 900 if there is error basically if the title type is not
there we get the type from the use SWAT and if the type is not there I'm going to have this error set type
okay and I select it it goes away let's Also let's add the dates now that's the times start time and end time
the date time local okay and these are not synced when I change this this de is not going we
don't have any connection there the connection happens only when we open the dialogue when you open the dialogue the
dates are all synced with what we had earlier and when I modify this it won't actually go back and modify this
type these are basic form elements we have seen a lot of times title error and we are using the register function to
register this phone number similar thing happening here we are making sure that the minimum is not
well then I'm going to create simple cost title value it's going to get the title and
price and it will just display along with the dollar symol then we are going to you will need
we have the date the duration the number and then we will have also create a valy management in the upcoming
section uh now we have to display the total value and then we will start working with our stripe payment button
and so on before that I'm we need I'm going to create a hook to to create price to create
prices so this is the type you're going to get the price per hour uh we we create a hook called use total
difficulty importing the jsx that has a provider actually so I have to configure the jsx in the ud Library also the jss
is is equal to react jsx now the typ will error will go away so here we are going to have a
charge first let's generate the parking charge so we have parking slots have uh charge price per hour so basically we
take the start time end time we calculate the difference in milliseconds we calculate the difference in hours
then we just calculate the price parking charge and we set that here difference in time comes from the
date here we already used this function in another place here right date range booking info we can we use the same
here same function we are using to get the millisecond difference in millisecond and we are just
calculating that to the price and the second one second UC effect we are calculating the valy charge so this has
to be saved in a constant we already have a constants file in the util I'm going to place it here so this is a
kilom and let's import that that's it so after the two use effects I'm going to
just return the parking charge Valley pickup charge and Valley charge drop off now in the book up hookup book slot
popup I'm going to use that hook okay let's also restructure the price per hour from the use
effect oh sorry so the price per effect comes from the garage value garage that is when the
the price per value it is we calculate that by going into all the available slots and we already have this this is
item based on the selected type and we are getting the price per hour from that and we get the total price object that
has the parking charge parking charge valy charge drop off Val charge pick pick up now we have all the required
created this use cost title valueing the title parking valy pick up value drop off and I'm passing all the charges
everything so let's look at the interface nothing is showing up why okay because we haven't set the type when I
$250 okay so for the first iteration I'm going to just continue to work with the swipe and
payment and then we will come back here and we will create the valy setup till that it's not even showing
the valy cost because we don't have a valy okay so I have to Let's uh fix this finish this
booking yeah so we need to create the mutation okay actually we are going to do the booking through a rest API
Endo so we need to we need to manage the booking status ourself so here we are not going to use uper client so we won't
clicking okay so I have not we have not set up the on submit here on submit use the handle submit
that have the dates on clicking okay so the form did not submit because I have to enter the vehicle
okay so I select this I we have the okay so again we got the infinity I have to set this Val form
and end time on clicking it we get the form data so the form is getting submitted now we have to collect this we
are going to hit the rest API okay so we will set the rest API in the back end and we will come back here
to continue with the righte payment so before we need to First install the stripe requirement
controller just like the resolver and then we will have the business Logic the code in the service file
also we are getting the booking service we adding the booking Service as a provider because we are going to
actually hit that when the payment is successful we are going to use the booking service to create the booking
controller let's create the controller and I'm going to decorate that with the controller decorator I'm going to call
stripe okay so you need the so you need to set up the stripe you create a stripe account and
you in the environment variables you have to create these envir variables right publishable key create
the copy that paste it here get the stripe key from your stripe account SEC and then the success key is going to be
3,000 SL stripe SL success we will be passing this checkout session ID to this stripe SL success route okay end point
and from that we will uh retrieve the session information and then we will if the session is information is valid then
we will actually go go ahead and create the booking also the cancel URL booking failed we will create the a simple page
module now can we get the hello stripe okay so that's working let's create other routes
we're going to have a post route that will create the session basically we're going to hit the
same thing with the post route let's get the create strip dto inside the strip I'm going to create
this D folder we going to have this uid total price object on the booking data we need to have
up and the that is a dto this the information we are going to call when we hit the we are going to pause when we
this now we have to create a create stripe session in the stripe. service so we create this method we
session we get the Stripe from the here checkout. session. create I'm going to add the payment method as
card in the line items I'm going to the object this is an object object with three keys three properties like the
payment the parking charge valid pick up and valid drop charge I'm using U object or entries to convert
that into a key value pair of arrays first thing I'm going to filter that the price has to be greater than
zero because we can send a value charge of zero and we don't I don't want to show that in the payment
page and then I'm going to Loop through using a map I'm going to get the name and price
will just convert the string into a title case that all the beginning words the first letter of the beginning words
ID and then I'm also going to set up the meta data this is the data which we will pass and in the success route we will
get this data and U we'll create the booking that's it so we create the session and then I'm going to
return the session. ID so that is the create session now it's almost ready the back end is
almost ready we can create a session we'll come back here to to handle this success one but before that I'm going to
go back to the book slot popup and we will set up our stripe in the front end so in the UI Library that's where we
have this components I'm going to install stripe at stripe SL stripe Js in the book slot popup in the on
and we can access the use session from the react um next O next o/ react so from this you can we can get
seen the syntax I'm spreading it and only if the payment info is valid payment info and drop off info are valid
if both are valid I'm passing the information here and I'm spreading it if not we are going to just assign the
nothing okay so that's how we generate the booking data once we generate booking data I'm going
to manually I mean everything okay it's inside a program but still we are handling it ourselves right in the
create booking session we are going to generate the looking session let's uh create write that function and we'll
types okay so this is the type we are actually using in the back end also booking is coming from the generator one
create booking do input first let's just hit the rest API we just created right API URL SL stripe
a post that's we that we did here stripe controller we have a post route we can hit the create stripe session and we
also know what the DT is U ID total price object and booking data here basically we are hitting that rest
GPI using FH and I'm also passing the body by syn by um stringifying it once we get that we are going to
publishable key from the next public typ publishable key so you have to save your publishable key in the en enir
variables of the front end the back end requires both the secret key and the publishable key the
front end only requires the publishable key okay so let's load the stripe now load stripe comes
from the stripe package we installed um I don't know why I have let's do this so I'm I'm loading
the stripe there and then I'm going to redirect the checkout so this checkout remember this
returns back a session ID right so since we are handling with rest API we don't have any type safety we don't know what
this session is going to have it's any and then I'm just going to return the result fine now let's go back to the
onsubmit and uh we will continue the process here I'm calling this create booking session we have we can mark this
okay so we have to modify this okay um initially we have like um we added everything other than the
cre updated updated and ID so we need to modify this so I'm going to use the pick type I'm going to pick the customer ID
information so I'm going to this is the custom create booking input okay so we're getting the customer
ready End Time start time vehicle number phone number garage ID type price per hour price per I mean total price price
now the booking service is creating a problem since we updated the create dto it does not have the all the type
the values we received from the dto first I'm going to make sure if the customer it could be it it is possible
that the customer is doing it for the first time probably we have to do something like this in the onboarding
page and after the user registers in the onboarding page we may have to um allow customer to create a
project so I'm making sure that we have the customer here or else I'm going to create a customer entry for the
uid so once the customer is created I'm going to generate a passcode I wrote a simple function for
this let's put that this util function util file it basically it's the random this and we will get the
passcode and then we get the date as uh time as string in the DT so we have to convert that into
dates then I'm going to we need to create a we need to find a slot right the user only mentioned the garage
ID I'm going to create a function get free slot which gets a garage ID start time end time and type here we are going
to get just get the first item the conditions are it has to be from the same garage ID it has to be the type the
start and end dates we're getting the free slot so this slot has this ID okay that's the picked
slot if there is no slot if something went wrong meanwhile when the user is booking someone else booked already then
passing the end time start time vehicle number all this information other than the slot ID comes in
it optional everything is required by default and we are not making it optional if I make it optional then the
error makes sense like it's saying the slot type slash slot type Union undefined is not assignable
data type is notot type here also the type is notot type yeah so I was actually getting the
and it is giving the wrong value here but when I click it we get the validation there okay at least we cannot
submit the form with uh with this data I abdate that every 2 hours $6 I'm clicking the book
01 clicking it's processing it's successful and it's going here right 3,000 stripe SL success and the
session ID we are getting this now what I'm going to do we're going to set up the sess the success end point in
URL all those things and we'll set up that and we'll come back here we we can just refresh this URL okay so that
everything will just go on the session ID will carry the cycle booking information okay let's build
it the controller I'm going to create this the success it's going to be it can be called like URL / strip / success
it's a get route and we can get the retrieve the success ID the session ID by this query
parameter Al we get the response if there is no session ID I'm I'm just going to throw an
error and I'm going to retrieve the session information that is happening by getting this
here and from inside this session idea we can get the uid and booking data from the from the session.
metadata let's then um create the booking in Booking input I'm going to type this using the create booking
booking using the booking service. create so we just wrote this service right that generates this passcode we
page okay so we have to import the response from the express okay so that we can do the rest
start redirect to the URL I have already saved it now we go back and um okay let's just
um create the a simple page for booking bookings SL page. TSX create a dummy page and then we will
come back here to to fetch all the bookings for the user and we will display that we will we
need we also need a bookings failed booking failed booking failed we will also quickly test
that page booking failed okay we have both these P dummy Pages now I'm going to Let's also look
information right now we don't have any bookings okay going to just refresh this this session ID is going to
refreshing fine so we are directed to the bookings that means that the booking has happened price per hour three total
and also I wanted to show one one more thing now when we go back click this we are going to see one
car and one cycle opening previously we had two cycles opened right I booked one and with this within this period there
failed okay so I click this the remaining yeah and also one more thing did you see the previously the cycle
price was three right because that is the minimum cycle slot available for the customer at that
time and that is booked now now the minimum price is $4 per hour and that is getting fetched now okay that is a
business logic that we are going for okay okay so I'm going to book that does do Cycles have vehicle numbers
number give it a phone number going to book this and then going to cancel the booking back now we get to
the booking failed page so here we can show some messages like well the booking has failed or something like that you
can book it again you can search for again you can have a search link all those things so we just
successfully did the booking we went through the payment the upcoming sections we will um we we
actually have to introduce the valy management section and we will set up the bookings page and so
on okay so um we have we can now do the booking without the valid assignment yeah we are going to do that
so I'm going to go to the address and um so I manually created this so basically we just have to H in minus 74 we have
that let's create a component called loader I'm going to create that inside the molecules
two two components from here one is just the loader which is the icon with the animate Spin and the other one is um
loading so we have to keep that inside the show garages when it is loading if it's loading I'm going to use a panel on
the map panel the position is going to be Center bottom and I'm just going to add the loader which is the icon with
Circle along with the message no parking slots available if the data. search garages. length is zero
now when there are no markers available we will be showing this error message and also there is a loader which quickly
information okay even though we already we also have the value assignment information stored in
the EM also here right we already have that we are already sending that but now we just have to get the
value from the user so in this form we're going to have a section here with a map with draggable markers
locations okay so first we have to update the API this is the booking input we have to now pass the valy assignment
so I'm going to create going to go to the create value assignment input I'm going to create a
float I don't have to add this right so this is what we are going to get it's just the
location pick a lat long return L return lat long maybe I should call this drop off flat long there is some
inconsistency in the naming but I'm going to just move on yeah so we have updated the create
assignment is true I need to add this object value assignment create and then I'm going to
to you can do just do null so basically when you destructure n you will get nothing but when destructure this object
create this is exactly what we are doing in the create I'm just passing that the object we we
get but we want to add this only if the value assment is is valid the object is valid that's why we have we use this way
directions so this directions is responsible for getting An Origin destination lat long lat long and then
we will use the mapbox API to create a a path directions just like Google directions uh it generates that and we
the react map GS source and layer tags require it's like a key property when you Loop through and when we create
items we have to pass we have to try to pass unique Source IDs I think we have the latlong okay I'm
going to create this lat long in the types in our util we have a types file here I'm going to create this lat long
items let's import that let's store the coordinates and set coordinates using U State we also need
inside a reference so that it won't trigger reenders I'm also going to debounce the
for a direction to work we want both the origin destination we need two points to create a direction if one of them is not
there I'm just going to set the set coordinates set the coordinates to an Mt array and this I'm and just I'm
returning I'm ending the use effect there if not when we have both the origin debound and
destination debound time basically I'm hitting the ap. mapbox directions ver five mapbox walking so
that's by that's what I'm going with you can we can further tweak it actually so we have different vehicle types like
cycle heavy car right bike so we can actually get the type and we can pass it here but I have I'm just simplifying the
process that would be the right way to do actually based on the vehicle we have to actually pass different in the method
of um directions and I'm passing the latitude longitude of the origin and destination I'm also
simplified I'm going to use an if okay immediately invoked function execution I think basically you can create a yesing
do synchronous operations that's how you can do uh you can use a inside a use effect so we get
coordinates so I was like going through the documentation and doing a lot of trial and error looking at the data
through that and then you go through manuver and then I get this okay I was not so I took a lot of a bit of trial
and error to know where the how how to get that particular information which we want for this
case we got the coordinates I'm setting the coordinates and I'm also getting the distance from the
data remember first we have for getting the coordinates we did all these things and for getting the distance uh I'm
going I'm doing this we already have the the distance stored in the US basically I'm making
distance okay that's it and then I'm going to create a line string a sequence of line
string so after the use effect I'm going to create this using an use memo so only when the coordinate
changes we will just return we will generate this object it's a feature with the geometry of line string
data and then I'm going to set the line color and the line withd using the paint option okay
basically we are just creating a layer I'm I'm generating this uh coordinates into a l line string geometry and I'm
passing that inside a layer I'm also modifying the paint modifying the line color and the width using the paint
and in order to satisfy the typescript I'm going to set this as as const so we cannot pass any other value
there other than this particular string okay it's not just a string but a feature and line string now typescript
set distance a call back function to to return um to set the distances distance between the two points that that is a
calculat distance that's not just a distance between two lat long two coordinates it's the distance that the
I'm going to create a component inside organism manage val. TSX so this is also going to get the
called use show wet going to get the lat long from the garage value and if there are no G no
value of the garage that that must there must be something wrong right and also I forgot to add that react toasttify so
using the alert alert for now which is not a bad thing but a toast is much more modern in the UI I'm going to install
TSX I'm going to import the toast container toast and slide I'm going to export the toast
react toasttify to see what other transitions they have and you can use them I'm also re-exporting the toast
and fine so in the layout I'm going to add this as a the body I'm going to add the toast
now we can call this toast function to create that toast message from anywhere we want so I'm going to import that from
the molecules you can directly import that it does not make any sense but any difference but
provider the form provider for that particular booking book slot EMA we get the this this is what we will
use to set the locations the pickup locations drop off locations and also we need to listen to the value information
light going to have a title valot some paragraph text or Val with Will whisky your car away to its reserved
component import the switch as H UI switch because I'm exporting that in the name of switch is going to get the label
children checked on change class name I think the Headless UI wait a minute let's let's look at the
I'm going to quickly just use this as an example Hy switch and I'm going to pass the check
looks okay so this switch statement will be managed with the use show valy the state we store here and on change we see
the value and if it's false we are going to set the value to undefined okay the whole the value in the sense let's go
optional so we will just nullify that when the person clicks that show valid disables the show Val then we will just
are going to get the lat long from the garage and we will set that to the pickup and drop off location so when the
itself okay and then the user will drag from that garage to wherever point they want that's the manage Val I'm going to
total cost total price I'm going to use that let's have a look at that know to solve manage
so the switch button is not working properly I'm going to copy my earlier the switch component from here and
defined let's define that oops fine and uh the label is depricated use label instead of okay
component after the switch I'm going to see if the value is true so the show value is set up we are
description want your code delivered somewhere else no problem choose a different drop off location drop off
point and we will make sure your ride is there waiting for you so I'm going to have one more switch component so this
will make sure that um this is to enable users to select two different pick of pickup and drop off
points we have another one here the checked one is the valy we are getting from the form State itself val.
also we have to update the drop off info based on this state yeah so when I select it this pack
this will actually manipulate the form data and uh it will reflect in the map the the markers location in the map we
are going to create after that I'm going to create a map let's wrap the entire thing with
position initial view state is going to be in the lat long the lat long is the location of the
garage and we going to have the fixed Zoom of 13 and I'm basically passing the height as 50 VH so I want a landscape
Moree first I'm going to have the marker for the garage this is not draggable okay I need to import the
then we will create a few more markers to display a draggable markers for the pickup and drop of
locations okay first let's deal with the inside the map first let's deal with the pickup info so if the pickup info is
so getting the location of the pickup location latitude longitude latitude longitude it it is dra dragable on end
I'm going to set the new location to the valid pickup dolat long if the different location is not
set right that is a Boolean if the user does not want different locations for the pickup and drop I also have to set
the same location to the drop off also that is the first Mark the first marker let's create the content of the
marker we're going to use a user icon because this is is what that is the pick up location icons
that is the first one let's have look at that need valet yes that is the map and you can see the marker here which is
after the marker I'm going to put this directions I'm passing pickup route just a a unique
string and the origin is going to be lat long which is location of the garage the destination is the valley.
pickup actually this thing does not have to be optional because we are already checking that
here so the destination is the pickup info the location stored in the pi pick up info the set distance is I'm I'm
passing the set value from the use form context and we get back the distance I'm setting that so that is
is not it there because we only have one okay that is the directions and it has like 400 milliseconds
delay and we see the directions so now we have to add the other um marker which is for the drop
mean undefined it's going to be trly the value here it's going to be a bit different on drag we just have to set
the we don't have to set the yeah we don't have to set the pick up pickup location it is just going to
there is a need that if the if the different location is set up I need to actually give both these things pick up
and drop off but this time this this is simple we are only dealing with the drop off and let's also rename the source
okay only if the user wants different locations we are going to show that now we have like two
going to set the drop off here and uh pick up needs to happen here so the story is like the user is going to drop
the it is it starts maybe tomorrow at u 2 p.m. 2:42 p.m. tomorrow 242 p.m. come here to pick my vehicle
dropped off at this location so the customer actually won't even look at the won't even go to the
garage that is the idea you can update the location if you want okay and also we are looking at the
um charges it is 1 hour and 1 day and 11 hours which is 35 hours $350 for the parking for the value pickup charge is
the vehicle number and the phone number let's book and also in the stripe page also we can
okay fine let's do the payment also remember we have I think we have one booking here and that booking
did not have any value assignment let's do the booking okay the booking is done and we will be
hour the vehicle number phone number passcode status is in booked we have U slot one this is a car slot and we have
and the pick a valy idea and return valy IDE are not set so these things will be we will be set we will set these things
from from the valy application it's is a different application fine so that's how we do the
valy management and the upcoming sections we will uh start to create this bookings we will create this bookings
application and then booking page and then we will move to the manager value application admin application
okay so we are actually working uh we have to finish this booking Pages booking page bookings page for the user
but I'm going to continue with uh creating the manager application which is going to we are going to run that on
that only managers can proceed so all that's what we I'm going to work on now basically from the inside the apps I'm
okay going to enable typescript es Lin Tailwind SRC app router and no for the customizing import default import
right now I have to set up the okay first let's run it I'm going to mention the port number as
hellow and I'm going to delete the globals do CSS remember we did the we did similar thing here also we actually
have one CSS file which is inside the UI Library so that's what I'm going to put inside the
um styles will also work here for example we can have the have some padding and uh background of
applications let's also add the now bar and uh everything into the managers layout page so there the menus
are going to be different I'm going to get this from here we're going to have two menus for
difference and I'm actually we also have to manage this metadata right now it is saying create
everything now let's add the Au Pages it's not going to be any different it's the same uh register with
the same layouts the same um components for the out layout on the register form nothing changes
here I added one more thing I have to also add this token and next to other routes okay we already went through that
here technically there is the same database okay we have the same database for these applications and
people can actually login login fail why also I'm seeing this optional for the first time password optional
why for some reason I okay maybe I was testing playing around okay that is gone now what I'm
thinking the problem is I miss an environment variable in the manager application that's what I'm guessing
okay so I'm going to create a EnV file the root of the manager application and I'm going to create this environment
variables API URL is still 3,000 next Au URL is 3002 for this application next OD secret is secret okay so I'm this is
local development so when you push to production you have to be careful mindful about having a really
complex strong secret so that then I'm going to try to log in with the with the user that I
created in the previous application okay I'm logged in you can see the the image is missing because I
have to populate the public that is we don't have user image this is the fall bag image I'm going to copy that into
the public public directory and now when you refresh you will see that image maybe I should work on this this gu is
um that is the basic application that is ready now let's work on we're going to work on something called a render props
we're going to have a component so let's first create a component called is logged in that is
the component name so the is logged in is going to block is going to have render a fallback
component when the user is not logged in if the user is logged in it will continue to render the
children let's go to the organism in the UI Library I'm going to create that is logged in.
render prop child the children is going to be either a react node from the react or the react
prop child which we created here which is a function which gives a uid okay you will see it in action in a
bit inside the component I'm going to use the U session from the next o so if the status
loading if it is loading I'm going to just use the loader panel which we created in the last
comply and inside that so this this condition is the user is not actually logged in but we are also I want to we
can have a fixed uh component here some js we can return some GSX saying that wow you're not logged in something but I
am getting a property here okay it is optional I'm going to make sure that we render that
component if the consumer of this component passes that okay else I'm going to have the default jsx using the
proceed I'm going to return a fragment and inside the fragment I'm going to test the type of the children
past the type of the children is function and this if this is a function if that is the children which got passed
children like this okay we can do that when we invoke the children this uid will get passed to
here okay so I'm going to keep the assertion there as render props and this is the is logged in so how to use that
to mark the page uh use client also the manager homepage is not static or it's not static so it's it's
going to have a data dependent upon who is accessing so that's also a c component now you can
get the uid there how cool is that this uid is passed by the is logged in component and we are rendering that
again actually I don't I don't want to get the uid here but I just wanted to show you the example that we can
actually pass properties like this into a component into the children okay so I'm going to create a
similar component called is manager so just like how we use the use session to get the user information in
the use use manager component I'm going to hit the back end to see if the manager has a
the get user so when you use this all authenticated you can get access to the authenticated user information that is
going to be of type you get user type here I'm going to just return this do primma dot you can also use the company
service let's use that company service do find one and I'm going to pass the ID from the user user user. ID so this ID
reliable the header the token we did everything in the O guard right okay so the company service find
the generate the code for this okay so my company I'm getting the so actually you can use the
query basically in the my company I'm getting the ID inside the garages I'm getting a few things so that's how I
compose you don't have to pass any argument any variables this in this query Also let's run the
Cen in the network library that's it now here let's import the generated code from the gql do/
it so the manager is just going to get the um base component and I'm going to import the
that get the data if it is loading I'm going to render a loader panel loading company if there is data if there is no
data I'm going to return just a alert section with saying that you don't have a company
yet so here we will come back to have a button uh that will probably that will open a dialogue that get some
information for the manager to create a company and then it will create a company if everything is successful we
are going to allow to we will show the children so this is a bit simpler than the is logged in component okay here we
are doing a lot more I wanted to show this this could be this U could be a useful pattern some situations this is a
simpler one we are doing this and uh we are rendering different things based on the this query
result fine now let's go to go back to the manager page and is logged in I'm not actually we don't want the uid into
it the dummy uh garages we created right so I used this account to create that let's uh change
confusion I'm not logging so that this is the is logged in page okay one more thing I wanted to do in the layout page
I'm going to add some add some background color which is a very light P Gray okay so I like this
when you have um White cards on top of it top of a mildly gray background I like the style I'm going to do the same
yep we will come back actually I I left the background uh transparent for the form but actually we will have some 3D
scene as the background in the login page for the login form okay so here we are I'm going to
don't have a company yet so that error message is coming from the is manager component okay this is the error message
so here we have to um create a dialogue on clicking it it opens a dialogue and we will do the company creation inside
page thing in the is logged in okay so we are getting that the problem is we modified the type
did not like this I wanted to make the ID to into uid because that's what I call we call in the back end I modified
it in the front end I imported that type definition like this okay this is okay this is the UI
Library the web also the app / web also I I included I added this so basically you have to just copy this and paste it
in the manager application and now when you do the Yon validate you're going to not get that
that we have to set up the so this is like we are combining two mutations okay we are making we are passing we are
company I'm going to modify this okay so I'm getting the manager ID and the manager display name along with
maybe let's just use the pck type it is a bit confusing for me I'm going to pick the display name that is the display
name of the company and the description so display name description manager ID and the manager display name
those are the things we are going to get in the company create input and then we will create the we already have created
the manager right okay so this is for creating the company only and we get the manager and we just add that manager in
the array of managers for that company this is done let's move on to the resolver in the
manager name sorry because the manager is already created here and the manager has a name here which is manager
guy so okay there was a small mistake we get the manager ID and in the resolver the service first we check if the
manager already has an account uh is already assigned into another okay first check is if the ma if
dot Company ID that means that the manager is already part of another company so we cannot that person cannot
company yeah so if everything is fine we are just creating a company passing the description display name and the manager
ID that is we have updated that now let's create that mutation through this I'm going to
that is actually enough going to the input file for the code gen pasting that now the network is running okay so it
created the create company in document that's all about the back end and the Coden now let's focus on the
TSX yes is enough because we are not going to have um provider component here I'm importing the use effect from the
schema schema create company we're going to have the company name first so so we make that mandatory by making it minimum
null there used to be um conditions functions like not non empty and so on but they were replicated so we have to
going to infer the type from the schema using the Z infer type of I'm passing the schema
name then I'm just going to create the use form use form create company use form create company I'm
here just for the naming convention I think all the schema starts with form schema so I'm going to add
that form schema create company and then we will rename this so that is the form schema and the use form
component right let's set that up so we manage the open close States for the dialogue and inside the div let's return
here right now let's just have create company that is a content of the dialogue going import that from the
atoms let's also import the use it now let's use it in the page here instead of this I'm going
see okay so we get to see that and on clicking it we it opens a dialogue okay so now let's let's
continue working with the create company dialogue first we need to have the form first let's uh get the company name
using the HTML label and the HTML input this gets the company name and also the register is fly type save so we
can only assign the properties that we have mentioned in the IMA similarly I'm going to also add
the HTML text area I think I have we have not created the HTML text area I'm going to create this
HTML fixed area. TSX again we just have some opinionated Styles here and then I'm just forwarding
the ref this is what we did for the other components as well the label is a bit more complex that we are getting
yeah text area is a bit simpler we have created these two now now I want to talk about one one thing
the so here how how do we get the manager ID from the token right this is the decoder information of the token we
get that from through this but but here I wanted to I wanted the user to send the manager ID so that if an admin wants
to create an account for a manager the admin can do that if I just play on the header token when the admin tries to
create a manager account for some other guy the account will be created for the admin right the admin's U ID will be
there in the token so that's why we get the manager ID and also we have to do some checks
here here so we get the manager ID here we will make sure there is a function here called Low R level
uh decoded information from the token this is the requested ID okay if the admin is there we are going to bypass we
all authenticated we have to get the decoded information from the token and then we going to pass
mutation the ID inside the user and the manager ID are going to be same if the admin accesses it admin calls this
mutation the IDS are going to be different but the request is an ID so that request will get bypassed that is
that's what happening here let's focus on the create company we got this but I'm not going to ask the user to type
the uid right so we need to intelligently populate that because we know that this is the ID
and when we get the uid there I'm going to use this set value only if the uid is valid I'm going to use a set
now I will make the other one read only okay we'll do that I'm just going to copy the first
ID this is manager ID and I'm going to make this read only okay now let's look at the so this is
okay you can either do this or you can just remove this from the form schema you can remove the element and in the on
submit here you can add the manager ID directly to the mutation but this is more transparent the user can make sure
that's it then let's just add a button create company the button type is going to be
company document that is going to give back an array the first one is going to be a mutation mutate function the second
onsubmit the unsubmit we already get the data here we can also destructure it but that is fine we can simply pass the pass
that let's make it asynchronous because we are going to do an asynchronous operation await create
it's okay now yeah now it's working and um we also need to refetch that right when I submit this when the
mutation is successful I want the data behind this data to be refed and refreshed right let's do that refetch
queries and then we can we can I also added this plugin right code gen plugin called named operations do query do my
description Big Apple Parking Solutions Solutions is your trusted partner for affordable and convenient parking in the
error okay so I have the company name this is actually this should be display name but I have that as a company
name display name description manager ID but in the forms that create company I have the company name description so
this has to be display name but nowhere I got the type error so in the code gen also this is the create company
typescript error types typescript error here here we get the company name description name and manager ID but the
company input requires the display name so previously it was not complaining okay I'm a bit confused
there okay so basically I'm uh um I'm going to go back and I'm going to rename this to display
name because the form the name says it's create company so display name the name should belong to the company now we get
just fine so actually we are combining both company creation and manager Creation with in that one mutation so
why have to here I also have to create a manager let's do it here so clearly this blow needs to be um
we have we have to probably should do something like is loged in is manager as company so we can have this those three
nested checks and we may actually create a manager in the Second Step okay it could be like onboarding process
process so basically I'm going to get the in the create company I'm also going to get the manager
null so optional will make the string string um or optional we also have one more thing called
nullable now this this is happy right let's look at the dialogue now now we can see the manager
name that's not read only they can update that the manager ID is read only and um okay now in the company
resolver I'm going to we have to change this I'm going to make it anybody can create a company anybody logged in can
create a company that is uh that's what we are going with now as as I told you this flow has to be for the are
strengthened um it could be an onboarding process with with more calls to the back end and in an actual product
in an actual company we may also have to verify that that means that a company representative has to give some input do
some mutation from their end so that the manager can proceed from the M create manager page to create company page all
those things but I have simp I'm simplifying this process now let's go to the service first first
step we are we know that the manager in this flow the current flow we know that we don't have a manager so we are going
to straight away create the manager we can also get the manager name from here okay we are going we we need to
update the D2 also so we get the manager ID manager name we get the manager name here and we are going to create the
manager pass a display name is manager name and the uid is manager U ID manager ID we don't want anything here we can
fine okay so here let's uh list the garages that belong to the manager and also we will have buttons to um to this
create garage page okay I'm going to create a new component called list garages inside the
company company ID basically the east manager I decided to actually make this use the render
here this a function right we exactly did this in the is logged in component it could be this or a simple
render react node now everything is same but when we return the children I'm going to return
um we get the company ID here instead of this let's return the my company. ID okay so that is a change I did and
that's how we pass the company ID here let's do it in the manager page here we are going to use
the we get the company ID here from the East manager component and then we will just pass the company ID like
this we'll finish the list garages and we will come back here okay so we're going to do some page
get the error message data loading State and that component is also going to manage the pagination
so we'll keep it here and uh so we will create that show data component and we'll come back to the
we're going to get the error as a string it's optional loading should also be optional the for
page ination I'm going to get the set skip take skip skip take result count total count okay all these information
are required to do the page Nation so we are going to use the page Nation from the material
and I'm going to destructure the set set skip set take take result count and total count from
and page number and we are just okay this is the this is how the pagination the on change in the page
component help works the on change here this handle change okay so that's how it works so it
here we are actually making the first page into zero right zero into take the first page has to be zero and
for the first yeah so for the first page it has to be zero into take if if the take is 12 for
example first page where it's going to be skip is going to be zero second page is going to be 2 - 1 into 12 12 that
that that number of results we need to skip so that is the logic here let's calculate the total pages so
we get the total count from here and we calculate the total Pages for example if there are like
337 garages we divide that by 12 and we calculate the total Pages that's it now we return the
div I'm going to have a title here with some text large margin bottom and so on and for the loading I'm using the loader
if if it's not loading if if the error is undefined but if the result count is zero I'm going to give the no
results let's create that no results it's a simple component let's create in the molecules
no results. TSX basically it's a flex Flex box with a everything in the center item Center justify Center
with a background I'm having his icon box to show empty no result so no results let's import that we are
basically we I keep doing this for for whenever I fetch information that's why I decided to
I'm this is development purpose right actually I'm actually printing the error there okay hope something went wrong and
this and then I'm going to grid grid calls three and GAP three I'm going I'm going to render all the
children we can further work on that we can make it um responsive maybe let's do it for a
smaller screen let's have like grd calls 2 and then uh for the mid screen we'll have grit calls
three or extra large let's go for GR calls four but that's sufficient I think that will
oops count equals total pages that is the number of pages I'm going to enable the show first button and show last
550 the take is 10 then the page is five and in the on change I'm passing the handle page
change that is the show data component now let's go back to the list garages which is here
thing I'm going to create a hook so in the hooks we going to create a file called page nation. TS
and this is the hook a very simple one I I am tired of using the two lines in every component
everything in one go so that we can get everything in one go in the constants I'm also saving the
Nation right so this guy gives back the all the pagination related stuff now we need we need to write the
garages query in the graph C input I think we don't have the garages query yet we have search gares okay let's
create the garages query always use this while composing Airy we have this garages I'm going to
enable all these things filtering sorting dist distinct cursor even and I'm going to add the
that will generate the code for the garajes document so I'm going to add a few things for the
for that query we need two things one I'm going to get the slots count basically we are going to group
byy all the slots that belong to the garage basically I want data like cycle 7even car 14 so how many slots total
slots available in that garage so I'm going to create a resolve field the garages resolver
entity for that I'm going to create an entity here in the garages entity file CL count type is going to return back
this let's create the resolve field so this all field is going to return back an array of
where yeah we can filter based on the garage ID we get from the parent garage. ID then I'm also I need the count based
on the type that's it now I'm going to go back here I'm going to add that slots
count okay so basically we get an array of type and accounts where garage that's not it we also have to do
one so we get the we condition because when the user filters we need to filter the total filter and get the total
updated total count also basically I'm using the garage. aggregate I need the count of all and we are passing the we
condition the we condition is going to have the address verified Etc fine so those two difference I wanted to
do now let's also add the garage count to the for and input file this wear is what we get here okay
this is the wear we are passing that to two queries both these queries and um the other stuff like
distinct the where reduces the total count okay so we have the query ready now let's go back here I'm going
are okay let's just um stick to the use Query later if you are if you are going for some searching filtering those kind
of thing when we have you remember how we did with the search garages right search page we did we use the use in the
show garages we use use lazy quy because we are we have this complex variables going on we were getting we were having
this filter sidebar and so on We Gather all this information so I whenever this changes we wanted to refetch so I used
use lazy query this time I'm not seeing that maybe we'll simplify the process so I'm
document generated file W okay so I did not name name that properly the when I was composing
this it was just called query I want I want to rename that to garages now we will get that gares document okay
variables I'm going to pass the skip take the be condition I'm going to pass the company
that is it now the show data is actually complaining that we don't have any children let's add some
children I'm getting the data. garages I'm looping through that I'm just rendering a div with the garage ID
have no results okay this is the no results component and also we are seeing this component the pagination all the
garage so see you okay so let's create a new garage in this section before that I'm going to
add the title to this saying garages with a link to the new garage page let's go to the list garages
component so this is what we are this is where we are fetching all the garages that belong to that particular company
and 're also doing the pation the set show data actually gets also gets this title which is a react node
title I'm going to pass a div it's some class name next item Center so we're going to
have two things one is the title garages then the link I'm just going to use the icon plus
link and now we get this no results and users can actually create click this to go this to go to
this new garage page and they can create the new garage fine now let's um start from setting up the back end so right
description images and Company ID so that's what we are getting right now that is not sufficient we are going to
how in the last time we merged two mutation into one right based on the access pattern we have in the front
end uh we were doing the creation of manager and Company together in one mutation similarly I'm going to combine
a few things together here the create garage we're also going to create the address of the garage and the
input let's do the pck type which is clear I'm going to pick the description display
ID that's because I'm going to get the company ID from the manager ID that is in the
have address SL long and the garage ID but we don't want the garage ID right because the garage is getting
created now before that we won't have the garage so I'm going to update I'm going to actually create
another address input which is I'm going to man modify the existing create address okay so I'm creating
address create address input without garage ID I'm extending that this um create address input and I'm picking the
address that and long in other way we can omit the garage ID but picking look simpler so this is
fine the next one similarly I'm also going to get the slots here in the cre create slot
ID if a garage has like 500 slots I don't want the front end to actually pass 500 items with the height
there so here in the create slot input I'm going to create another input input type called create slot input without
garage ID so I'm omit so I'm taking this input type I'm omitting the garage ID I'm also adding the count there so
basically in the resolver we are going to Loop through and we will create plots that's another input type
and um yeah so we can get n number of that so this array is there because while creating a garage users can create
like 100 Cycle slots 200 car slots so those items are going to be inside this array okay car count five then the the
next item bicycle count 12 something like that so this is the garage input we have now let's go and um work on the
resolver first let's make sure that the manager belongs to a company we're going to basically get the
token and we use that U ID to fetch the company ID so we basically looking for company at find first where managers
some of managers should have this ID right so so we get the manager ID and if we don't get any man
arguments which is a number so let's spread all the arguments and then I'm going to add the company ID
the service file and Implement that first I'm going to have a check here slots so let's destructure the
arguments slots. sum slots is an array and sum of slot. count we get an array which says like
type cycle count five type typee car count 12 so I'm making sure that people are cannot create more than
20 I'm actually planning to deploy this okay for public uh so I'm having a few I'm going to have a few restrictions in
first I'm going to create the garage I'm going to pass pass the address the address
information goes perfectly well here so we just want the address lat and long those are the mandatory fields and those
that's what we have here address slat long so we can just take that and uh pass here and typescript is happy I'm
passing the compan description uh display name and images so this last information we needs
to prepare that to suit what uh the garages take right here we can create actually we can um create many
here okay so actually we can also create an um array of stuff here but the data we received is different we have the
method create it here basically I'm going to call this group slots by type it gets this type remember
this is the input type with the account array it's going to return back this slot create many input so
object then uh I'm going to Loop through the slots array we going to get the count and then uh D
type as a type if you don't have that type in that object we going to create a new array for that that basically the
return return type is going to be an array of this okay we are putting the type we're putting the garage ID all
complaining so I'm going to just remove the slots and address from there and now it works
fine as I told you yes uh we have a huge prog huge product and it's going to take um every path every mutation every query
product you may ask then how can I change the address of the garage right so yeah so we have to handle those
things those N Things we are finishing 80% and we are going okay now let's we have already
created the garage I'm going to create the slots array using the group slots by type basically it returns an array of
I'm passing the slots by type that's it so after that I'm going to return the garage so that's all about the back
end now we have again um go to the front end create the form schema for that and then we'll create them forms and we'll
proceed with that before that we always go from the back end to the bridge which is the code gen and then the front end
right so let's uh go to the Apollo Explorer and we will compose a query for create garage
the progress I'm wasting that and also going to modify the mutation name and there is one um one thing wrong
okay that is by mistake okay that is I think till now we have only one thing that is in camel case
I'm going to modify this to Capital let run the Goen to run the network it is successful now we have
the create garage document here fine now let's move on to create the form schemas in the forms
provider okay actually I'm not sure if you if we will use a provider so we will just stick to the
y u so we are going to get multiple images and U using the input input element we're going to set the multiple
to True type to image and that uh the type is going to be file list and I I don't know how to exactly use that type
address equals z. object flat long address and we can use it here and then we are going to get n n
maximum let's also give the minimum to one and now here I'm going to add this s array
garage then create the use form hook use forms from the create react hook form s resolver from the hook form
SL resolver SL zard then this is pal schema react or create garage I'm going to call this slots and
by default I want this to to be an array empty array otherwi I don't don't I don't want
to set any default values it's uh user will create them in the form okay so this is the use
gets um some children it wraps some children in inside and then we get all the methods which include the register
set value and so on we get everything and we are passing inside the form provider form provider again comes from
nested uh components we need to do this we need to have Pro um WRA the entire children with a provider and we can use
the exact register function value function everything inside the children but I'm going to start building
using the hook and when we want to Nest the children we will come here we will create a provider we will wrap the
the wrap the create garage component with the provider and then we will use the use form context instead of this
functions like register handle submit everything from the use form garage and I'm going to use the create garages
mutation using the use mutation that is from the Apollo client these two are going to come from
fine now let's start creating our form so the whole form is going to we going to have the map in the right side and
form first one going to set the display name let's import the HTML label HTML input um this is a display name and you
cannot go wrong here you have to select one of these you cannot give any other names having some
title this is the error message the label button yes error message you will we will see this I think we did not see
submit and in the AR on on submit I'm going to just use the handle submit this won't get called right now
because we have not implemented the mandatory Fields yet but still when I click it the error message shows
I removed the the Min zero Min one right I come back here and submit you don't have the error anymore you will have
other other errors but that error is not anywhere that error is not there so if you want to make a
used to be something called non mty and they replicated it okay let's continue building our UI
next thing is a text area I'm adding the column five I'm registering the description
here and we're setting the U error for the address it's a bit tricky we are going inside the location
you may give that like this but actually this particular field is for the the inner one the address.
field I'm having some placeholder okay now we are going to create a component called image preview
we're going to set up cloud inary and um we will upload multiple images let's create the image preview
component so basically this is again an OP um like a branch component okay if the user select
some Source sources the image sources we are going to render the image even before uploading we going to use cloud
inary even before uploading it will render the images before render before selecting the pictures we will be
rendering the children which is the HTML input element with the type of uh image and uh multiple
true and I think uh rendering the images before uploading is important because if something is wrong the user
can reselect right we going to get the SRC which is file list that is the e. Target do files
zero I'm going to just create a grid of images render them let's say grid with a two column
I'm going to have an absolutely play button this is an absolutely placed it's going to be placed in the center okay
like left half top half and also I'm going I'm making the translate adjusting that to the X and Y
so that it will be like in the absolute center of the parent also I'm making the parent
relative let's import the icon trash from the Tabler icons react okay that's it now we get this file list
how to render that in an in an actual image component let's do that after that let's
component from the next image I'm passing the key because we are rendering we are looping
through having some class names which is object cover aspect square and taking the full height and
this it won't work typescript is also complaining that is the file right in order to do that I'm we have to
do this URL dot create object URL and then you can pass the file now the typescript is happy we will render the
I'm going to just return the children I'm going to have a file Flex item Center justify
that before adding that we need to get the listen to the value of images we get the watch and we can listen to the value
preview this images is whatever we pushed inside the form data and in in the clear image I'm using the reset
field from the use form hook and I'm resetting the field resetting the field of images here
control component the controlled component I'm using the controller from the react cook
form I'm doing that for the names but for the images I'm passing the control from the use form hook
here and then accepting the image file type is is actually file it's going to accept the
image any any type of images and I'm setting the multiple true so that we can select multiple images
and on change I'm actually getting the e. target. files that is a file list okay so I can click through and that is
images and I told you uh I don't know how to exactly use file list here that's why I just go with the y in the s
demo I'm going to get some images from the unsplash.com and let's give shout out to
John not going to read that I don't know how to read that okay John for this image this image and then let's um get
images I'm selecting it and that is the image preview component okay you can further polish this
component you can actually have a independent delete button for images and uh I don't know how to do that even
so here we are simply using the reset reset field I'm resetting the whole thing and I don't know if I can do
have an array instead of uh any here if I have Z do array of string and if I push the push the URL inside that the
three okay the good thing is we have not uploaded the image yet the image gets uploaded when when we submit submit
that rename that so submit when we submit the image will get up uploaded to the cloud inary and then
we do the mutation we we we upload the image to the cloudinary we get the URLs and then we do the
good and here also I have to add this minimum of one so because I did not see the error here okay two pills are
in it's free you have ample free free usage and you need the cloud name there okay copy this and paste it inside
create an environment variable called next public cloud inary cloud name that is the first one
the second environment variable which we want to work with the cloudinary is next public cloudinary upload
name so when it asks uh signed or unsigned go for unsigned we're going the we're taking the the easier path for the
one so let's proceed I'm going to create a hook let's create in the util library
inside the hooks I'm going to create create a file called cloudinary dots import the use State going to
create a hook called use cloudinary upload so this Hook is going to return back an upload function and the loading
that's what we store in the form schema also first I'm going to set the loading State Let's uh and then I'm going to
file list and I'm looping through that getting individual file and then for each file I'm going to
create a form data first I'm going to upend the file itself and then I have I have to open
the upload preset which we just created right with this name of key upload preset and then I'm going
to use the fetch to actually push this form data into the using the api. cloudinary version onecore one I'm
passing the cloud name here image upload this is unsigned so it's not a safer way but it works for the
okay if the response is okay not okay it has to be inside the promises if it's not okay I'm throwing
have okay so we don't have types type safety here and if you remember we did not install
anything that is related to the cloud inary so basically we don't we are actually hitting the AP as it is just
so there is no type safety here and in the image image I'm going to get the secure Ur secure
now let's that is the promises now we have to await all the promises that is going to return
back okay that is going to return back this an array of promises and I'm resolving them in all in one go and I'm
finally going to set the loading to false okay that is the hook and um we're going to return the
component let's import The Hook from the util SL hook SL cloudinary and we we can get back the
uploading and the upload we are going to have two kinds of U two things going on one we have we
have a loading for the mutation maybe let's rename this to uploading why don't we return that
this loading State it's going to be uploading or loading so this is for the loading State for the mutation this is
continue we have um so it's a two two column grid okay okay so I'm going to have a map here
with a movable marker draggable marker so the first item is a form the second item I'm going to use the
map okay let's import the map from the map map from the organism and the initial value from the
initial view state from the constants that is pointing to the nework okay AP access token is required
application you have to copy that map next public map boxcore token you have to put that inside the
environment variable of the web manager okay we got it we got the map let's add let's add a
panel let's have a panel in the left top I'm going to have the search box search Place box remember
one in the same panel inside the same panel I'm going to add the default Zoom controls okay so this one it is working
but remember I told you that we can add more buttons here as children I'm going to add we also have
component simport that that is a center of map component and center of map requires a latl a on
that and use a set value from the use form hook set value set the location. lad and location do
longitude using this actually I'm going to also render under this lat long in the UI okay here
why am I like truning reducing the uh Precision here I'm going to actually have the lat long
rendered here and I don't want it to be too long maybe let's increase the Precision
and they have to render themselves here right in the center for that I'm going to create a
garage components file this is going to have multiple components that we need for creating the
for writing the create garage component template this guy takes initial location it's a view State lat long
Zoom um which also gets the location information using use watch use watch from the re hook form
providers right in the create garage I did not create the provider but we we want this form is going to need a nested
forms we are going to have children like this one right the marker is going to listen to the location and um it renders
itself and also we are going to have ADD slots component going to have n number of slots getting created that component
provider so Yep this is going to be similar to what we did earlier with the providers and also here I have to do
react node we can pass anything it's going to WRA the entire template and then I'm going to get all the methods
from here and I'm passing them inside the P provider so that we can get back in the use form
context here it is complaining that okay so I have to convert that into a TSX file okay now it's
happy I have created the provider now let's go to the create garage first I'm not going to export
this I'm going to convert this into a create garage content so this is a opinion create garage content then
export const create garage this is the file we are going to component we're going to exp export here I'm going to
have return use form the form provider garage create garage and then inside that I'm going to use the create garage
page you can import the P provider here and we can W the entire template here but I want to like en consulate or keep
everything together inside that one template so I like this format okay now we are working with the
create garage components oh also one more thing the create garage now we cannot directly use
location information for example in the form schema has to be same here also inside the nested components here
created I have to replace this with the use form context and also you have to pass the use form type create garage
okay now everything should work let's continue with this uh garage marker so we get the initial location we
location the of the marker the dragable marker are set from different places when the map moves we get the center of
name when the map navigates to that location we want the marker to be there so that's why we U get this
location and this marker is draggable when we drag the marker we have to also let let the form State know that the
Auto latitude and longitude from the from the location information going to set this this is
draggable and also when the drag ends on drag end I'm going to use the get the lat long and I'm going to set that
value fine now we can just use that in the create garage so inside the map this does not go inside any panel
panel is for the overlays the marker exists right inside the map okay I also have to pass the initial
State initial location to does not make sense to me I'm going to remove this basically we
get the this marker lives get the location information set value information and uh we use the location
this so the pl the problem here is when the map loads we are not seeing the location we are not seeing the marker
straight away so I'm actually setting onload I'm setting location lat as lat inside the
Center okay so that should work now this marker gets the location and then I don't want to do any of
this now the market should appear okay yeah fine now when I move the map okay the marker goes there as
well I don't I don't precisely remember how the marker went there because I only had
and on mov end I did not do anything but okay okay okay got it so I actually update do the same thing here in the on
location change of the search map box search Place box so I it gets a call back and um we set the location lat long
there and hence when we move somewhere like let's go to Paris the marker already waits for the
we can do something like um when the user types the address here we can technically do it now we can
hit the mapbox API and get the lat long for that address that would be impressive but I cut that corner for the