Build and Deploy a Full Stack MERN Application With CRUD, Auth, and Charts Using Refine

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
full stack myrn application the Pinnacle of web development yep you heard that right today you'll learn how to build and deploy a full stack man application with modern material design a fully functional dashboard a property management page and a user's page both connected to our database and the profile page that connects the two this video is the updated full stack mern course you've all been waiting for this video is perfect for you if you want to learn how to convert a figma design into a fully functional website dive into the world of full stack development using the most popular stack out there and master crowd principles that allow you to create read update and delete documents our application will have a properties page where you can read our properties and you will also be able to create a property and finally on our Pro property detail page you'll be able to update and delete it that means if you learn how to build this application you'll be able to make the most complex and modern applications out there if you think about it every app is a crud app in a way create read update and delete posts images articles files messages and more you get the point after you develop this app I'll even teach you how to deploy to the Internet so you can share it with your friends potential employers and put it on your portfolio to get a job you might be wondering what are the prerequisites for building such a fantastic web application you only need a solid understanding of react a basic understanding of node and mongodb can be helpful but they're not a requirement we're going to start simple and then move to more complex topics as we go I'll explain every step of the way alongside building this application you learn how to use the most in-demand Technologies today node.js Express mongodb and the reactions that together form the powerful Marine stack material UI the most popular UI component kit nowadays typescript yep you heard that right we'll be using typescript on this project and no previous typescript knowledge is required you'll learn how to transform a figma design into a fully functioning website using cloudinery you'll also learn how to optimize images and store them on the cloud and using Google auth you'll provide your users with a quick and easy way for them to log in and register and most importantly you'll learn how to build react based crud applications incredibly easily using refine have you ever wondered if there is a tool that will set up everything you need for a website like authentication State Management and routing while still giving you the freedom to customize it that's exactly what refine is refine is a headless react-based framework for Rapid web application development now what does it mean for a tool to be headless headless is the most popular development approach nowadays so far it has been limited to the back end with great examples like strappy refine found a way of building a headless structure Logic on the front-end side it offers both the freedom to start from scratch or use any UI framework of your choice with built-in support for material UI and design chakra UI and maintain refine provides plenty of features that make your app ready to ship within minutes one of the biggest features is zero config one minute setup with a single CLI command and it's not just the UI reframe provides connections to more than 15 pack-end Services making it easy to set up and use other than that refine also offers SSR support with nextgs or remix and auto-generated crud uis from your API data structure and of course there are many additional features as you can see here one of the best things about refine is its excellent Discord Community they are always ready to help so you can get support and resolve your bugs quickly refine also has a strong presence in GitHub with over 7000 Stars their development team is very active and quickly resolves issues reported in the platform and the download stats for refine are also increasing day by day which is a testament to its popularity and Effectiveness among developers with its headless design by approach excellent community support and strong presence on GitHub refine is a great choice for anyone looking to develop apps quickly and easily and that's exactly what I'll teach you today in this full stack course alongside this video I've also prepared a complete myrn roadmap and a cheat sheet that covers everything you need to become a fantastic Marine developer the guide has an entire step-by-step burn Mastery roadmap prerequisites helpful illustrations and even learn project ideas that you can build after watching this video you can download the ultimate guide and use it as a reference on your web development Journey whenever you're unsure what to learn next the link to the comprehensive guide will be in the description if this video reaches 30 000 likes I'm recording more learn videos with that said let's dive right into the code as we always do on JavaScript Mastery we're going to start from bare Beginnings by opening an empty Visual Studio code window and creating a new folder on our desktop in this case we can call it refine underscore dashboard finally drag and drop that empty folder into your empty Visual Studio code inside of our Visual Studio code you can go to view and then terminal this is going to open up an empty integrated Visual Studio code terminal inside of here we can run one single command npm create refine Dash app at latest and then client like this now we're asked a question whether we want to install that package and yes we do once it is installed it's going to open up a CLI that's going to ask us all the questions it needs to know to initialize our application and there we go first we need to choose a project template in this case let's go with create react app then what would you like to name your project in this case we can name it client since we'll be using it on the client side then we need to choose our backend service in this case we'll be using a rest API as you will create your own backend API then it's asking us which UI framework we want to use and in this case we're going to proceed with material UI now it's asking us if we want to add some example Pages we're going to click yes do we want to customize the material UI theme we're going to also say yes do you want to customize the material UI layout we're going to also say yes do you want to add dark mode support we're going to say yes to that as well do you need any authentication logic yes we'll be using Google do you need i18n support in this case we won't be using that but it's good to know it exists do you want to add k-bar command interface support in this case we won't be needing it now we need to choose a package manager you can use npm or yarn in this case I'm going to proceed with mpm and we can share our choices anonymously and with that done refine is going to take all the answers we put in here and it's going to initialize the perfect starter repository let's give it a second and I'll be right back and there we go success created client ad client we can see our entire file and folder structure right here but most importantly we can go to our package.json to check the install dependencies as you can see we have a lot of refined packages which are going to make all of this possible but we're going to also add a couple of packages on our own so down below we can now CD into client like this and then we can type npm install and then we can add Apex charts we're going to use these for those beautiful charts on the dashboard we also need react Dash Apex charts and believe it or not that is it refine provided us with everything else we're gonna need to create a full stack marine application so for now simply press enter let's wait for our charts to be installed and then we can explore our Repository so what we can do is close the packet Json inside of the packet Json let's check out the command to run our application that's going to be mpm run Dev so inside of our client let's run npm run Dev and let's check it out in action and as soon as the website opens up you will be greeted with a series of errors but no worries these are really simple to fix we just need to import the title cider in the layout in our components so just go to source components layout and then index.ts inside of here we're currently exporting just the header but we need to export everything from dot slash layout as well and then we're going to duplicate this two more times and we're going to do the cider and we're gonna do the title with that done if we now go back to the website you can see we have a fully fledged and fully functional dashboard available right here isn't that great we can also log out and this all has been created for us but don't worry we're going to start with everything from scratch so now we can log out and you're gonna see a page that looks like this of course we want to modify it to fit your application so the login is going to be the first thing we're going to focus on to start with the login we can close our index we can go to our pages and the login is going to be the only page that is there right now inside of there we're importing things like use effect use ref and there's also a special hook called use login which we're going to utilize later on we also have some imports from Material UI great with that said we can start modifying our login component for that we're going to have to import our application logo which we don't yet have so now might be the best time for me to provide you with all the files and assets that you'll be able to use throughout the entire process of building this application down in the description you can find a link to a zipped assets folder simply unzip it and then paste it right here inside of your source that's going to look something like this inside of there you'll see an index.js exporting those two logos and then two different versions of those logos in the SVG format another thing that you can get from the description and that's going to be in the GitHub gist down below are the links to a specific font we'll be using across our application so let's go to our public index.html and then inside of here just below the theme color you can add those three links that you can find in the GitHub just down below below that in that same GitHub just below you can also find the index.css file so right in the source you can create a new index.css file and then you can simply copy and paste the styles from the GitHub gist as you can see these are simply some media queries positionings of cards and setting up the font family another thing we'll be using in our application is the constants folder so let's create constants and then inside of it let's create a new index.ts file the constants are also going to be in the GitHub just down below and as you can see this is just about 30 lines of simple property referrals info things like title percentage and color for one of the charts we'll be using I didn't want all of you to type this by hand because we have more important things to focus on another thing you'll have to get from that same GitHub gist is going to be the code for one of the utility functions so inside of utils you can create a new file called validate form dot TS you can simply copy and paste it right here this is a file that's going to check if we have properly entered all of the properties again this isn't so complicated logically but it takes a lot of time to write out so I simply provided it here for you so we can focus on the Marine stack Logic on top of that below the assets there's also going to be an interfaces zipped folder we need the interfaces because we're using typescript this is going to help our IDE know which specific properties our objects have so you can delete the current interfaces folder unzip the one link below and then simply paste it right here there you'll be able to see that we have our Google so we can see what do we have once the user logs in but we also have additional props for some charts for our properties for our agents and so on later on we're going to dive deeper into this to explain how these properties correlate to our actual objects and the last thing you'll have to get from that GitHub just down below and I promise this is the last one is the config file for our charts so inside of the components folder we can create a new folder called charts inside of there we can create a new chart.config DOT TS file and inside of there you can paste that config file this is just going to simplify the process of creating our charts and with that said we are ready to dive into creating our login page which we started in the first place great now we have the access to our logo so we can import that's going to be a Riga which is the name of our application from dot slash assets there we go now as you can see the Google button has already been created for us so we don't have to do anything there but right here we need to enter our client ID coming from Google so now I'm going to show you how to get your client ID first go to console.cloud.google.com the link is going to be down in the description then on top you'll have to create a new project so just click right here and then click create new project let's name our project yariga or you can do real estate or refine whatever you prefer and let's click create our project is being created as we speak this process usually takes just a couple of seconds and as soon as it has been created you can click select project go to the navigation menu and click apis and services great now that we're here the first thing we'll have to do is to go to oauth consent screen there you can choose external you can enter your app name I'm gonna do your Riga you can do refine or whatever and then you can choose your email after that you can scroll all the way down enter your email one more time in this case that's going to be a developer email but that's the same for us and then you can save and continue the second step is to add the Scopes we can save and continue we can save and continue for users and we have our summary now from here we can go to credentials and then we can create credential let's create a new oauth client ID we can choose our application type that's going to be a web application app name is going to be a Riga and then we can add authorized JavaScript Origins so let's add a URI I'm going to do HTTP colon forward slash forward slash localhost 3000 let's copy it let's also add localhost without the column 3000 to be safe and then we're going to add authorize the redirect Uris which are going to be the same localhost 3000 and localhost and with that we can click create now it says right here that it might take five minutes for these to take effect but we can immediately see our client ID right here I'm going to copy it and we can go back to our application we can of course just add it right here but that is not the best practice and here in JavaScript Master read the best practices are the only things we teach so what you can do is go to your file explorer collapse everything and then inside of the client you can create a new file called dot EnV this is going to store our environment variables inside of there you can create a new variable called react underscore app underscore Google underscore client underscore ID and then you can make that equal to this key that we just copied that's going to look something like this and now inside of her login.tsx instead of just typing it manually right here for everybody to see you can say process.env dot react underscore app underscore Google others for client underscore ID and we can save it now for the changes to take effect we have to reload our terminal so press Ctrl c y and then simply rerun it by running npm run Dev and with that we should be back on our localhost 3000. now we can continue setting up our login function and finally now that we have our own Google client ID we can scroll down and we can change the look and feel of our login immediately starting with the Box we won't be using this background which has a gradient we're going to do something simpler so inside of the SX probe you can add the background color equal to that's going to be hash fcfc FC and we can save that and immediately on localhost you're gonna see we have this really white gray color now we're gonna have this container we're gonna have a box and then we have to change the logo in this case we're going to use a logo with a source of yariga which is the name of our app and we can rename it to your Riga logo now if we save this go back and reload you can see we have our new completely custom login now if you click sign in with Google it's going to open up a new window that looks like this and you can log in you'll have to first confirm that you want to sign in so we can do that and we are in that was it that was everything we needed to do to make the Google oauth login work isn't that crazy now we can start focusing on our sidebar or cider how refine likes to call it we're going to add all of the additional Pages routes change the logo and the look and feel to do that we can close our login go to our source components layout cider and index.ts this is where the rest of the magic will happen as you can see refine provided us with a lot of predefined features things like collapse open open even links and translations and so much more so we only have to make a few cosmetic adjustments before we start making our changes let's open up the browser side by side with our editor like this and let's get started let's go down all the way to line 137 right here and we can modify the font size to about 16 pixel I found this value to be just a bit better we can go down a bit more to line 180 and right here we're going to change the background color of our item so list item button line 181 we want to check if we have currently selected the item if that is the case we can change the color to B Ash 1 e 3 6 e 8 like this and also when not hovering we also want to change this so let's say if is selected then we can have a color of 4 7 5 b e 8 like this and then we can have transparent if we now save this you can see these are going to get a bit bigger and we have a different color which right now doesn't suit the design at all but soon enough you're gonna see how great this is going to look like as a matter of fact let me show you exactly what we're going for this right here is the finalized design we want to have the logo on the top and this is how we want our list items to look like so let's try to turn this into this with that said we can scroll a bit more down below this justify Center we can add a margin of 10 pixels and then Auto we can also add a border radius of 12 pixels and we can add a Min height equal to 56 pixels finally we can add a width of 90 percent now if we save this this is going to look just a bit different and they already have this spill-like structure which is closer to the design we can keep scrolling down a bit to see this color right here and we're going to change it we can check if it is selected then we want to have hash FFF meaning pure white otherwise we can have hash 808191 and of course this is a ternary operator below that we're going to have primary typography props there we want to change the font size to 16 pixels again and below the font weight we can change the color again if is selected we're going to do a classic just white color otherwise we can have the same one we had before hash 808191 and we can also add a margin left to divide it a bit from the border of 10 pixels great as you can see this is now even closer to this but if we scroll just a bit more down to line 258 we can change the font size to 16 pixels here as well and then we can change our logout button so here you can see the log out and on line 277 we can expand it and below the justify content we can add a margin of 10 pixels Auto we can also add a border radius of 12 pixels A Min height of 56 pixels and a width of 90. this is going to make the logo button appear the same as our regular resource button finally in the list item we can change the color to be hash 808191 and we can also increase the font size right here on 298 to 16 pixels finally a bit below we're going to see our drawer that drawer we can change the color to again the same thing eight zero eight one nine one and we of course have to have the hash sign for the cooler great but now we're gonna see the biggest change there is if you scroll a bit more down we want to see our drawer which is right here 386 we have our background color BG cooler and we want to change that to hash fcfcfc and now if you save that you can see that this is going to take that light color also we can change the elevation to zero to remove that shadow if you scroll a bit more down we're gonna see the button for left and right for expanding and collapsing our sidebar there we can give it a background of hash 475b E8 there we go that's going to make it match our design just a bit better and also we want to give it an on Hover effect so that's going to be and call and hover Colin and then we want to change the background to be equal to Hash 1 e 3 6 e 8. there we go so if you look into that right now it's just a bit better finally going a bit more down to our box we're going to have a BG color which we want to change to hash 475b E8 there we go this is when it is collapsed so now everything matches and if we expand it and compare it it is looking a bit closer to what we have now it seems that we're close to being done but if we make our browser just a bit smaller you can notice we still have this color right here and we want to change that so let's go to line 360 and right here you can see 363 we have to change the color to Hash fcfc FC there we go so now we have our white sidebar which is close to this one but of course the text of this resource should also be gray so let's see if we missed just one style right here when changing the color and it looks like we didn't miss it but we just missed placing this sign right here at least I did so make sure to add a hash on 183 and then we should have something that looks like this which is much much closer to the sidebar we're going for but now we can focus on changing the logo on top as well so let's go to our file explorer and let's open up our header component inside our header we're going to go to our app bar and we're going to change the elevation to zero and we're going to add an SX prop which is used for styling in material UI and change the background to be equal to Hash FC FC FC there we go so this is going to change it finally we won't be needing this icon button to change the color from dark to light mode and that's going to be it for the header but now we can go to the title component which is right here inside the title we have to import our logos so we're gonna import the logo as well as yariga coming from just assets there we go and now instead of linking to refine logos we can simply when collapsed link 2 that's going to be Source equal to logo and we can put the alt off here we go and then when it is expanded we can show another logo which is going to be the ariga there we go so now if we save this we're going to get a colored logo which should make everything look a bit different there we go so before we had white and white which didn't look good but now we have something that looks much closer to our design and that is wonderful we can also collapse it and you can see it immediately collapses to this smaller version of the logo which you think looks just great and we also have our icons which are collapsed right here great now that we have made design changes you might be wondering how can you add additional items to this sidebar list well let me show you refine made it so easy by providing a structure for you to keep adding new lines and pages so let's go to app.tsx and let's scroll all the way down to the main component which you're rendering which is the refine component inside of here we can provide a lot of different props to it and they're going to immediately change how our app behaves and what features does it have and we do that by adding additional resources remember we're creating our application as a crud app create read update and delete resources in this case we immediately have posts which is great but we want to change that just a bit we're going to rename posts to property right here and right now they have all of these mui components which simulate our layout right now but we will want to create our own look and style and components for all of these pages so what we can do is we can remove all of that and save it immediately you can see that we have a 404 built in as well which is great and it got removed from the list because there's nothing yet to show but don't worry we're gonna fix that really soon for now just to be able to see our post we can add a list and we can add the mui inferencer which was there before this is just going to allow us to see how it would look like once we add additional properties there we go as you can see the errors are built into refine as well so you don't have to worry about things like these you just have to focus on the data now let's add additional resources I'm going to duplicate this below and from property I'm going to rename that to agent we're going to also add a couple more below agent we're going to have review below review we're gonna have our message and then finally below message we're going to have our my profile now if we save that you can see that it's going to add all of these list items to our dashboard but there are a couple of things we want to change first of all you can see that an S for plural has been added to all of those lists but we don't have my profiles but rather my profile so we can provide an additional options object and set the label to be equal to my profile this is going to make it look just a bit better we have to add a comma right there there we go my profile and you can also notice that we have to modify the icons for all of these properties so scrolling all the way up we can import those icons right here below the refine mui Imports we can say import account Circle outlined we can also import chat bubble outline we can import the people alt outlined we can import the star outline rounded and finally Villa outlined there we go now all of that is going to come from ADM UI forward slash icons Dash material we can now scroll down to where we Define those lists and under property we can add an icon property and that icon in this case is going to be Villa outlined we can keep adding additional icons the second one is going to be people alt outlined that changed as well then for the review we can add an icon of star outline rounded then for the message we can add an icon of chat bubble outline of course and then for my profile we can add an icon of account Circle outline as well and now this is looking much much better as you can see it is looking like it does on the design it is exactly the same wonderful we can collapse it and as you can see we have the tooltips and everything works perfectly right off the bat wonderful on top of all of these resources we're gonna also have a dashboard page so we can add a special property called dashboard page which is going to be equal to our home and that home page is something we haven't yet created so right at the top we can import all of the pages that we'll be using throughout this video that can be done a bit below where we have local Imports and right now we're importing just the login so let's expand that let's maybe divide it from all other Imports so we can see it more clearly and let's import that's going to be login we're going to also have a home page an agents page we're going to have a my profile page we're going to have a property Details page we're going to have an old properties page like this we're going to have a create property page we're going to have an agent profile page and an edit property page there we go so a lot of different pages and of course we're going to get an error now because we haven't yet created them so now might be the best time to go into pages and start creating these pages one by one so let's start with the home that's going to be home dot TSX and immediately inside of there we can run rafce this is going to immediately create a simple home page now if this didn't work for you you can go to extensions and then you can install es7 plus react react native Redux Snippets as soon as you install this the rafce command should work so install it run ref CE and then let's proceed with all other components we'll be using the second component right here is the agent dash profile dot TSX there we can also run rafce but we can change this to agent profile like so then we're also going to have an agent property or a page agent.tsx where we can also run rafce then we're going to have a new file called all Dash properties dot TSX and there we can also run rafce and we can fix this right here from all properties to all properties in camel case great now we can create a new create property so that's going to be create Dash property dot TSX we can run rafce and once again fix the create property to camel case after that we're going to have the edit Dash property dot TSX we can run rafce and one more time we can edit this to camel case finally we're going to have my profile my Dash profile dot TSX we can run rafce and then we can edit this to my profile in camel case and the last one on our list is property Dash details dot TSX and there we can again run rafce and change this to camel case there we go so now we have all of these components but we are yet to export them so let's create a new index.ts file inside of the pages folder there we need to import all of these components and then export them from one file this file is going to be down in the description so you'll be able to Simply copy and paste it it's going to contain just some simple imports and exports so you don't have to type them by hand great with that said we can now go back all the way by closing all of these files and going back to our app.tsx there you can see that we're exporting home was not found in Pages login that's because we have to remove the login here because now we're importing all of the pages and if we do that we are back here and you can see that this special dashboard appeared as you can see our dashboard is different from our list items list items represent resources and dashboard is a standalone home page so let's just change the icon color for that as well by going back to the cider index.tsx of The Cider component and then going to our dashboard that's on line 218 there if you scroll down a bit you can see this list item icon and then the color here we want to use the hash 808191 and if you save that you can see the color of the dashboard changed as well now to make our dashboard look the same as our resource properties we can also give it a margin left of about 20 pixels and we can also give it a margin right of about let's do 14 pixels right here so this should move it a bit to the right and we might went overboard right here so let's try to do 10. or maybe something like 6 will do there we go so this is now looking much better we can properly move between all of these Pages as you can see the URL changes and also the highlights actually change on the left side so we can be on the dashboard where we have our home component or we can move to all of our different pages great with that said we're now done with the sidebar and of course the next thing we can focus on is going to be the home page so to start with the home page let's go to our app.tsx there we specified that our home page will be the dashboard page so we can control click into it and here we are this is where we're going to develop that great looking dashboard let me show you how that's going to look there we go we're going to have the dashboard title right here then for cards two different charts and then a property list great with that said let's get started with creating our dashboard to start creating our dashboard we can first import a couple of things we're going to need the first thing is going to be the import use list hook and that hook is coming from pan code right here forward slash refine Dash core this is one of the most important refines Hooks and it allows us to get access to a specific resource such as a property then we'll have to import all of the different components we'll be using on our dashboard and if you think about it we have created all the pages but we haven't yet created the components so inside of the components folder we have to create them let's start with creating the agent folder right here inside of the components folder and that agent folder is going to have an agent card dot TSX and there we can also run rafce then we're going to have a folder for all of the charts we already have it so inside of there we can create a pi chart dot TSX and we can run rafce inside of there as well alongside our pie chart we're going to also have property referrals dot TSX and that's also going to be a regular Arrow function component finally we're going to have a chart for total revenue so we can write a component totalrevenue.tsx and create a react Arrow function component great below the chart we're also going to have a home folder this is where all of the components that we'll be using in our homepage will be and we only need one it's going to be called top agent dot TSX and we can again run rvfce inside of there there is just one component of the home and that's because we have another folder called common inside of there we'll have components that will reuse across all the different pages so let's create the first one that's going to be custom button dot TSX and inside of there we can run rafce another one is going to be a form component.tsx and we can also run refce next we're going to have a profile dot TSX where we can also run rafce and the last one is going to be a property card dot TSX maybe the most important one so far and we're also gonna run rafce inside of it great now we have to create an index.ts file inside of the components folder again in the GitHub just down below you'll find a file where we are exporting all of those components we have just created so we can simply import them in one line inside of every single other page in our project once you paste that we can close all of the currently open files go back to home which makes us ready to import them let's start by creating import and we're going to import the pie chart let's also do property referrals let's do total revenue we're going to also need the property card and finally top agent and all of these are coming from components great and now we can use them in our home that's going to be it for our Imports and we are ready to start creating the structure of our home page to get started with creating our home page we can first turn this div into a box since we're using material UI a box essentially is a div with some additional properties and of course all of these properties that we want to use we need to import at the top so right here let's import typography which is essentially a fancy way of saying a text element a box and a stack coming from add pan code and that's going to be refine Dash mui and if we save this we should be able to see what we had at the start which is an empty slate now right here we can add a typography so let's add a typography that is not a self-closing element but it's going to say dashboard let's give it a couple of props such as font size of 25 font weight of 700 and let's also give it a color equal to Hash one one one four two d now if we save this we can see our dashboard title below that we're gonna have one more box and this box is going to wrap our four charts these ones right here so that box is going to have an empty of 20 pixels for margin top it's going to have a display equal to flex and it's going to have a flex wrap equal to wrap finally a gap of four inside of there we can render our PI chart component that looks like this that is just the component that right now says by chart that's about it but soon enough we're going to develop it so that it represents some data so let's pass some props to it let's pass a title equal to properties for sale let's add a value let's say there is 684 for now we're going to leave this static we're going to add a series of an array of 75 and 25 you're gonna soon see what this is and then we can provide colors for those Series so those colors can be an array off first one is going to be four seven five b e eight and then the second one can be hash E4 E8 e f great and now immediately you can see that typescript lets us know that this pie chart is not accepting a title property so that is something that we have too so it essentially lets us know hey you're not expecting any properties here which is pretty cool great now that we have this property we can also duplicate it four more times because we need four of these and we can just change some values for the second one let's say properties for rent change this to about 550 maybe a series of 60 and 40 these are percentages we can also randomize the colors just a bit so I'm going to change some letters right here the third one is going to be total customers let's say that is equal to 5684. let's leave that to 75.25 let's change the colors just a bit again just entering some random numbers and the last one is going to be total cities so this is the amount of cities that we have in which we have properties in and that can be about 555. great now we can save that we can go into the pie chart component and we can properly accept these properties so we are accepting a title we need a value a series and colors great and we can start creating this card right here properties for sale so to do that we're going to convert this into a box and still I think we're getting that error and that's because the box is not defined so in pie chart we have to import box typography and the stack coming from at that's going to be pan card refine mui and we also need to import the interface for typescript so that's going to be Pi chart props from interfaces home like this get right now we have to specify that these props are going to be of a type pie chart prompts and now typescript immediately helps us as you can see right here we're accepting callers but in the home we provided color which is phenomenal because we know that we simply need to change this to colors and then the value is properly going to work if we didn't have typescript in this case we could have spent hours trying to find that one little typo great with that said let's create our look and feel of our card first let's add a stack within this box that stack is essentially just a div that's going to have a direction of column and inside of there we want to have two different typographies four two different pieces of text so let's create a first typography that one is going to render the title and if you save it we should be able to see it right here properties for sale rent total customers and properties for cities now let's modify it a bit by giving it a font size of 14. and let's give it a cooler equal to 808191 and of course we need a hash at the start finally below that we're gonna have one more typography much larger this time 24. the color is going to be one one one four two D and then it's also going to have a font weight equal to 700 meaning bolded and a margin top of one or Mt and it's going to render the value so now we have our title and we also have the value great finally we can render our react Apex chart by importing it at the top we can say import react Apex chart from react Dash Apex charts and then we can render it as a self-closing component just below the stack react Apex chart and self-close it we need to provided options first so that's going to be an object where the chart it's going to have another object and it's going to have a type of donut in this case so this is a donut chart it's going to have colors which is going to be equal to colors like this meaning we can just omit the latter then it's going to have a legend which in this case show is going to be false because we don't need it and it's going to have data labels again an object of enabled is equal to false because we don't need any data labels in this case so that's it for the options if we just add a final comma right here and we save it let's see if we see something nope nothing yet and that's because data labels looks like I misspelled it right here but good thing we're using typescript so it notice that and we are good to go we cannot yet quite see the chart but that's because below the options we didn't yet provided a series we didn't provide the type equal to Donut and most importantly we need to give it a width of 120 pixels now if we save that you can see those beautiful charts appear right here and not only that if you reload they're going to be nicely animated wonderful finally let's style the cards themselves we can do that by styling the Box so let's make some space and let's give it an ID equal to chart let's give it a flex property of one let's give it a display equal to flex as well we can give it a BG color of hash fcfc FC also a flex Direction of row justify content of space Dash between align items of Center PL for padding left of 3.5 py meaning padding vertical axis of 2 Gap two and finally border radius of 15 pixels minimum height or Min height equal to 110 pixels and then the width equal to fit Dash content now if we save this we're going to see the look and feel of our newly created charts of course only if we fix the error that we have right here it looks like we misspelled height so if we fix Min height there we go this is looking wonderful we have all of our charts right here we can even hover to see what it is about also some of the charts have colors that are a bit hard to see on the white background so what we can do is take maybe the third chart and then copy the colors for it to all other colors as well of course feel free to play with this and put the ones that you prefer the most if we save this now there we go this is looking great we have four different cards and if we expand this you can see they have a flex property so they're always going to appear nicely on the screen wonderful now with that said if we look at the design we're done with the first part and we are ready to begin with this second huge chart right here so on the home page we can go below our initial box and then there we can create a new stack this stack is going to have a property of empty margin top of 25 pixels to divide it from the top cards a width of 100 percent a direction equal to an object of on small devices column and on large devices meaning LG row so this means that we're going to have it next to each other on big devices but on smaller devices they're going to appear one below another great with that said inside of there we can render two different components total revenue which is our huge chart a self-closing component as well as property referrals which is this smaller chart with that said if we save it and go back we should be able to see just the texts but if we dive into this component by control clicking it we can now start developing the total revenue chart great to start creating our total revenue chart we can go back to home and to the pie chart to quickly grab some of the Imports right here we're going to get the imports from the Apex charts and the one from refine mui so we can go back and we can paste them right here we're going to also need one icon that's going to be import Arrow Circle up rounded and that is coming from add mui forward slash icons Dash material we're going to also need the chart config so we can say import total revenue options from dot slash chart dot config and there's one more config that's going to be total revenue series also coming from chart config if we quickly explore those you're gonna see that these are the ones that we provided at the start of the video that's simply some data for us to show in the chart later on you can make this Dynamic but for now we're going to use this chart config with that said let's start by wrapping everything in a box as we always do in mui applications this box is going to have some padding so we can say p is equal to four then we can give it a flex of one we can set the BG color to be equal to Hash fcfcfc we can also give it an ID equal to chart we can give it a display equal to flex a flex Direction equal to column and a border radius equal to 15 pixels there we go this is just our card now what do we have to have in this card let's look at the design so we have the total revenue and then we have last month running month this is going to come with our chart and then we have the revenue and the chart itself so with that in mind let's create a new typography this typography is going to say total revenue and now we can style it a bit by giving it a font size equal to 18 pixels of course that's going to be like this 18 we can give it a font weight of 600 and a color of Hash 11142 D if we save this our Revenue just grew a bit larger great now below that we can create a stack that stack is going to contain another typography which we can create right now and it's going to say dollar 236 comma 535 so we're showing this dollar amount again right now static but you can make it Dynamic if you want to now let's style that stack by giving it an m y of 20 pixels that's margin vertical a direction equal to rho a gap equal to four and a flex wrap equal to wrap great and we can also style the typography by giving it a font size of a huge 28 pixels a font weight equal to 700 and a color equal to Hash one one one four two D and if we save that that's going to look just a bit better but now below this typography we can create another stack this stack is going to have an arrow Circle rounded up and it's going to have an SX prop equal to an object we here we're going to have the font size equal to 25 and we're going to have a color equal to Hash 475b E8 let's check it out there we go so this is that icon and then below that icon we're gonna have another stack a stack within a stack and that stack is going to have a typography that's simply going to say 0.8 percent and we can give it a font size equal to 15. and we can give it a color equal to Hash four seven five b e eight if we save that you can see the percentage and we're just trying to achieve this look right here so finally we can duplicate this typography say instead of 1.8 we can say then last month and there we can change the color to eight zero eight one nine one and if we go back this is looking a bit closer than what we had before we can also change the font size to 12 to make this a bit smaller finally the stack above has to have a Direction equal to rho now make sure that you're editing this stack right here and not this tag that's wrapping these two elements so stack and then we have arrow that stack has to have a direction of row also align items equal to Center and finally a gap equal to one if we save this that's going to look just a bit better there we go so the last thing we need is going to be the chart itself and we can do that below this last stack right here we can render a react Apex chart a self-closing chart that's going to render series equal to total revenue series like this we imported that at the top and then we can render the type in this case it's going to be a bar chart we can set the height to 310 and we can provide options equal to total revenue options now if we save this the chart appears now as you can see this is still not looking exactly like it does on the design it looks a bit stretched out it has a bit too much height so let's see where the issue could be it's most likely going to be in a stack that wraps our chart as well as our typography so there instead of doing my 20 which is 20 times the special material AI unit we just want to do 20 pixels that's going to make all the difference there we go so now if we expand this we have a beautiful Revenue which also is fully responsive as you can see right here so it's going to adapt to any size and also just to show you if we reload we're going to have a wonderful animation and we can also hover over it to get more details we can also click right here to collab specific pieces and it's going to nicely animate Apex charts really is phenomenal so I highly recommend you checking it out but in this case I prefer this one with that said we can move to the second piece which is property referrals we can close the total revenue and then go to home and control click property referrals great to get started with our property referrals we can once again import the Box the stack and the typography coming from pan card refine mui great now on top of that we're gonna also import a property referrals info which is coming from Constance forward slash index great let's just spell it properly so we don't have any mistakes later on and we should be good to go now to get started with property referrals we can again turn this into a box and it's going to have almost the same exact properties as the previous box so let's go to total revenue and let's simply copy all of these properties go back and then add them right here now let's see padding is going to remain for Flex in this case we don't need Flex BG color is going to remain the same ID is fine in this case we'll have to add a Min width of 490 display Flex for the radius 15 and flex Direction column great inside of there we can also have a typography which is going to be the same as in the total revenue so we can simply copy it go back and paste it right here that's a typography with a font size of 18 font weight of 600 and the color of 1142d and it's going to say not total revenue but rather property referrals there we go now if we save this we should be able to see that box appear right here below and there below this typography we want to add a stack that stack is going to have an my of 20 pixels a direction of column and a gap of four and inside of there we want to map over all of these bars so if you look at this we're going to have a couple of different bars each bar is going to have a name or a title a percentage and then the this bar that's going to represent the percent filled so to make our life a bit easier we're going to create a new component called progress bar can't progress bar is equal to an arrow function or rather a functional component with an instant return meaning just put parentheses right here and we're going to pass a couple of props to it we're going to pass a title a percentage and a color and since we're in typescript we have to Define this as an interface so right here we can say interface progress bar props and that's going to be a title of string it's also going to have a percentage of number and it's going to have a color of string and now we can Define our progress bar props as progress bar props great now how is our progress bar going to look like well first we have to have a stack with a title any percentage on top so let's create a box element that box is going to have a width of 100 percent inside of there we're going to have a stack and that stack is going to have a direction equal to row because here social media is in the left side and then we have on the right side of percentage it's also going to be align items equal to Center and justify content is going to be space Dash between as you can see right here social media on the left side and percentage on the right side inside of there we want to have two different typographies so typography one is going to Simply render the title and we can give it some styles font size of 16 font weight of 500 and finally a color of hash1142d and finally we can duplicate this topography below render the percentage and add a percentage sign after that now if we save this and go back nothing is going to show because we're not using this progress bar yet so right here below let's Loop over all of our property referrals info call a DOT map on it get each individual bar and for each bar return a progress bar self-closing component to which we can pass a key equal to bar.title and we can spread out all of the rest of bar properties now this property referrals info is simply an array of a lot of different titles percentages and colors copied from this design right here so if we go back and now we should be able to see social media 64 Marketplace 40 and so on great but now we have to implement the bar itself this part so that's going to be right below the stack right below the stack we can create another box that box is going to have a margin 2 to divide it a bit from the top a position equal to relative a width of 100 percent and a height of only 8 pixels finally a border radius of 1. and a BG cooler equal to Hash E4 E8 e f and finally inside of there we can render a box that box is going to be a self-closing component it's going to have a width equal to a template string of percentage and then we can add a percentage sign at the end and most importantly it's going to have a BG color equal to color now if we save this and go back we can already see empty bar lines now the only thing we have to do is give it a position equal to Absolute and this is going to make the colors appear on top of these elements of course after giving it a height of 100 percent and a border radius of one there we go so now we can see those items appear right there and you can see we are not in the full width right now of the browser but still everything looks and feels so nice and if you expand it further you can see how nicely it appears on the right side right here the one thing that we're missing is the spacing between the total revenue and property referrals so if we collapse this we can now close the appropriate referral since we're done with that on this stack wrapping the revenue and property referrals we can add a gap property of four and that's going to give us a gap between those two elements there we go it just appeared so if we expand it you can see how beautiful this is we have our fully animated charts right here we also have our charts on the top and we have property referrals on the right side this is all a process of creating a dashboard but now we're going to dive into creating properties and that's where we dive into the full stack part of this application if I open up our figma design you can see that now we're going to start working with property lists meaning we have to be able to create those properties read them update them and delete them so we're diving into an interesting part of this video right away for now we can be happy with the dashboard we can close our our home and go to our app and we can start implementing our first ever resource or property so instead of rendering this mui dummy component we can render a list of all properties and if you remember correctly that was one of the pages that we imported at the top as a matter of fact while we're still here let's put all of our pages to use we're going to show all properties on a list but if we want to show an individual property then we can show property details if we want to create a property we're going to render create property and if you want to edit property we're going to render the edit property page refine provides all of these out of the box so you don't have to worry about crowd functionalities you just have to create pages that implement it and then everything is going to work right out of the box so now if we go to properties you can see all properties and then later on once we re-navigate to one of these individual properties refine is automatically going to render the property details now we can do a similar thing with our agent we're going to render a list of Agents and we're going to render a show of agent profile for our review that's just a dummy list item so we can re-navigate it back to home same thing for message but then our profile is a real component where we can render the my profile page great with that said we can now navigate between all of those pages which is looking great and we're going to start with implementing all properties first so we can close our app DSX and we can go to that's going to be pages and all properties we're finally diving into the action to get started with creating our properties we're first going to import a couple of things our properties are going to be the first page which we're going to code completely on our own so let's get started first we can import an add icon coming from that's going to be add mui forward slash icons Dash material then we're going to import a special hook called use list this is going to allow us to fetch all of the properties later on and that is coming from add pan card forward slash refine Dash core then we're going to import a couple of things from mui that's going to be a box stack and a typography coming from add pan card forward slash refine Dash mui and finally we're going to import a hook called use navigate and that's coming from add pan card forward slash refine Dash react Dash router Dash V6 as you can see all of these features are provided to us by refine so we don't have to worry about setting up mui manually or setting up react router great finally we can import two components which we're gonna use later on the property card as well as the custom button coming from components right now inside of here we can immediately initialize some hooks for example cons navigate is equal to use navigate and we call it as a hook I just noticed that I misspelled it so that's going to be Navi gate there we go and we can fix it right here and immediately if you reload we're going to get an error saying that react hook use navigate is called in all properties which is not a react functional component but technically it is there's just one slide mistake when we're using that snippet of code it created all properties with a lowercase first letter but since it is a component we have to rename it to all properties where a has to be capitalized and there we go now we're good because our IDE knows that we're working with the react component great now we can start creating the layout of our application so that's going to be inside of a return and we can see that we don't have access to a custom button because I misspelled it that is supposed to be an N at the end and there we go we're good so instead of this div we're going to have a box element and within that box we're going to have a stack element that stack is going to have a direction equal to row a justify content equal to space Dash between and align items equal to Center inside of there we can render our typography this typography is going to say all properties and we can of course style it a bit by giving it a font size of 25 font weight of 700 and a color of hash 11142d and we can save that and we get this wonderful heading and immediately below that typography we're going to create our custom button it is going to be a self-closing component and we can pass a couple of props to it we're first going to pass a title equal to add property then we're going to add a handle click functionality which for now we can leave as an empty callback function then we can pass a background color equal to Hash 475b E8 and then we can pass a cooler which is going to be fcfcfc and finally we can pass an icon which is going to be a self-closing component of add great now we can immediately see that typescript says hey you cannot pass a title to a custom button because it's not accepting it so let's move into creating a custom button and we can add custom props to it so right here we can import a button coming from that's going to be add pancod forward slash refine Dash mui then we can also import our custom button props coming from interfaces forward slash common and if you control click into it you can notice that our custom button has a type but the type is not needed sometimes and it has title background color color full width icon and so on so now our button knows what we need so let's get all of those props by saying type title background color full width and finally icon and most importantly handle click and then we can say Colin custom button prompts we're saying the props are going to follow this structure and with that said the error is gone but now at the top right we have a text saying custom button so let's implement it we can simply return in this case a button of course so that's going to be a button component and that button is going to render the icon so we can render the icon right here and we're going to render the title just below if we save this immediately we should see add property which looks much better but now let's style it further that button is going to have an SX property which is used for styling and it's going to have a flex if it is full width then it's going to have one usually it's going to be unset then we also want to give it a padding of 10 pixels horizontal and then 15 pixels vertical we also want to give it a width which is going to be if full width then we want to give it 100 percent otherwise we can say fit Dash content then we can also give it a Min width of 130 we can give it a background color equal to the background color we passed as well as color equal to the color we passed through props then we can give it font size of 16. font weight of 600 gap of 10 pixels text transform equal to capitalize and we can do and column hover so meaning on Hover we want to set the opacity to 0.9 like this as numbers and then we can also give it the same background color there we go finally the last thing we have to do below the SX prop is we can pass an on click equal to handle click meaning whatever we pass to it it's going to do that thing now if we save it you can see we have this wonderful wonderful button add property and right now it doesn't do anything but if we go back to all properties we can add a real handle click to it and that handle click is going to use the navigate hook so we can say navigate and we want to navigate to forward slash property forward slash create but now that I think about it better thing would be to say properties create this way we're following better crowd naming conventions so we have to fix that somewhere and that is going to be in the app.tsx right here under all of our resources see how we name this property well this right here is going to be properties this is going to be agents reviews messages my profile is fine so we always want to use plural when we talk about specific resources in our crowd rest apis immediately changing this change the route so if we now go back and click properties it's going to renavigate us to the correct route now and we can go back and we're no longer going to navigate to property but rather properties now if we click right here you can see we have properties create and that opened up a new page now how did it know to show create property at the route properties create well it's as easy as checking our app DSX and checking out the resources right here we added everything it needs to know the name properties which is going to correspond to this URL the list showing on all properties meaning just properties and then create is going to be on the properties forward slash create and then we render the create property page wonderful now I would want to keep doing the old properties and now show them but we cannot do that as there is nothing to show so first we're going to focus on the create property then we're going to connect it to the back end and then we can finally work on showcasing those properties to get started with our create property we can first import a use State hook coming of course from react we can also import a use get identity hook coming from add pan card forward slash refine Dash core this hook will allow us to easily get all of the user related properties such as name email and profile photo we can also import field values and most importantly the use form hook coming from add pan card forward slash refine Dash react Dash hook Dash form like this really soon you'll see how powerful the use form Hook is after that we can import the use navigate hook which is coming from react router V6 and then finally we can import the form component coming from components forward slash common forward slash form this is a component we are yet to create before starting with the layout we can first initialize all of the hooks at the top so that's going to be const navigate is equal to use navigate and as soon as we do that you're going to get an error saying you cannot create a hook inside of something that's not a react function and the reason why our IDE thinks that is because we called it with a lowercase starting letter so we have to change this to create property with a Capital C and we're good after that we can say const data and then rename it as user is equal to use get identity this will allow us to get all the user info because we need to know who is creating this current property after that we're going to have a hook which is going to be a use State more specifically called property image and set property image and that's going to be equal to a use State hook which is going to be at the start an object that's going to have a name equal to an empty string and a URL equal to an empty string if you think about it all of our properties will have some kind of photos attached to them so we need to be able to store that state in a photo but absolutely everything else besides our photo is going to be handled by that's going to be equal to use form hook coming directly from refine so what specifically can we get from that hook well let's expand our Visual Studio code just a bit and then let me show you what we can get let's type refine core and from there we can destructure the on finish as well as the form loading so immediately know if the form is loading and when we are done now next to refine core we can also get the register through which we can register every single input or text field and then we're going to also get the handle submit so we can submit everything and send it to the server that is it a lot of functionality packed in this incredibly useful hook now let's collapse this back right here and we are ready to start creating the layout believe it or not our entire create property is going to be consisted of one single self-closing component and that is form so right here inside of the form we can start sending many different properties first of all we're going to send a type equal to create because later on we're going to reuse the same form for the edit functionality that's the primary reason why we are creating the separate component for the form in the first place now we also want to pass register equal to register on finish equal to on finish we're going to also pass the form loading equal to form loading we can pass the handle submit equal to handle submit and finally we can pass the property image equal to property image now there are two additional things we have to pass and these are going to be extra functions which we're going to create the first function is going to be called handle image change and for now we can simply leave it as an empty react Arrow function and below that we can create const on finish Handler and that's also for now going to be an empty Arrow function great now we can pass those as well so right below handle submit we can pass the handle image change it's equal to handle image change and finally we can pass on finish Handler is equal to on finished Handler now as you can see we're immediately getting the error right on the type property and that's because if you now control click into the form you can see there's nothing there so we of course have to set up our props and typescript interface for our form properties so let's do that right away inside of a form we're going to import a lot of properties from mui that's going to be a box a typography which is just a text element but in this case we're going to have deform control as well a form helper text then we're going to have a text field a text area Auto size a stack a select a menu item and finally a button and all of this is coming from at Punk card forward slash refine Dash mui now as we discussed we also have to get the form props coming from interfaces forward slash common and let's also get our custom button since we worked so hard on creating it so that's going to be custom button from dot slash custom button great so now let's grab all of the props that we passed from the create property so right here inside of the prompts that's going to be a type register handle submit handle image change form loading on finish Handler and property image and all of that is going to be of an interface form props so now typescript shouldn't complain let's see what we have here that's property image property register does not exist on type form props and if you save you can see that typescript is no longer complaining which means that we're good to proceed with creating our actual form so to do that we're first going to wrap everything inside of a box that box inside of it is going to have a typography so let's create a new typography element and that typography is simply going to say type a property now of course that doesn't mean type a property but type is rather the type of the form it's either create or edit in this case it says create a property great now let's make it just a bit bigger by giving it a font size equal to 25 a font weight equal to 700 let's also give it a color equal to Hash one one one four two D and let's save it that should give us a pretty title great now below that we can create a box that's going to act as a wrapper for our form it's going to have a margin top or empty of 2.5 to divide it a bit from the typography above we're going to give it a border radius of about 15 pixels let's also give it a padding of 20 pixels and most importantly a BG color equal to Hash fcfc FC if we save that we'll be able to just barely see our form and this is where all the inputs will go so inside of the Box we can finally create a form component to that form we can pass a style of margin top is 20 pixels we can also give it a width of 100 percent we can give it a display equal to flex and it looks like I missed a comma right here and finally after display Flex we can give it a flex Direction equal to column since we're going to show all of our text Fields one on top of another and finally a gap of 20 pixels now if we save this you won't be able to see anything because there's nothing in it and finally we're going to have an on submit on our form which is for now going to be equal to handle submit remember this was created for us by refine and then to it we can pass the on finish Handler again everything is already done for us we'll simply have to pass the right things when we call the on submit and inside of the form we can start creating our inputs so let's create our first form control A4 control is an element that wraps the form helper text and also it wraps the text field so they act together as one text field is going to be a self-closing component that looks like this so if we save this and if we write something in this form control something like enter property name you can see that we have a text field and we have the helper text so the user knows what to type in now let's style them now to style it we can give it an SX property equal to font weight of 500 we can give it a margin of 10 pixels on top and bottom and 0 on left and right let's also give it a font size of 16. and finally let's give it a color equal to Hash 11142d now if we save this that's going to look just a bit better and we can start creating our first text field this text field is going to be of a full width it's also going to be required we can give it an ID equal to outline Dash basic we can give it a color equal to info and we can give it a variant equal to outline now if we save this we're going to just have a bit of a better looking input now if we save this you can see that our input is looking great and now for the most important part we can spread dot dot register and then we can call it as a function and pass the title of that text field in this case it's title and we can set the required equaled to true this is the only thing you have to do to manage the data or to manage the state of that input refine is going to handle everything else once called the handle submit Handler great with that said we can proceed to our second form control and since it is really similar to this one let's simply take this one and duplicate it below the form helper text is going to be the same but rather it's just going to say property description and we can save that but instead of having a text field we're going to have a text area Auto size so let's delete the text field and let's create a text area Auto size it's also going to be a self-causing component we can set Min rows to 5 and if we save that that's already going to look just a bit different we can also give it a required property a placeholder equal to write description that's good we can give it a color equal to info and we can give it a style now bear with me we're going to give it a width of 100 percent let's give it a background equal to transparent let's give it a font size equal to 16 pixels to make it a bit bigger we can give it a border color equal to rgba 0 0 0 and then 0.23 for the a or the opacity we can close that string right here we can give it a border radius of 6 to make it a bit rounded and let's save it and see how does it look like right now okay that's just a bit better after the Border radius we can give it some padding like 10 and we can change the color to Hash nine one nine one nine one and if we save that this is looking much better finally to register it we can simply copy the registration from the last input and paste it here register this time not the title but rather the description great now after our text area Auto size and after form control still being inside of the form we're going to create a stack and that stack is going to have a direction set to row as well as a gap of four inside of it we want to create yet another form control this form control is going to have an SX property equal to flex set to 1. and then inside of it we can create a form helper text form helper text rewardee created these before and we can give it an SX property of font weight of 500 a margin of 10 pixels and then 0. a font size of 16 and a color of hash 11142d and finally we can say Select Property type now if we save this we'll just see another one of these helper texts but below that we're not going to have a text area we're not going to have a text field we're going to have a select element so just below the form helper text let's create a new select element that select is going to have a few props so we can expand this give it a variant equal to outlined we can give it a color equal to info display empty required input props is going to be equal to an object where we can say area Dash label is going to be set to a string of without label like this and then default value is going to be apartment so right here we can say apartment and of course there's going to be an equal sign right here great and apartment is spelled with 1p so let's fix that right here finally we need to register this property as well and that's going to be as simple as saying register property type and required is set to true and with that you'll see this select element which right now is empty so we have to provide some menu items to add let's do that right away by creating our first menu item that menu item is going to have a value equal to apartment the title equal to apartment with a capital A now if we save that you should be able to see our first and only option now we can repeat this for all of our property types so let's duplicate this maybe eight more times below and also let's expand this just a bit so we can see it better in one line there we go so the second one is going to be a villa so let's type Villa right here then we're going to have a farmhouse again Farmhouse with a capital f then we're going to have a condos there we go again condos with a Capital C after that we're gonna have a townhouse and a townhouse with a capital T we're gonna have a duplex so let's type a duplex right here and duplex we're gonna have a studio as well as a studio right here and finally we can have a chalet like this and there we go now if we save this you should be able to select between all of these elements and for this we're using material UI they make this so easy now below or next to our property type we want to have another one of these text Fields so let's go to our first text field which was just a basic title and let's copy the form control for the entire title we can go down and we can paste it just below this form control wrapping the select we're going to keep all of this the same we're just going to change the form helper text to enter property price and when it comes to changing things in the text field everything is going to be the same but we're going to also add a type equal to number since we're talking about a price and right here we're going to register it as a price input and if we save this you can see we have enter property price on the right side and if we collapse this you can see everything is still fully responsive even on smaller screens with that said we can copy the same form control that we just created and go below this form control and below the stack and there we can create one more form control that's going to say enter location so right here we can say enter location and it's not going to be a type number so we can remove that and we can just say register location there we go so now we should have location as well and this is already looking like a real form finally below that form control we can create one stack this stack is going to have a direction equal to column as well as a gap equal to one and a justify content equal to Center as well as a margin bottom of two inside of there we'll want to create our button that's going to be used to upload the photo but first to style it better we're going to create another inner stack that stack is going to have a direction equal to rho as well as a gap equal to two inside of there we can create a typography element and that typography can say property photo we can style it a bit by giving it a color equal to hash 11142d a font size of 16. a font weight of 500. and a margin y meaning on top and bottom 10 pixels if we save this that's going to give us an error and that's because I missed a t on weight so if you fix that we should be able to have a property photo down below and with that we can create our button so still inside of the stack just below the typography let's create a button component that button is going to say upload and then we can put an asterisk right here meaning it is mandatory and we can start styling it by setting the component equal to a label and giving it an SX property equal to width set to fit Dash content color is going to be set to Hash to E d480 and we can say text transform is going to be set to capitalize to make it like a call to action button and we can give it a font size of 16 for it to be more easily noticeable great let's save that okay that's looking great and below that or inside of that we can create an input that input is going to be a self-closing hidden property or tag and we can say accept is equal to image and then forward slash asterisk meaning everything type is going to be set to file and then on change is going to be set to a callback function where we get an event and then we can call handle image change and then we can call it with e.target DOT files zero so we want to pass the first and only image to add now you can see that tapse is complaining that we might not have a file right here that maybe it is null but will make this field mandatory meaning it will have to be filled so for now we can simply create a comment and say at TS Dash ignore that's going to ignore that warning right here great now below the button and then below the stack we can create one final typography this typography is going to say property image question mark dot name so we're going to Simply render the name of that uploaded image we can give it a font size equal to 14. a color equal to hash 808191 and we can give it an SX property of word break equal to break Dash all great now if we save this you cannot see it now but if we upload something you will be able to see the name of that photo below the stack still inside of the form we want to create our last and most important button that's going to be a custom button it is a self-closing button and it's going to be of a type is equal to submit it's going to have a title if we are loading the form then it's going to say submitting dot dot else it's going to say submit and finally it's going to have a background color equal to hash 475 be8 and it's going to have a color equal to Hash fcfc FC and if we save that you can see it right here great with that said we have completed our entire form and it's looking great so now if we expand it you can see it is fully responsive and it looks great even on mobile devices and we are ready to start testing it out so now we have the form we have the create property but of course we have to do the logic to connect it handle image change and on finish Handler these are the two last missing pieces of the puzzle so when it comes to the handle image change I'm gonna make this one easy for you down in the description below in that same GitHub gist you'll be able to find the finished handle image change function code so you can simply get it from there and paste it here the reason why we're doing this is because this is simply some regular Javascript file reader stuff we're simply getting the file and then we are reading the data from it once we read it we're simply setting it to the state now nothing more nothing less but what really matters and what I want to focus on is the on finish Handler this is where we're using refine we're passing all the data that we're getting from the form and finally submitting it so that our backend can create a record in the database and that we can experience all of the best crowd functionalities we can start by accessing all the data that we have from our form so we can say data and that is going to be of a type field values great then we can check if there is no property image dot name that means that the user hasn't uploaded the image so in that case we can return an alert saying please select an image and finally if we do have an image we can await on finish remember that's coming from refine and we can pass everything to it by everything I mean an object inside of which we can spread all of our data from inputs we can add our photo which is equal to property image dot URL and we can add the email of the user that created that property that's equal to user dot email remember that's again coming from refines use identity hook great and of course since we're using a weight here we have to make this function async great and this alone should allow us to create our post but if you think about it this is only allowing us to pass the data to the right backend endpoint and since we're building a full stack application it is our job to create that backend to create that endpoint that's going to listen for this request to create a record in the database and then to Showcase it later on on the front end and that's exactly what we're going to do next now we are at a breaking point we are the point where we can start creating our backend so let's go ahead and close all for currently open files and open up the file explorer to start creating our backend from scratch we can right click here in the Explorer create a new folder called server we can then go to view and then terminal make sure that you see the dot dot to move to the root of our directory and then CD to server so that we are in here now we can run npm in net Dash y this is going to initialize an empty packet Json now while we're here we can also add a type is equal to module right here that's going to allow us to use the modern import export syntax and we also have to install a couple of dependencies so let's clear the terminal and run npm installed we're gonna need cloudinery and we're going to use that to serve our images then we're going to have course for cross origin requests we're going to have dot EnV for safely storing our environment variables of course Express and Mongoose as well as an old man with that said you can run this command it should take just about a minute and then we can move into the packet Json to see if all of the dependencies have been installed correctly and it seems they have now we also need to change our scripts so from test what we can do is we can create a start script which is simply going to run a command node mod Index this is going to make sure that our server gets started gets spinning with that said we need to create that starting index file in the server so right click right here new file and do index.js instead of here we can import of course Express from Express which we'll be using to create routes for our entire application then we can import everything as dot EnV from dot EnV this allows us to use environment variables we're going to also import course from course for cross origin requests now we can configure dot EnV by running the dot env.config and calling it as a function and we can also initialize our app by saying const app is equal to express and we call it as a function we also need to say app.use which is the way we're adding middleware to our application and there you can use course and also we can add an additional piece of middleware by saying app.use express.json and then inside of there you can pass limit is 50 megabytes we want to specify the limit for the files we'll be sending from the front end and we can create a dummy route app.get is just forward slash meaning a root route and then we have a callback function of request and response that looks like this for now we can simply do res dot send message is equal to hello world that way we know that our backend is running finally we have to start the server so let's create a new function const start server is equal to an async function like this we're going to have a try and catch block so if something goes right we're going to be in the try and if we catch an error it's going to be caught right here so if we have an error we're simply going to console log it and what do we want to do in the try well we want to try to connect to the database that is a really important part and to keep our code tidy we're going to create a new function and a new folder in the server called mongodb and inside of there we're going to have a function called connect.js inside of that connect we're going to import Mongoose coming from monogous Mongoose is a modeling library for mongodb it's going to allow us to make models more easily in schemas and then we can here create a const connect the B function that accepts a URL or a URI and it's going to look something like this Mongoose that set strict query like this is going to be set to true this is going to save us later on after that we want to run Mongoose dot connect like this and we want to pass the URL now this is an async function so we can chain a DOT then on it and if we're successful we can simply type console.log mongodb connected otherwise we can catch an error and simply console log it and of course we have to export default connect to DB so we can use it within our index now it looks like we have some typing errors right here Mongoose dot set expected something else I think we should be good hopefully we're not gonna have problems with Visual Studio code because the syntax indeed is valid great so what we can do now is go back to index and we can import connect DB coming from dot slash mongodb forward slash connect and since we're not in react I think we have to specify the extension as well that's connect.js now we can use this function connect DB right here inside of the start server we want to connect to the DB and then in here we need to pass a special mongodb URL right now we don't have it so that's going to be the next step let's go to mongodb atlas to get it you can visit mongodb.com forward slash Atlas forward slash database and then click try for free in my case I already have an account so I'm gonna sign in you can log in or register using Google or GitHub once you register or log in you should be able to see something like this you should find a place where you can create a new project in this case we're going to name our project yariga which is the name of our real estate application and I'm going to click create project now inside of here we'll have to build a database so click that button and we're going to choose a shared free cluster it's going to ask you a couple of questions choose the region closest to you and click create cluster now you'll have to enter a username and a password in this case I'm going to do JavaScript Mastery and I'm going to choose my password make sure to remember this password because we'll have to use it later on within our code great that's it when it comes to quick start now we can go to network access and make sure to click add IP address and then allow access from anywhere this is going to allow us to access our database now locally but also later on once we deploy our application great finally we can go to database connect and then we want to connect using your application and in here you're going to get your url but as you can see you'll have to replace your password right here so let's copy it and now inside of the server you have to create a new DOT EnV file we called it mongodb URL so let's do DB underscore URL is equal to and then you can pass your url again as you can see you'll have to type in your password right here I chose one two three one two three a like this make sure to type in your own password and your own username for this to work great now that we have that we are now referencing that mongodb URL right here by saying process.env.mongodb underscore URL and we are trying to connect to our database once we are connected we can then run app.listen on port 8080 like this and once we are listening we can create a callback function that's going to console.log and say something like server has started on Port 8080. you can even type HTTP colon forward slash forward slash localhost Colin 8080 that way you'll be able to click it and since we have this function we can of course call it start server and this is all that we need to properly connect to the database and start our server so let's close all the currently opened files let's go to view and then terminal and let's run npm start if everything goes right well this is not right right so it says Mongoose that set unexpected token this is what I was scared about it looks like it is giving us some issues right here even though the syntax seems to be correct oh it is not correct I had a mistake hopefully you caught that much earlier than I did right here we're missing an end of an arrow for our function so hopefully you caught that mistakes and typos happen now we can stop it from running by pressing Ctrl C and then Y and we can simply Run npm start one more time and hopefully now everything goes smoothly still it didn't it looks like strict policy or strict query was not typed right this right here was supposed to be strict so hopefully you caught that as well and third time's the charm if we run it one more time hopefully it's going to work there we go server started on localhost 8080 mongodb connected now you can hold Ctrl and click this URL and you should be able to see a Json output that says message hello world which means that we are live also in this quick process I also taught you how to create a new mongodb database Cloud cluster which essentially is completely free and allows you to store data on the cloud with that said we're now done with the mongodb function but we are yet to create our models or schemas for the data we'll be using later on so let's right click mongodb create a new folder called models inside of our models we're going to have a user.js model so what we can do is import Mongoose from mongoose and then we can say const user schema is equal to new Mongoose dot schema and then we pass an object for options there we can have a name which is going to be of a type is equal to string and required equal to true then we're going to have the email also a string and also required finally we're going to have an avatar which is going to be also a type string and also required that's the photo and then we're going to have all properties every user will have a list of their own properties so this right here is going to be an array so make sure to put it in square brackets an array of objects where type is going to be of mongoose dot schema dot types dot object ID so we're going to have a type of object ID and it's going to be a reference a ref to a property object like this great that's it for our user schema so we have to create it into a model right now by saying const user model is equal to Mongoose dot model called user based on the user schema and then we can export default user model great and let's fix the spelling right here great now we can create another model called property dot Js we have to follow the same rules that's going to be import Mongoose from mongoose then we can const property schema is equal to new Mongoose dot schema and then we can start giving it properties it's going to have a title which is going to be of a type string and required equal to true it's going to have a description also string required to true it's going to have a property type which is going to be also believe it or not a string and required to true then it's going to have a location which is going to be a string required to true it's going to have a price which is going to be of a type number and required to 2. it's going to have a photo which is going to be of a type string because it's a URL and required to true and finally it's going to have a Creator which is going to be of a type Mongoose dot schema dot types dot object ID and then we are referring it to a user that created it so we have a two-way reference a user can create multiple as you can see this is an array multiple posts or properties and one property can belong to one user or a creator finally we can say const property model to define the model out of that schema by saying Mongoose that model property based on the property schema and finally we can export default property model great now we can use those models to create the instances of these documents in our database so we have mongodb we have models we have index but we don't yet have the routes if you remember correctly on the front end we set something like forward slash API forward slash V1 forward slash properties and then maybe for slash create we'll have to see but we have to have this route right now we only have forward slash localhost 8080 and just slash that's it nothing's there so let's go ahead and create the routes for our application by creating a new folder on our server called routes inside of our routes we're gonna have a new property Dot routes.js and we can create one for our users by saying user Dot routes.js inside of here we're going to import Express coming from Express and then we have to import all the controllers now if you're new to the backend development you might be wondering what is a controller route is pretty much self-explanatory right it's a specific route we can visit or ping from the front end but what is the controller well to simplify my explanation mdn web docs comes to rescue especially Express tutorial part 4 routes and controllers right here we can see that from the front end we're gonna make an HTTP request right here then that's going to be forwarded to routes and then every single route is going to forward the request to the appropriate controller right here and then that controller is the one that's connected to the models and the database controller is the logic for each route and the route is just the endpoint so before creating routes we also have to create controllers so let's say controllers and then let's create two separate files that's going to be property dot controller .js and also user Dot controller.js let's start by defining all of the controllers for the user first we have to import user coming from that slash mongodb forward slash models forward slash user.js and a controller is nothing more than a simple function so we can say const get all users that's going to be one of the controllers and controllers are usually asynchronous because it takes some time to do something with the database for now we're going to leave it as an empty callback function then we can create the second one const create user is equal to async rec res then we can create another one which is going to be called const get user info by ID like this that's also going to be an async empty function for now and that's it we need to be able to create the user get all users at get user info by ID finally we need to export them by saying export get all users create user and then get user info by ID great now we can repeat the procedure for properties inside of here we're going to also import the property model that's going to be property coming from dot slash mongodb forward slash models forward slash propertyjs and in this case we'll also have to have the user model so we can say import user from mongodb models user.js and let's create those controllers const get all properties is equal to an async function where we have a wreck and a res and a callback function which right now doesn't do anything then we're going to have another one const get property detail is equal to an async Rec and res function like this then after that we're going to have a create property cons to create property is equal to an async reconrest function as before and then also we need to have an update property const update property is equal to an async Rec and res empty function for now again we're working with full crowd functionalities so the last missing piece is cons the lead property is equal to async rack and res and with that said we have get everything get detail create update delete that is it create read update and delete full crud so we can say export and we can export get all properties get property detail create property update property and delete property great now we can utilize all of these controllers inside of our routes let me show you how that's going to work we can start with our user routes first and here we can import create user get all users and get user info by ID and we can import all of that from dot slash controllers forward slash user dot controller.js then we can initialize an instance of a router by saying const router is equal to express.router and then we call it as a function and finally we can start creating a route we're going to have as many routes as many we have controllers so that's going to be router dot route in this case forward slash and then dot get and then we're going to get all users like this now we can duplicate this two times the second one is also going to be on the forward slash but it's going to be a post so we're gonna call a create user controller and then the third one is going to be on forward slash column ID meaning once we reach a specific ID then we want to get user info by ID and finally you need to export that router so export default router hopefully all this makes sense now we do have a couple of folders a couple of files everything divided in a couple of places but that's for a good reason imagine if you had all the routes and all the controls in one place it would be a mess but like this we note that we have our user routes and each route corresponds to a specific function we're going to call from within our user controller now we can repeat the procedure for our property routes there we can import Express from Express we can also import all of the different controllers first one being create property then we're going to have delete property get all properties then we're going to have get property detail and the last one is update property and all of that is coming from dot slash controllers forward slash property dot controller dot JS and again make sure to have that extension because I don't think it will work without it then we need to create an instance of our router const Router is equal to express that router and we can create all of our routes router dot route forward slash dot get and then that's going to get us all properties we can duplicate this a couple of times the second one is going to go to column ID we want to get property detail by that specific ID the next one is going to be just slash but it's going to be a post route because we want to create a property then we're going to have again a column ID but this time it's going to be a patch route meaning we want to update a property or patch it up and finally we're going to have again a column ID but this time it is going to be a delete so we can call a delete property controller finally we can export default router once again I hope this makes sense imagine if we had all the controllers in one file mixed property users and then all the routes in one file mixed that would just be a mess this way we can know which routes we have that correspond with specific resources and refine has done a wonderful job with this because every single resource is listed right here we have properties which is great with that said we can go back to the index.js of the backend and we can import those routes so at the top right below are import connectdb we can import user router coming from dot slash routes forward slash user Dot routes.js and we can also import property router coming from dot slash routes forward slash property dot routes dot Js and now we can make use of them by calling middleware so that's going to be app.use forward slash API four slash V1 forward slash users and then we attach a user router one more time app.use forward slash API forward slash V1 forward slash properties and then we pass in the property router now all of the routes are hooked up and we are good to go but whenever we call any one of these routes be that API V1 properties and then maybe a route to get properties to get property details to create a property it's all going to be good they're actually going to get cold but if we go into controllers of those properties you can see that they're not going to do anything so now is our time to actually implement the logic of creating instances and documents in the database on creating users creating properties and linking it all together so the fun part begins now even though we were about to create the create property functionality there is one thing we have to do before if you think about it right now once we log in that's it we just log in but we don't officially create an account in our database so if we were to proceed with create a property now we wouldn't be able to link it with a user in our database because it doesn't exist it just exists right here in the browser so what we have to do is now that we have the backend controllers we can hook up the client side to our server to create a user in the database and then that user will be able to create a property so hopefully that order makes sense and to implement our user creation we're going to go to app.tsx and then we're going to scroll a bit up and you can see right here that we have the login functionality right now yes we are logging Us in and we're setting the user login to local storage but we're not doing anything with the database and that's exactly what we will do right now so once we get this profile object then we want to save user to mongodb great so let's get started with that right away to save our user to the database we first have to of course check if there is a profile object meaning if a user is logged in and then if that is the case we can say const response is equal to a weight Fetch and then we need to trigger our API by saying HTTP colon forward slash forward slash localhost 8080 forward slash API forward slash V1 forward slash users there we want to create a second parameter which is going to be an object with options in those options we need to provide a method which is going to be a post method because we want to create a user we also want to provide headers which in this case will be content type application Json and make sure to type it exactly like it is typed here content Capital C type capital T with a dash in between and then application Json finally we can pass our body our body is going to be Json Dot stringify and then we're going to pass in an object we want to pass a name equal to profile obj.name we want to pass an email equal to profile obj dot email and finally we want to pass an avatar equal to profile obj dot picture and with that said we're passing everything we need but you can notice that we cannot use in a weight right here because we're not in an async function so simply make the login an async function Gray rate and then once we get the response back from the database we can do that right here below closing it we can see Khan's data is equal to a weight response.json this is going to contain the data of our actual user in the database and then we can do what we're doing here we can remove this if by checking for the profile object because we already have that and then we can bring this a bit above inside of this if right here so we're getting the data and then we want to set local storage user to be json.stringify dot dot profile obj and we also want to pass the Avatar and finally we want to pass the user ID to data dot underscore ID and that's all that we need to do but this is only going to happen if the response is 200 so we can say if response that status is equal to 200 then we can call this entire block of code and if it is not meaning else we can simply say return promise dot reject like this and then we're closing this if statement and finally we're going to set our user to the local storage and return promise.resolve so what we have done is we're not only storing the user in local storage but we're also creating it in the database hopefully that makes sense and while we're here why stop there why not also look into the logout function inside of the logout we won't have to do a lot because we are not going to actually delete a user once we log it out so this one is already done when it comes to the check auth and all of that that is already all done for us by refine so with that said we successfully have the ability to create the users in the database now to show you I can log out and before logging in again we need to go back to the back end and we need to create our create user controller so we can go to server controllers user.controller.js and we have to implement the create user function to do that we can expand it a bit we can also get all the data we just sent from the front end right here that is name email and Avatar and we're going to extract that or destructure that from reg.body then we need to check if a user exists in the database by saying const user exists is equal to a weight user dot find one and then we want to find it by email if a user exists then we can simply return res dot status of 200 and then we're going to return a Json of user exists this is going to contain the entire data for our user else if a user doesn't exist we can say const new user is equal to a weight user dot create we're going to pass in an object containing a name an email and an avatar and finally we can also return res dot status 200 dot Json where we want to return a new user like this great and we can wrap all of this in a try and catch block because sometimes something might not go right so we can wrap it in a try and catch block but all the code we had so far inside of the try like so and then in the catch we can return an error that can be res that status of 500 dot Json where the message is equal to let's do error Dot message great and with that said we have create user functionality so to show you how it works we can now sign in which would not only sign us in locally in the browser but also within the database so let's sign in you're going to get a Google sign-in form like this and we are in but what matters the most is to go to database to go to your cluster 0 and then to go to collections inside of collections we should be able to see our users but right now we cannot seem to see them so let's go to the console and we can see an error it says right here event emitter memory League detected 11 exit listeners added to bus interesting so it seems like our app crashed let me try to reload it and let me try to rerun it again npm start okay so this error is not related to the login it happens immediately once we do this and it seems to be in the user.routs.js so we simply wrongly imported it at least it looks like so let's go to server index.js that is right here and it's routes here what I told you I made a mistake that I was trying to warn you about you have to add a DOT JS extension at the end so if we fix this and rerun it one more time it crashes again okay let's see cannot find controller properly looks like I misspelled that again so that's going to be in the routes file let's go here and we want to do property okay so again I want to leave this errors in to show you that typos happen and we are back and running now we can go back to our application we can log out and we can sign in one more time which should create a user in our database there's the form right here I'm gonna sign in and we are in nothing happened on the back end which should make me assume that now if we go right here and refresh we can see properties zero but users is still zero which means that our user wasn't created so let's see what it was about now we're gonna recheck everything so let's start from scratch we have a user route to create a user which is a post route on forward slash and we can look that right here API V1 users there we are calling this specific post route to create a user then that right here executes and we should send back a status of 200 so maybe going back to our app and opening a console right here we should be able to see what happened so we have a couple of Errors right here but what we can do is go to the network Tab and just try to repeat that same procedure one more time to see what happens so let's go here let's reload oh of course it's not going to work our app is actually not running believe it or not I closed it when I opened up our backend application but refine is so good that apparently it even has some offline functionalities so we were able to go through everything even when we were offline that's cool so what we're going to do is I'm going to start a new terminal put it at the start and we're going to see D dot dot and then we can run it with npm run Dev okay this was funny our client side was offline so it couldn't actually make any requests to the backhand but now we're gonna be back and running our server is running our client will be running soon and then we'll be able to try it out one more time to create a user in a database I'm going to close all of the currently open tabs besides our localhost and besides our mongodb Atlas database and there we go we're back right here I'm going to open up the terminal and I'm going to click sign in with Google that just opened up this window and I'm gonna sign in there we go if we go back right here and refresh we can see our user with a name email Avatar and all properties which is currently an empty array wonderful this works now that we have the user we are ready for that user to go right here if I zoom this out a bit go to properties go to add property and now we are ready to add the property in this user's account so to do that we can go all the way to the back end part controllers property controller and then create property this is going to be the next controller we'll focus on creating a property will be a lot like creating a user we first have to destructure the properties we're sending from the front end and these are the title description we're gonna also have a property type right we're going to have a location a price a photo and an email and all of that is equal to rec.body that's how the front end and the back end speak then we're going to do something really interesting we're going to start a new session now what is a session con session is equal to a weight Mongoose dot start session Mongoose has special sessions and these sessions ensure that what happens in this create property function is atomic meaning the entire creation of a property is going to be considered an atomic Transaction what does it mean it can either work or it cannot work but we cannot get stuck somewhere in between and this is what helps to ensure that so once we start the session we have to also session dot start transaction and again this ensures that we go through all the way now that we have that put in place we first have to get the user by email by saying const user is equal to a weight user dot find one by email and then we also can do that session and pass in the session we can make a check if no user then we can throw new error user not found if there is a user we have to get their photo and upload it to cloudinery so we can say const photo URL is equal to and now we're diving into the logic of using cloudinery so we of course first have to set it up so let me show you how to set up cloudinery first go to cloudinary.com the most powerful media API and products and then click get started there you can sign up with Google or with GitHub and once you sign up you should see a page that looks like this a dashboard there we have a cloud name an API key and an API secret we also have an API environment variable all of these are right here so let me show you how to collect these and save them we're going to need a cloudinary cloud name so you can copy it go to our DOT EnV and right here let's add cloudinery underscore Cloud underscore name is equal to this key right here we can copy the API key as well that's going to be cloudinary underscore API underscore key equal to this and finally we're going to have a cloudinary underscore API underscore secret and now we can simply get the secret as well great so now we have all of these variables and we can utilize them when setting up our new instance of cloudinery that's going to be at the top of our property controller so right here at the top we can import everything as dot EnV IR from dot EnV which is going to allow us to use environment variables and we can also import V2 as cloudinary coming from cloudinary then we can set up our DOT env.config call it as a function and below that we can call cloudinery.config and we can pass in all the necessary Keys such as Cloud name equal to process.env dot cloudinery underscore Cloud underscore name we also need to provide the API underscore key equal to process.env.cloudinary underscore API underscore key and we also need to provide an API secret equal to process.env.cloudinery underscore API underscore secret and with that we have everything we need to move down and get that photo URL of the photo we just uploaded to cloudinery and to do that you simply need to await cloudinary dot uploader dot upload and then you simply pass a photo it is as easy as it can be and finally we have to create a new property by saying const new property is equal to a weight property dot create remember we're referring to the property model and then we can pass an object in that's going to have a title a description a property type a location a price it's going to have a photo as well which is going to be photo URL dot URL and finally it's going to have a Creator which is going to be a user dot underscore ID this is where we're making a connection between a user and a property finally we also need to update the user so we can say user dot all properties dot push and we want to push the new property dot underscore ID to make sure that they are connected finally we want to await user.save to save this new session that will be opened and then we want to await session dot commit transaction meaning we are done with this transaction and we are ready to move on finally we can rest that status of 200 dot Json and we can send a message property created successfully what we can do as well is wrap this entire thing with a try and catch block so at the start we can open up a new try and catch block take this entire code and put it inside of the try right here and then we can finally do the same thing for the catch by same thing I mean just returning an error press that status all 500 dot Json and then we can simply pass the message as error.message and that is it we successfully created the controller or the logic for creating a property now going back to client source pages and then create property we have our on finish to which we're passing data and then refine by refine I mean the refines use form and handle submit functions are going to do the rest of the work for us so let's go ahead and give it a shot I'm going to collapse this right here and let's try to create a new property let's give it a name of something like Star Sun Hotel and apartment let's write something of lorem ipsum dot dot dot let's make it an apartment and give it a price of 500. and let's enter location something like San Francisco finally let's upload a photo and by the way if you want to get some great photos you can go to the figma design go to property and then right here you can get any one of these images by simply selecting that image clicking it a few times and then going to export and then you can do 3x to have a better quality with that said I'm going to go with this one right here add an m to lorem ipsum and submit now as you can see nothing really happened and I think I know the reason why we inside of the form have a submit button that's the thing that triggers everything and that is our custom button with a type of submit but if we dive into that custom button you can notice that we're never ever checking for the type and this button is simply calling the handle click so what we can do is we can pass a type to this button and type is going to be equal to if type is triple equal to submit then we're going to render submit like this so first we have to do a check and then once we check we can do submit or we can do simply button great now the error is gone and we can try resubmitting this one more time before we do that let's open up our Terminals and let's also open up the console so we can see if there are any errors if they appear so right here I'm going to Simply close the net Network and everything let's go ahead and put this on the right side and if we submit we get a 404 and that 404 right here says that we're trying to make a request to some kind of a API fake rest refine.dev properties but that's not what we want to go for we have worked hard on creating our own backend API so there's a simple fix to that let's go to our app.tsx and then on line 129 you'll see this data provider inside of the refine component there we have to specify the root of our API so let's do HTTP Colin forward slash forward slash localhost 8080 forward slash API forward slash V1 let's save that and let's clear our Network and let's resubmit it one more time and we got 200 successfully created that's great now at this point we cannot really see our properties because we haven't yet created the cards for them but as you can see property created successfully we just have to create the card to display that property so let's collapse this right here we're going to expand our code editor just a bit right here and we're going to close all of the currently open files open the file explorer and go all the way to client source pages all properties and right here below our custom button and the typography we have to render or map over all of our properties and then we can create a property card so this is getting excited with that said let's proceed with fetching all of the posts and displaying them in the all properties section below the stack containing our custom button we can create a box and this box is going to have an empty or margin top of 20 pixels it's going to have an SX property for Styles that's going to have a display equal to flex and it's also going to have a flex wrap equal to wrap finally it's going to have a gap of three with that we should be able to Loop over all of our properties now if we look into our code we don't seem to have the properties yet but let me show you how simple it is to get them using refine remember that use list hook we import 4 well instead of that we'll be using use table hook this Hook is much more powerful and will allow us to do pagination filtering and sorting all in one hook let me show you how we can initialize it just below the navigate we can say const and then we can destructure something from or rather is equal to use table and what will be the structure well we can destructure the table query result which is going to contain the beta that is loading as well as the is error props these will just allow us to more easily handle and represent the data that we're getting right here now this data should be populated with all of our properties that we have created but for that to happen we have to create a new get all properties inside of the property controller page so let's go there this one is going to be pretty straightforward we just have to create a try and catch block instead of try we can say Khan's properties is equal to a weight property dot find pass in an empty object because we want to find all of them and then dot limit Rec dot query dot underscore end so we want to Simply limit it to however many there are and then we can send the press that status of 200 and then that Json properties that's it that's all that we need to get all the properties and then we can also send an error which we can copy here below res that status 500 that Json message his error message great and now we can conserlock the data to see what we have in there so let's collapse this just a bit and let's expand our browser as well go away from the mobile mode Let's expand it and go to the console now if we reload the page on the localhost 3004 slash properties you can see that we have data containing an array of one single element which is our star Sun Hotel and apartment that we created in San Francisco and you might be wondering how is this even working well since in the app.tsx we have created our base root route of our API API V1 on localhost 8080 and now we are inside of all properties meaning list right here the use table Hook is so smart that it's going to read the URL automatically and it's going to know that we want to get the data for the properties resource and that's exactly what we get this is why I love refine now let's make use of those properties you can notice that data is actually within one more object called beta so to get that data or to get old properties we can say const old properties is equal to data question mark dot data and then we can say question mark question mark array this is going to ensure that if we don't have the data it's going to default to an empty array so we don't have any errors and then below that we can utilize the is loading and is error states by saying if is loading we can return a typography of loading dot dot and then else if is error we can return the error right here and most importantly we can map over all of our properties right here at the bottom by saying all properties that map we're going to get each individual property and then we want to return something instantly meaning we're going to have this instant return parenthesis right there and I think we're missing just one here now what do we want to return for each property well it's going to be a property card a self-closing custom component we have created and to it we have to pass a key to make it unique it's not going to be ID but rather underscore ID then we also have to give it an ID which is going to be property dot underscore ID we can also pass it a title equal to property dot title we can pass it a price equal to property.price location equal to property.location and then we're going to do photo equal to property dot photo and finally a title equal to property dot title these are all the props we have to pass to a property card and as you can see typescript is complaining again and that's for a reason that's because we didn't Define these properties on the property card but also we have a duplicate title property which I can remove so let's go into the property card and let's start setting up all of the Imports and props so the typescript doesn't complain we can import something called a place coming from add mui forward slash icons material this is simply an icon we can also import a link coming from add pan card forward slash refine Dash react router V6 and we can also import a couple of material UI properties import typography let's do a box a card a card media for the image a card content for the content and a stack coming from add pancod refine mui and finally we have to import property card props from interfaces property then we can accept all of these properties right here by destructuring the ID the title the location the price and the photo and we can say we are expecting these props to be off type property card props and now we can dive into creating a property card as you can see right now we have only one property so let's make it happen to get started with the layout of our property card we can wrap it in what it is and that is a card material UI has a special card element which is going to make the styling of our application much simpler there we're going to provide it a component equal to link meaning once we click on this card it's going to link us to the property details of that property where is it going to link us to well that's going to be forward slash properties forward slash and then ID of that property then we can do some light styling like giving it a Max width right here of something like let's do 330 pixels we can also give it some padding like 10 pixels and then on Hover meaning we have to put it in a string and put an end sign there column hover we want to give it a box Shadow now this box Shadow accepts many properties so we can do 0 22 pixels 45 pixels 2 pixels RGB a 176 176 176 0.1 I found these values to work the best so let's do it like this and finally we can also give it a cursor of pointer meaning we can click on it great and we can also give it an elevation equal to zero meaning we don't want any additional Shadow on top of it now if we save this we might not be able to see anything oh we just see a little card right here that's because we are yet to add the card media so card media is going to show us our beautiful property that we have entered before we can set it as a component meaning IMG we can give it a width of 100 percent we can give it a height of 210. we can give it an image equal to a photo that we're passing through props we can give it an ALT tag equal to let's do card image and let's also do an SX property of Border radius of 10 pixels now if we save this you can see our beautiful property image right here that we used when creating this property now let's go for card content just below card media and we can collapse this so we can see the changes that we make live we can open up a new card content element and inside of there we're going to have a stack that stack is going to be of a direction equal to column and it's going to have a gap equal to one inside of there we want to have a typography and that typography is going to render the title below that typography we're going to have a stack another one that's going to have a direction equal to row it's going to have a gap equal to 0.5 and it's also going to have an align items equal to flex Dash start and inside of there we can simply put an icon meaning that's going to be a place icon we had before we can give it an SX property equal to font size of 18. like this we can give it a color equal to hash one one one four two d and a margin top equal to 0.5 great below that place we can also render a typography where we're going to show the location like this now if we save this it should already start coming together just a bit there we go but if we go below this stack and Below another stack we can add a box and that box is going to render another typography that's going to Simply show a dollar sign and then a price like this great now we have all the content we need but let's go ahead and let's style it just a bit better so to discard content we can give one SX property of display is equal to flex that's immediately going to change some things we can also give it a flex Direction equal to rho we can give it a justify content equal to space Dash between and we can give it a gap equal to 10 pixels as well as padding x equal to 5 pixels if we save that you can see that's going to change the layout just a bit put the price on the right side now we have this typography of title so let's style it a bit let's give it a font size equal to 16 to make it just a bit bigger font weight of 500 right here and a color of your the Noid one one one four two D now if we save it it's just a bit more pronounced then we have the place which is fine and then this bottom typography we can give it a font size equal to 14. and a color equal to Hash 808191 that's for the location there we go finally we can style the Box this box is going to have a px of 1.5 that's for padding horizontal we can also give it a py of 0.5 for padding vertical and a border radius of one like this we can also give it a BG cooler equal to Hash d a d e f a and also we can give it a height equal to fit Dash content if we save that you can see this price box appear and we can style the typography right here by giving it a font size equal to 12. font weight equal to 600 as well as a color equal to Hash four seven five b E8 if we save that you can see it looks just a bit better but still it's not as close as to what I showed you at the start all of these seem to have this bottom border which indicates it's a link so we have to get rid of that and of course to get rid of that we can go to our card and add one more property of text decoration is going to be set to none so if we do this you can see it disappears and we have a wonderful property card now let's go ahead and add one more so let's go to add property let's go with lavender apartment let's do test property type is going to be a villa let's do 1000 right here enter a location let's do Italy and I'm gonna upload a photo with that I'm gonna click submit and immediately we are redirected right here and it is immediately showing we even get a success message that is great so we have successfully completed two out of four crowd operations create and read now of course there's also delete and the update and hey we still have to show the details for a specific property as you can see we immediately route to it and we can go back to dashboard but already I think you can see how great this app is becoming now we're just gonna focus on adding the delete update and also show the property detail now as an extra added bonus I wanted to show you how simple it is to do pagination sorting and filtering all using refine what you can do right here is we can utilize the use table hook to its full potential from you stable below table query result we can also get current meaning the current page Set current which is going to allow us to set the page we can get the set page size which is going to allow us to change the number of elements on the page we can get the total page count and finally incredibly handy utilities such as sorter set sorter for sorting as well as filters and set filters for filtering so let me show you how to use all of those on top of our old properties so right here inside of the Box we're going to make some space and we're going to create another box this box is going to have an empty of 20 pixels to divide it from the top it's going to have an SX property of display is set to flex as well as Flex wrap is set to wrap and finally Gap is set to 3. inside of there we can have a stack and that stack is going to have a direction set to column as well as a width set to 100 percent inside of there we can move this typography that before we head down here so let's move this typography it's going to say all properties but what we can also do is we can make it Dynamic so let's say open a new Dynamic block if no all properties dot length then we can show a dynamic string of their there are no properties otherwise we can show a string off all properties there we go so now we can remove the static one right here now immediately below that typography still inside of the stack we want to create a new box this box is going to have an MB of 2 meaning margin bottom it's going to have an Mt of 3 meaning margin top a display of flex a width of about 84 percent this is where our filters and sorting will go we can also do justify content equal to space Dash between and finally a flex wrap equal to wrap now if we save this nothing really should happen we just created some space for adding our filters now we're going to create one more inner box that box is going to have a display is equal to flex a gap equal to two a flex wrap equal to wrap and a margin bottom that's going to be on extra small devices 20 pixels and on small devices and higher it's going to be zero and finally inside of there we can render our custom button our custom button is going to be used for sorting so we can give it a title that's going to be dynamic sort price like this and for now we can leave this as it is later on we'll be able to sort it better we also have to give it a handle click so let's set a handle click and for now we can leave it as an empty callback function we're also going to set a background color equal to 475 be8 and then also a color equal to fcfc FC and there we have our sort price button that's great so this is going to be used for sorting just below that button we can have a text field this text field is a self-closing material UI tag and of course we need to import it at the top so scrolling all the way there we can import the text field later on we're going to also use a select element as well as a menu item element so we can import the menu item as well finally we can scroll down and this text field is going to have a variant equal to outlined a color equal to info a placeholder equal to search by title now if we save this you should be able to see an outlined text field appear and there we go we're going to use this for filtering by title for now we can add the value equal to just an empty string and we can also add an on change equal to an empty callback function because we're going to fill this soon enough for now we're just focusing on the layout now below that text field we're going to have a select element this select element is going to have a variant equal to outlined a color equal to info a display empty property it's also going to have a required property it's going to have an input props of area label without label written like this also a default value set to an empty string for now the value can be set to an empty string as well and the on change is also going to be set to an empty callback function looking like this now you can see our select but it's looking a bit empty without any menu items so for now let's simply add a demo menu item that's going to have a value of an empty string and inside of it we can say all so we want to see properties of all types and there we go we immediately created the layout for three different things for sorting for filtering and some more filtering as well based on the type now that's happening at the top of the page but now I promise that we're gonna do pagination as well so below our property items meaning that is right here below this stack containing the property cards and below that box right here we're going to create our pagination we first have to check if there are any properties left to paginate so we can do all properties dot length is greater than zero and end and then we can show R by generation the pagination is actually going to be just a box for the start so that box can have a display is equal to flex and it can have a gap equal to two gap between the buttons that we are yet to create and then we can have a margin top of three to divide it from the properties above and flex wrap set to wrap great now inside of there we can start with our custom button this button is going to have a title equal to previous so this is going to move us to the previous page we can also give it a handle click and there we can set current remember that utility function that we got from the use table Set current and whenever you're setting the state with the previous version of that state you want to create a callback function called prev and then we can say prev minus one we're simply decreasing one from the number of pages then we can set the background color to be equal to Hash 475 be8 as well as a caller equal to FC fcfc and finally we need to disable the button if we are on the first page so we can say disabled is equal to no current is greater than one so if this is the case then we cannot go back so now if we save this you can see that we have a previous button now even though we are on the first page the button doesn't seem to be disabled so let's go into the custom button and let's get disabled from props and then right here we can say disabled is equal to disabled there we go now as you can see we cannot click the button because we're on the first page great now below that custom button we can create a box this box is going to only be visible on large devices so we can give it a display equal to on extra small devices hidden and then on small and larger it's going to be Flex we can also give it align items equal to Center and we can give it a gap of 5 pixels inside of there we can simply say page we can provide an empty space like this and then we can give it a strong tag to make it bolded and then inside of there we can see current like this off page count so this is going to let us know on which page are we right now and there we go you can see page one of Nan and that is fine that's because we didn't yet implement the back end for pagination to work but soon enough we'll do that so we'll be able to see one of one then below this box we can duplicate this button that we have created before and this is going to be our button to go to the next page so right here we can set current prev and it's going to be prev plus one instead of -1 the color and the background color are going to be the same but it's going to be disabled if current is triple equal to page count that means that we are on the last page and now we have previous we have next and we also have the number of pages now we're going to also do one additional functionality which is creating a select element that select element is going to have a variant equal to outlined it's going to have a color equal to info a display empty and as a matter of fact I think that we can completely copy the select that we have above so right here remember to select you can copy it all the way to the ending tag and we can paste it right here we can also fix the indentation by moving all of this a couple of lines back everything is going to be the same but the value and the on change are going to remain empty for now and of course we have to add some menu items so in this case we're going to map over some array items so let's create a dynamic block of code with an array of 10 20 30 40 and 50. and then we can say dot map all of these are page sizes so we can say size and then for each size we want to instantly return a menu item and of course we can add a key because We're looping over it as a size the value is going to be size as well and then the text is going to be show size like this this will allow us to switch between many different page sizes so later on if we have more elements and we want to see more in the same page we'll be able to show 50 on the same page and the best thing about it is that our pagination is going to immediately calculate the number of elements per page and it's going to decrease the number of pages and of course we can set the default value to be a number 10 so that it shows right here in this case the value can be removed great later on once we implement the on change we'll be able to see the changes that we make right here but with that said believe it or not we're done with the layout for our sorting filtering and pagination now we're going to dive into implementing the back end for all of these functionalities and then finally we're going to come back right here at the top of our layout and I'll show you how easy it is to implement everything using refine with that said we can now go to the back end so file explorer server controllers property controller and inside of the get all properties I'm gonna show you how to add additional logic so we can fetch all of the properties based on pagination filtering and sorting so let's get started now we have created the layout for all of these and the refine will automatically pass it back to the server so it's going to pass it of course through rec.query so right at the top we can say cons and we can destructure something from reg.query or rather is equal to reg.query the first thing is going to be underscore end we're going to have underscore order is it ascending or descending it's going to be underscore start from where are we starting from which element we're going to have an underscore sort and we're going to have title underscore like so that's going to be what the title is like used for filtering right here by title and we can set the default value for that to be equal to an empty string and finally we're going to have a property type which is also going to have a default value of an empty string if it doesn't exist great now we can also form our query so we can say const query is equal to an empty object and then only if we have property type so if property type is not equal to an empty string then we want to add our query to the query so query dot property type is equal to property type so this is ensuring that we only query or filter if we do have that query passed in and the same things goes for the if title like so if it actually exists like this then we can say query.title is equal to dollar sign regex or regex is equal to title like and then options I that means case insensitive meaning if we type it all uppercase or lowercase it's still going to find it great so now we have created a query based on which we can search for these properties so what we can do first is we can get the count of all properties that's going to be helpful with the pagination const count is equal to a weight property dot count documents like this and then we can pass in the query make sure that it is passed inside of brackets like this then we can get the properties but we will no longer simply get them by finding everything we're going to pass additional filters so let's put that in a new line dot find and we have that limit later on so let's modify the find not everything but rather we're going to pass in our query to only find elements based on the specific parameters then we're going to limit it to that's the underscore end then we want to skip a specific number of elements that is underscore start and then we want to sort things and that's going to be sorted by the parameter underscore sort and the Order of underscore order that can be ascending or descending and that's going to be this sort price right here and finally we want to refine to know the total number of elements and we're going to pass that through headers so we can say res dot header of x dash total Dash count is going to be set to count and then also rest that header of axis Dash control Dash expose Dash headers is going to be set to x dash total Dash count this will allow us to expose this header to the front end so that we know the total count of our resources and finally the only thing we have to do is res that status of 200 and pass over all of the properties that is it and now a refine is going to have all the data it needs to really easily Implement machination sorting and filtering let me show you how simple that is let's start from top to bottom and from left to right that means that our first sorting ability is going to be to sort the price to sort the price we need to know what is the current price sort so we can say const current price is equal to sorter dot find we want to find the item and then item.field is triple equal to price so that's what we're trying to get and then we want to do questionmark dot order this will give us the current order of the price property now that we have that we can create a special const toggle sort function which is going to take in a field of a type string and it's going to return set sorter like this we want to pass in an array and then an object where we pass in the field and then we pass in an order so order is going to be if the current price is currently set to ASC meaning ascending then we want to change it to descending otherwise it's going to be ascending and now we can use this current price and toggle sort on this button so let's scroll down there we go this is our first button right here sword price doesn't really say a lot so we can go to Google and we can search for Arrow up and we can copy this character right here so we can say sort price and then we can check if current price is triple equal to ascending then we can show D Arrow up otherwise we can show the arrow down you can also search for that arrow down simply right here arrow down and then you can copy it there we go now if we save this and go back you can see we have sort price down and of course we have to add the handle click and that is as easy as setting the toggle sort and then passing the price as the parameter there we go if we save that you can see right now we have 1500 and if I click five hundred one thousand of course this is not maybe as interesting as if we had like 10 or 50 elements but you can still see that sorting fully works right out of the box and this was so simple to implement using our own custom backend and refine now we're going to focus on filtering by title so we can scroll up and same as we got the current price we also need to get the current filter values so we can say cons current filter values is equal to use memo we're going to use memo just to save some memory and to make it more efficient now that use memo is only going to change once we change the filters like this and then that use memo has to be imported from react so at the top you can import use Memo from react inside of there we first need to get all of our logical filters so const logical filters is equal to filters dot flat map now flat map is a special JavaScript structure it is similar to an array but in this case refine theme recommends to use a flat map to make this more efficient now inside of here we're gonna have an item and then we want to instantly return meaning like this field in item so if that exists then we want to return an item otherwise we want to return an empty array like this and it looks like I'm missing one closing parenthesis now that we have these logical filters we can return an object where we're going to change the title logical filters dot find where we're going to get an item and then we're gonna return item.field is triple equal to title and then we can do question mark dot value or an empty string this is going to allow us to filter everything by title now we can use this current filter values inside of our text field so right here we can go to the text field the value is going to be current filter values dot title and then the on change we always get a key press down event and there we can call these set filters pass in an array and then pass in an object where the field is going to be set to title the operator is going to be set to contains so that's not going to be just the exact match we can also make it just contains which is great usually you would have to make this work manually but refine did it for us and then finally we have value now value is going to be e dot current Target dot value if that exists then we want to have the E dot current Target dot value else we want to leave it as undefined there we go and with that done our filtering should work so let's test it out we have a lavender apartment and we have a star Sun Hotel Apartment so if we start typing for apartment both of them should be here if we try with lavender you can see immediately that only Lavender is here but even if you just type L A immediately it's there and if we start typing stars and hotel immediately that works again right now you can only imagine how functional this would be if we had like 50 elements that would make it so handy for us to be able to search through it sort by price and do all of this and now we're gonna also implement the filter by property type so right now we just have all but maybe we just want to search for Villas or condos or apartments so let's Implement that right away we can scroll above to our filters and we can return right below the title property type that's going to be logical filters dot find there we have an item item.field is triple equal to property type and then question mark.value or an empty string with that we can scroll down to where we have our select and then we can essentially copy what we had right here in our search by text field so we can copy the on change as well as the value so let's go ahead and copy that and let's override the current value in the on change now we are missing one closing parenthesis right here and we're missing one more so if you properly close this that should be looking good but now there are just some minor differences we have to make current filter values dot is going to be property type and Below field is going to be property type the operator is going to be EQ meaning equals and then the value is simply going to be e dot Target dot value there we go now if we save you can see we're good but we only have one property and now right here still inside of set filters meaning right here after this array we want to say replace because we want to immediately replace the value that we click and now we just have one value so let's add additional ones we can have value of nothing equal to all but then we can create a dynamic block of code and there we can create an array web apartment then we can do Villa we can do a farmhouse let's do a condos let's do a townhouse let's do a duplex finally we can do a studio and a chalet there we go and then we can map over that by type and then for each one of these types we're going to return a menu item that menu item is going to have a key equal to type since they're all unique and the value equal to type dot to lower case that's important and then finally they're going to render the type now if we save that you should be able to see all of these appear right there and right off the bat since we implemented filtering right here at the top it should work so if we search for apartment there we go this is the apartment and if I'm not mistaken the other one was set as a villa so if you click you can see that the Villa remains for every other one there are no properties so we have apartment we have a villa and we have all again imagine how this would look if we had more properties great finally the last missing piece of the puzzle is the pagination and would you believe me if I told you that there's nothing else that we have to do to make the pagination work previous and next pages are already fully functional but are right now disabled and for a reason that's because we only have two elements and our current page is showing 10. so the last thing we have to do is we can use the set page size down below that is right here inside of this custom button instead of this custom select for that matter where we can get the event and then we can say set page size to be equal to e dot Target dot value if we have that then we want to return a number of e.target.value else we want to return 10. so with this we'll be able to set the total number of elements on the page 30 40 50. now this was just a phenomenal bonus that I decided to include in this video the pagination sorting and filtering The crucial parts of every single crud application since this was an addition to this video that wasn't initially planned you can keep it here and keep working on the application it's still gonna work for you perfectly but in future scenes of this video when I am viewing the old properties these features are not going to be here but not to worry you have them implemented and they're going to work perfectly for you when you deploy the application great with that said we can go to file explorer and then that's going to be property details to get started with property details we can first import a couple of things from Material UI such as typography a box and a stack we're already used to all of these already let's also say from add pan card forward slash refine Dash mui now we also want to get a couple of hooks coming from refine that's going to be use delete because from The Details page we're going to delete our resources the use get identity this is to determine whether the property that we're looking at is created by us or another user and then finally the use show which is going to allow us to pull all of the data for this specific property and that is coming from at pan card forward slash refine Dash core finally we can also import the use params to get the ID of a specific property as well as use navigate and this is coming from add punkod forward slash refine Dash react Dash router Dash V6 and we can also get a couple of icons so let's import a chat bubble a delete edit phone place and a star and all of that is coming from add mui forward slash icons material and we'll be also utilizing our custom button so we can say import custom button coming from components great now let's make use of all of these great hooks that we have imported that's going to be const navigate is equal to use navigate and immediately we have to rename our property details to property details with a capital p then let's try to get our current user by saying const data rename as user is equal to use get identity then we can get the ID from params this is the ID of the current resource we're trying to view then we can get const mutate is equal to use delete this function will allow us to quickly delete a resource and most importantly we can say const query result is equal to use show and we don't have to pass it anything refine is going to be smart enough to check our URL and to understand that we are on the forward slash properties show and then the ID it's going to grab it and it's immediately going to make a call to our backend to get the data for the resource we're currently looking at isn't that great now we can destructure that resource further by getting the data that is loading as well as the as error from it so that's going to be equal to query result now of course it doesn't even make sense to consulate the data because it won't be there we haven't yet created the backend endpoint to get the data about one specific resource so to get the property detail we can first get the ID of the property we're trying to get by going to rec params and then we can check if the property exists and then if it does and we can check that by trying to reach it by saying a weight property dot find one we can pass in an object checking the underscore ID if it is equal to the underscore ID we have or rather just the ID that we got from params and then we can do dot populate Creator if it is there because we want to add the Creator to it finally if it exists meaning if property exists then we can rest that status of 200 and then dot Json property exists so we're going to essentially return it back home else if it doesn't exist so we can do that right here else we can rest that status of 404 and then pass something like property not found like this of course we have to properly close this if so if we do it right here that is looking good to me now if we save that and if we go back to our front end we can now console log the data and see if we get it back let's open up inspect element go to console and reload the page and would you look at that the data object is there containing one property that we have created before and one that we're trying to fetch isn't that great now as you can see the data is inside of another object called Data so what we can do right here below is say const property details is equal to data question mark dot data or it's going to be an object like this in case it doesn't exist and then we can also utilize the is loading and is error by saying if is loading we can simply return a div that's going to say loading dot dot and we're going to do the same thing for error if is error we're going to Simply return error we don't have to have any dots in that case great let's fix the spelling and this is looking good we can close the console and now we can code the UI part which are our property details everything in this application and in life is a box so let's create a box right here and then we can have a border radius is equal to 15 pixels we want to make this box really nice and round let's see how that looks like it shouldn't be anything at the start of course then we're going to add a padding of 20 pixels as well as a BG color equal to Hash fcfc FC and we can add a width equal to fit Dash content and immediately we get this card inside of that card we're gonna have a typography this typography right here is going to say of course details we can style it just a bit by giving it a font size equal to 25 and a font weight of 700. finally a color of hash 11142d and we can save that below our typography we can have a box and that box is going to have an empty or margin top of 20 pixels a display equal to flex and a flex Direction which is going to be a bit more complicated on extra small devices it's going to be a column and then on large devices and larger it's going to be a row and we can give it a gap equal to 4. great the column of course is supposed to be inside of quotes now inside of that box we're gonna have a couple of other boxes so right here we can create a new box and within that box we're going to have an image so we can render a self-closing image tag that's going to have a source equal to property details dot photo and we can try to save it as you can see we get this beautiful Apartment image right here now to this box we can give it a flex equal to one as well as Max width of 764. I found this value to work best that's going to contain the image just a bit we can give it an ALT tag equal to property details dot title a height equal to 546 I found to work the best and then a style equal to object fit which is going to be set to cover as well as a border radius set to 10 pixels like this if we save that it's going to become just a bit more rounded and we can give it a class name equal to property underscore details Dash IMG this is a special property or a class that was provided to you at the start of the video but as you can see it's not really getting applied and that just made me think remember when we had to add that special not underlined property right here that was in the property card right there we had to add this special text decoration none we can remove that the reason for that was looks like our styles are now getting applied not here and also not here so inside of our app.tsx if we go here I think that I imported the index.css Styles but I might be wrong yep they're not here so let's go to our index.tsx and inside of here we have to just add one line and that is import index.css this is going to add a few of those styles that we had at the beginning that I provide you with so if we look into here there we go and as you can see that already made it just a bit better and if you go here that image is just styled in a better way so now those styles are being applied and we can continue with our life we're gonna go back to property details in that box and then below that image we're gonna have yet another box believe it or not this box is going to have a margin top or empty equal to 15 pixels and inside of there we're gonna have a stack that stack is going to contain a typography and that typography is going to render the property details dot property type there we go so if we save it you should be able to see that this is an apartment now of course let's style it just a bit now below the property type let's also create a box and that box is going to render something dynamically an array of 1 2 3 4 5 elements through which we're going to map over do you know what this is well these are stars so for now we're going to just say that every single object has five stars and later on if you want to add a star ability of the ability to add stars to each object you can do that dynamically that's a challenge for you and of course we can add a key equal to a template string of star Dash and Then star like this and we can give it an SX equal to cooler is hash F2 c94c and now if we save this you should be able to see five stars appear right here great now let's style this stack above our typography by giving it a direction equal to rho this is going to make the stars appear next to the apartment let's also give it a justify content equal to space between which is going to make the stars go to the right side let's give it a flex wrap equal to wrap and align items equal to Center great to this typography we can apply the font size equal to 18 a font weight equal to 500 and a color equal to hash 11142d and finally text transform equal to capitalize now if we save that it's looking just a bit better great now we can go below this stack containing this box and we can create another stack below this stack is going to contain absolutely everything almost the same as the stack above so we can simply copy this entire stack and replace our new one of course it's not going to be property type anymore this time it is going to be property title there we go and then we're not gonna go over the Stars we want to show the property location so right here we're not going to have this box but rather immediately below the typography we're going to have a place which is a self-flowsing icon equal to SX and we're going to give it a color of eight zero eight one nine one and just below that we're gonna have another typography which is going to render the property details dot location there we go so if we save this you can see apartment and you can see location and La USA right here but of course we have to style it a bit so let's first focus on this big title that title of course has to be bigger than the type of the apartment so we're going to give it a font size of 22 and font weight of 600. the caller can remain the same there we go that's just a bit better now regarding the place and the typography we can wrap them in a stack so let's create a stack right here let's give it a margin top of 0.5 let's give it a direction equal to rho align items equal to Center and let's give it a gap equal to 0.5 and now we can place those place and typography inside of that stack that should make it look just a bit better and closer together and now we can style this last typography by giving it a font size of 14 and giving it a color equal to hash eight zero eight one nine one there we go so this is looking just a bit better finally we have more details about this entire apartment it's going to be the price of course So Below this stack we can have another box right here and I just noticed this typography should be wrapped together with this stack within another box so I know this is getting a bit confusing but here we have the typography with the title and we want to wrap that with a box element and that box element can be closed right after our stack right here so now if we save that you're going to notice that now the location appears right here which is a bit better and then a new box begins now since the rest of this property Details page is just taking the elements and then laying them one on top of another you can do that on your own way you can do it a bit differently from the design you can have your own style for that reason you can pause this video right now and implement the rest of the details coming from the property details component you can simply console log it see what's in there and then somehow showcase them on the screen in case you want to follow along I'm going to leave the rest of the code for the property details down in the description below it's going to be in that same GitHub gist so you can simply override our current code and we're gonna get the rest of our property Details page which is going to look something like this it's going to contain the price which you can see right here a description and then a card with the current agent that created that property with buttons to edit it and delete it another thing right here that is currently static is the photo of a map but if you really want to you could take the geographic location of this place and then embed a real Google map right here if you want to add on to this project this would be a great thing to do but with that said if we now expand this you can see how great our property Details page looks like and how simple it was to make using refine now there is one piece of logic that we imported with the code right here and that is right here checking if the current user is the one that's currently looking at this property so if we are a currently logged in user then we can see the edit and delete buttons and if we are not which we can mock right here here just for a second then we can see this dummy message and call buttons but in this case we of course are so we can get back the edit and delete another thing of course is the deletion so right here we have the handle delete property where we are checking whether we want to do that and then if we do we're simply using the mutate and then we are referring to the resource under properties with a specific ID and then on success we're navigating back to properties great but of course the backhand side for the deletion of a property hasn't yet been implemented so let's go to property controller to delete a property we can create a new try and catch block inside of the try we need to get the ID of the property we want to create and that's going to be const ID which we destructure from rack params then we want to get that property so const property to delete is equal to a weight property dot find by ID and then we find it where we say underscore ID is equal to ID and then we populate the Creator the reason why we just deleted immediately is because we also need to delete its ID from the Creator the person that created it so what we can do is we can check if there is no property to delete then we can throw a new error property not found else we can create a new session by saying con session is equal to await Mongoose dot start session and then of course we have to start the transaction as well to make everything Atomic to make sure that it either goes through or it doesn't stack in the middle now we can say property to delete and then simply say remove and remove it from this session then we also do property to delete that Creator dot all properties dot pool and then property to delete like this finally we have to await property to delete dot creator dot save and then we pass in that session and finally we do a weight session dot commit transaction meaning everywhere what we did remove the property remove the Creator from the property remove the property from the Creator we now want to commit to everything we said we would do and finally we can say res that status of 200.json and then we're going to send a message property deleted successfully there we go that should be good to go and we can also in the catch send the 500 with a message saying error Dot message great with that said we can go back and this should now be working because refine makes it so easy we simply need to call this one function and pass the ID so let's click delete function and hopefully it works we get an alert asking us if we are sure yes we are and there we go success it was immediate it was incredibly fast great now while there is one property left to work with we can implement the edit functionality as well so that's going to be in that same controller right here in the update property controller function so let's go ahead and implement it right away as when deleting or fetching a specific property when updating it we also need to know which property are we updating so let's open up a new try and catch block and let's get const and then we need to get the ID from direct params so that we know which one are we updating but for the update we also have to get all of the properties from the front end const title description property type and location price and the photo as well from the front end so this is the part that we didn't yet do on the front end if we click on the edit you can see that it is a 404 it doesn't exist so we have to go not to the property detail but rather 2D property edit edit property there we have to implement the form to send all of the updated fields from the front end to the back end but don't worry that's going to be much simpler than you might think because we're going to use the same form component that we used in the create if remember right here this is going to be the add property and we can copy most of these functions to create our edit property as well so let's go here and let's go to edit and start with the edit property page in the GitHub just down below you can find the entire edit property.tsx file and simply paste it right here as you can see this is the exact same thing as we had inside as you can see this is exactly the same form we had inside of the create property you can see that right here as a matter of fact the create property also had on finish Handler it had a handle image change and it had some of these props and if you look at the edit property on finish Handler it has the handle image change and some props right here as well it is mostly the same so I simply wanted to provide it to you because you have already done all the great work of creating the form component and now we can simply reuse it for the edit property and now if we go to properties we click on a specific property and click edit as you can see here we are we immediately have all of the values pre-filled lavender apartment test we can select a property type such as apartment enter the property price and the location and we can re-upload the image and of course the best thing about this is the use form hook which automatically gives us all the data that we can pre-fill in all of these inputs with that said now we can go back to the controller and we know that we're accepting all these properties the property name description type price location and so on and let's try to make sure that there aren't any typos so that's going to be description great so now that we have all of these properties how do we actually edit it well we're going to do it like this we're going to do a weight property dot find by ID and update and there that's going to be underscore ID is equal to ID we're going to find it and then we need to pass all of the updated properties such as title description property type location price and then finally the photo but we have to re-upload that photo to cloudinery so we can say const photo URL is equal to a weight cloudinery dot uploader dot upload and then we pass that photo great and now we can right here say photo is equal to photo URL dot URL or we can use the same old photo if the old one wasn't provided great finally we can do res dot status of 200 and then say property updated successfully or we can do res dot status of 500 and say there is an error great that is the controller for the update property now let's go ahead and try to change the property description from test to something more interesting and for that let's use chat GPT so let's say that we have a lavender apartment which is a villa in Italy so let's do create a comprehensive description for lavender apartment or let's do lavender Villa in Italy and let's see what is it going to come up with luxurious vacation rental located in the Rolling Hills of Tuscany Italy this is crazy it keeps typing but I'm just gonna get this one that's the new lorem ipsum you're always going to have some great content to submit and we can also resubmit the photo after adding it you can submit and there we go you can see the value changed immediately I can notice that I uploaded a really grainy image so I can go back and I can really quickly re-upload a better image let's see if that works and it does so that means that our update or edit functionality is done delete is done as well the dashboard is done as well and what we can do is we can Now list out all of the agents and that is available on our pages on top there we go pages and then we have agent profile but we also have agent that is it to get started with the agents page we can first import the famous use list that is coming from at pan card forward slash refine core this is going to allow us to quickly fetch a list of users and we can also import our very known box and typography coming from add punkod forward slash refine mui and we can also import a special component called Agent card coming from components great inside of the agent we can rename that to agents with a capital a there we go and we can make use of that list by saying const beta is loading and is error and then we can use the list and then pass the resource we want to get in this case it's going to be users hopefully you're starting to get the point of how refine works you have a lot of different resources that correspond to resources on the back end and to the models on the back end and in the database and you can simply use the list to fetch them right here and you get the hooks for loading errors and finally the data so one more time to get the agents we can say const all agents is equal to data question mark dot data they are stored right inside of here but of course we have to implement that API endpoint and that's not going to be in the controller for properties but rather for users we have only implemented the create user but we are yet to implement the get all users endpoint and that's exactly what we're gonna do right now that one is the simplest one we can simply create a try and catch block if something doesn't go right we can rest that status of 500 and we can simply send the error message like so but if everything goes right we can see const users is equal to a weight user dot find we get all users right here and then we can pass a limit of reg dot query dot underscore end if there is a specific end in this case we don't want to end it and finally we can say rest that status of 200 and we can do that Json users to bring them back to the front end now inside of here we can for now let's simply alert all agents and see what do we get and there we go object object which means something is there maybe we can do all agents and then zero that's again going to give us an object object I'm guessing but agents have their name right so we can do dot name or rather email I'm sure they have an email but this time typescript saves us and says all agents is possibly undefined so we can use that same syntax and make it into an array to ensure that we always have access to it great thank you typescript for saving us right here now we do have an error we cannot seem to alert this but no worries we can simply do a quick console log to check all agents so let's go ahead and go to inspect console and we do get an array of one user and it did indeed have an email great so finally we can showcase those users we can of course before add the if is loading we can return loading and if there's an error we can return the error and now we can create the layout to show all of our agents we can do that by creating a box and then within that box we're going to have a typography and that typography is going to have a font size equal to 25 and font weight equal to 700. it's also going to have a color equal to hash 11142d and it's going to say agents list there we go that should be looking good and immediately below that we can have a box that box is going to have a couple of properties such as Mt 20 pixels for margin top and it's going to have an SX property with some additional Styles such as display in this case going to be Flex it's also going to have a flexor wrap of wrap a gap equal to 20 pixels and finally a background color equal to Hash fcfc FC there we go now if we save this we should be able to see that box appear right here so we can fill it up with something and that something is going to be a dynamic list of all agents dot map and then we get each individual agent and for each agent we want to return an agent card a self-closing card component with that we should be able to see one card right here and that's exactly what we get finally we can pass some props to it we can pass a key equal to agent dot underscore ID we can also pass an ID equal to agent dot underscore ID we can pass a name equal to agent.name we can pass an email equal to agent dot email we can pass an avatar or an image equal to agent dot Avatar and we can pass a number of properties and O of properties is equal to agent dot all properties dot length there we go finally we can control click into the agent card and implement it right now tabscript is going to give us some errors but that is just fine as you already know it's giving us errors because of the props we're passing in so we can first get those props such as ID name email Avatar and an O of properties number of properties and we can set that to be of a type which we can import so we're going to import two types that's going to be agent card prop as well as info bar props which we're going to use later on coming from interfaces forward slash agent and now we can say our properties of agent card are equal to agent card prop if we save that the error goes away great now we can import all of the other things we're going to need for our agent card we can import a few icons such as email outlined location City phone and a place coming from add mui forward slash icons material we can also import the use get identity that is a hook coming from refine core allowing us to get our currently logged in user then we can also import a couple of components from Material UI such as box and typography coming from I had Punk card forward slash refine Dash mui and we'll also need to redirect to that user's profile page so we're going to have a link component coming from at pan card forward slash refine dash react-router dash V6 great and with that we have everything we need to start creating our agent card first we're going to get our current user by saying Khan's data rename it as current user is equal to use get identity it's so easy to get the current logged in user with refine then we can start with creating that user card let's collapse this just a bit so we can see it right here and let's get started we're going to have a box and that box is going to have a couple of properties first of all it's going to be of a component link because once we click it we want to link to somewhere we want to link to the user profile of that specific agent so we can say it's going to go to and we can create the logic of where is it going to go in a special function called const generate link which is going to be a single react function there we can check if current user dot email is triple equal to the email of that specific user then we can return my profile so then we want to go to my Dash profile else we can simply return go to forward slash agent forward slash show forward slash and then ID inside of dollar sign and curly braces and now we can use that generate link right here and we call it as a function that's where we want to navigate to once again if it's another agent then we want to go to their agent profile else if it's us we want to go to our profile page then the next property is going to be with this card is going to have a width of 100 percent and then we want to have an SX property so right here we can say s x we can give it a display equal to flex we can give it a flex Direction equal to on extra small devices it's going to be column and usually on small it's going to be row we're going to also give it a gap of 20 pixels so we can have some space between the elements we're going to give it a padding of 20 pixels and this should already look much better if you look into it there we go and we also want to give it some box Shadow on Hover so we can say inside of a string and column hover in that case we want to give it a box shadow of a string 0 22 pixels 45 pixels 2 pixels and then rgba 176 176 176 and then 0.1 we already had this before so now if we hover over it you should see this Shadow appear great and of course what is an agent without an image so inside of that box we're now going to render a self-closing image tag this image is going to have a source equal to Avatar it's going to have an ALT tag equal to user it's going to have a width of 90 pixels just 90 and a height equal to 90 as well finally we can give it a style equal to border radius of 8 as well as object fit equal to cover and we can close it and there we go the image just appeared below our image we're going to have a stack element that stack is going to have a direction equal to column we want to show some elements one on top of another we're going to also have a justify content equal to space Dash between we're going to give it a flex of one and a gap on extra small devices meaning XS equal to four and on small devices equal to two and we're going to create another stack within it that stack is going to have a gap of two it's going to have a direction of rho so this is going to be for two elements that are going to appear next to each other it's going to have a flex wrap equal to wrap in case the width of the browser shrinks a lot and then we're going to have an align items off center inside of there we want to have two different typographies the first typography is going to render the name of that agent and the second typography just below is going to say what they really are and they are a real estate agent so I guess guys I'm changing the careers GSM is now a real estate agent we can now give it a font size of course the name itself must be larger than the title give it a font weight as well of 600 and give it a color as well of hash1142d and to this real estate agent we can also give some class names or Styles such as changing the font size to 14. changing the color to hash 808191 this is already looking so much better now if we go below this stack we're going to create a new stack just below that stack is going to have a direction equal to row it's going to have a flex wrap equal to wrap a justify content equal to space Dash between and align items equal to Center as well as Gap equal to 2. inside of there we're gonna show four different elements we want to show the phone number the email the place and the location so let's create a new component to do that just at the top above our agent card we can create a new quick functional component const info bar our info bar is going to accept an icon and a name as props and we can say these are of a type info bar props and it's going to instantly return something meaning we just have the parentheses right here so what are we going to return it's just going to be another stack element and that stack is going to render an icon and below that icon we want to render a typography right here that typography is going to render the name so now if we save nothing's going to happen because we're not yet utilizing this info bar but if we go down inside of this stack we can now render this bar as a matter of fact we can render it four different times info bar and we need to pass an icon and a name to it so let's expand it a bit let's pass an icon equal to an email outlined with an SX equal to color of 808191 like this and we can also pass a name which is going to be email now it looks like we didn't import this email outlined so let's go up it looks like it's here but why is it complaining let's check it out module build failed we have an icon and it looks like we have one extra closing bracket right here so if I delete that nope I think we needed that let's see why is it giving us an error on extra small device this is supposed to be SX prop not extra small so if we fix this oh yes we have to close the actual email outline it is a self-closing tag there we go that's much better now we can duplicate this three more times for the second one we're going to change the email outlined to place like this for the third one we're gonna change it to phone for the fourth one we're going to change it to location City there we go we of course have to change the name as well so the name is going to be let's do something like static string of London let's say this agent is from London and for the third one we have to add a phone number we don't yet have that so let's add some random numbers as the phone number let's do this there we go and the last one is going to be the number of properties so here we can render a real template string of number of properties properties like so there we go if we now save this and of course we have to correct our template string there we go we now have four different icons and titles appear right here but of course let's style them just a bit by styling our individual info bar stack hopefully now to get the point of why we created this individual card why we created this individual component because we are reusing it four different times and it's easier to just re-edit it once then re-editing it four times this typography can have a font size equal to 14. and a cooler equal to Hash eight zero eight one nine one that's going to make it just a bit better and let's also change the stack by giving it a flex equal to one let's give it a Min width equal to that's going to be on extra small devices 100 percent and on small devices 300 let's give it a gap equal to 1.5 and a direction equal to rho this should make it look so much better okay this is good as you can see on smaller devices they go one below another but if we expand this is the flex wrap property in action as you can see we've wrapped them in a flex wrap meaning if we run smaller it's going to be one line but as we expand they're going to nicely wrap all around which is great and there we go there is our first and only agent right now what we can do now is I can log out right here and then log in with another account I'll choose GSM masterclass experience this is a new email account we created to post testimonials of students that complete our comprehensive GSM masterclass bootcamp if you're interested in checking that out you can just YouTube JSM masterclass experience with that said I'm going to log in and then go to agents and there we go we have Adrian and we have JavaScript Mastery we can see the number of properties and we can see the email here as well now on important difference is if we go to Adrian profile which is the currently logged in user we're going to go to the my profile tab but if we go to the profile of another user we're going to go to the agent show profile which is a completely separate thing so since we're currently logged in into Adrian we can do the my profile page so to do that we can collapse this right here and then we can go to pages and then my profile but don't worry once we Implement one the second one is going to be incredibly similar as that's what they are profile Pages no matter if it's our currently logged in user or not to get started with the profile page we can import our trusted use get identity from pan card refine core as well as use one great below that we can also import our profile component which we're going to soon Implement and that's going to be in the components folder now my profile is a functional react component so we can use the capital M at the start and we can first get the data about our user const data we rename it as user is equal to use get identity then we also want to get more info about the user from our database so we can use the use one const data is loading and is error is equal to use one we pass in an object where the resource is equal to users and then the ID is equal to user question mark dot user ID like so with a lowercase i letter finally we can get our individual profile by saying const my profile is equal to data question mark dot data like this or we can just leave it as an empty array finally if we are loading so if it is loading return loading if there's an error return error and the only thing that this profile is going to show is going to be a render of the profile self-closing component the reason why we have this profile component is once again to be able to reuse it both on our profile and on the profile of a specific other agent hopefully that makes sense same way as we reuse those little cards inside of of the agents so our profile is going to have a type and in this case that's going to be my my profile it's also going to have a name so we can pass my profile dot name it's going to have an email my profile.email it's going to have an avatar my profile.avatar and it's going to have properties equal to my profile dot all properties and finally we can control click into the profile component and start implementing it of course first we have to deal with the Imports so we can get the profile props right here and then get all the needed props that's going to come from interfaces forward slash common and there we can simply get the type the name Avatar email and all properties and say that's going to be of a type profile prompts and if we save this and go back to my profile of course if we properly spell this there we go we can now go to Adrian and we have just loading and as you can see it just keeps loading that means that we haven't yet gotten the data for an individual user in our database which is exactly what we can do now so we can go to our user controller and do our last backend function get user info by ID to implement that function we'll have to get a const ID is equal to rec dot params we have to know which user do we want to fetch the data for so we get the ID from the params then we say const user is equal to a weight user dot find one where the underscore ID is equal to ID and then dot populate all properties so we want to populate all properties on that user finally if there is a user then we can rest that status of 200 and we can return that Json user that's it so we're returning all the data but also all the properties about that specific user that's what the populate function does if you think about it in the model right here mongodb models user you can see that the user itself just stores the IDS of all properties but we don't need IDs in this case we need complete properties so what we can do is we can populate all properties which is going to generate individual property objects inside of the user great now that we have that we're simply going to return it but if a user doesn't exist then we can simply rest that status 404 user not found great now if you reload the page we can see barely right here but if we expand it we can see the profile which is exactly what it says right here great now this profile page is going to be entirely made of pure layout we're not going to do any logic there so once again to make it a bit simpler for you the complete profile page will be provided for you in the GitHub just down below simply find it there and paste it right here as you can see we're going to go together to every single little detail of this page but just to share with you we have a name right here we have a dummy photo address phone number and the email and that is about it so how does that look like we have boxes typographies more boxes within more boxes as usual we have this dummy image and then we have a box for the Avatar icon then we have a box where it says real estate agent right here then we have a stack for this specific address and then the actual static address and then this is copied two more times for the phone number and for the email which you can see right here and that is about it but now I'm gonna show you what really matters we're done with the user controller with the my profile page but we haven't yet done the agent for a user that's not my profile in this case JavaScript Mastery it is A4 4. the reason for the 404 is because we are on the agent show and we redirected from the agent page which means that we need to go to the agent card and then look at the link if we see it right here this is supposed to be agents plural so if we fix it and then click we go to agents show and now we can see the agent empty profile right now it is empty but if we go to agent profile page we can get started with filling it out and that's the best thing about this it's going to be almost entirely the same as my profile page so we can go to my profile and simply copy and paste the entire thing into the agent profile page and paste it right here you'll have to rename the my profile to agent profile like this and then we don't have to use the use get identity because that is for our currently logged in user we just need to use one we're going to also use the use params so we can import use params coming from add pan card slash refine Dash react Dash router Dash V6 then instead of using the use get identity we're gonna get the ID use params like this then once we have the ID we can simply use it right here ID as string to get the real user from the database it's loading it's trying to get it but it's having some issues as you can see it got a status code of undefined so let's try to console log the data right here and see if we get anything back since it had trouble loading I'm guessing it's not going to be there immediately so if we open it up we indeed do get undefined so if we try JavaScript Mastery one more time yep it's having trouble loading it so as always in JavaScript Mastery let's debug it together let's open up the inspect element and go to the console there we can see an object that doesn't give us a lot of information but if we go to the network tab and then reload the page we'll see a request being made to our backend and there we go it fails right here if you check the headers we can see that it's going to localhost 8080 API V1 users and then the ID of that specific user which is great but we're getting a status code of undefined which isn't really good so let's go ahead and check out our user controller 4D get user by ID and as you can see in all of our other routes such as get all users and create users we have a try and catch block and in this case we don't have it so I'm really glad this happened we now got an error and we didn't properly handle or account for those errors so we can now do a try and catch block right here put all the code in the try block and then simply return the proper error just console logging or returning the error of course isn't going to fix it but still it's going to give us more information so we can do res dot status and then send 500 and then pass over the error message so if we do that and reload the page so apparently it just failed at the start but then the second one returned okay so I was wrong adding the error handling actually did fix the problem which is great so with that said now we have the my profile page which is wonderful what I wanted to show you is that agent profile and my profile are exactly the same we're just reusing this profile page but it still says my profile and this is a profile of another agent so we can go to that's going to be agent profile and we can change this from my to agent and more or less that's the only thing that we have to do because all the other data is immediately being different from our profile if you want to check that out so we're currently logged into Adrian and I was hoping to see the profile right here but it looks like it's having some trouble fetching it so if we go to the network Tab and reload okay it gives us undefined now so what we can do is I will try to expand our browser to explore our application in more detail and I'm going to log out I'm gonna go back and log in with our original JavaScript Mastery account and it looks like it even fails to log in right now so if we go to console yep nothing seems to be running going back to our application it seems that while testing the application we have crashed it so that's entirely fine it happens so what we have to do now the only thing is just re-run our application and everything is going to go back to normal that's why it's important to always have proper error handling so your app doesn't break now if we go back we can sign in with Google I'm gonna go with JavaScript Mastery this time and we got invalid credentials so let's go to inspect Network and let's try it one more time as you can see in the users it says res that stats is not a function which means that I simply misspelled one function inside of the user controller so we can go there and see where do I have res dot stats it is right here in the create user so that is supposed to be status great let's get that fixed and let's try to log in one more time I'm gonna do JavaScript mastery and we are in and before going to agents let's open up our app and make sure that our app is running fine so right now it is crashed so we have to rerun it by running npm start then we can go to agents and let's open up another agent it's gonna try to load it but looks like it's gonna be unsuccessful yes it's still pending and it just gives us an error inside of our application though we can see that this request broke it so if we look why it says cannot set headers after they are sent to the client and that was on getting us the user info by ID and that is another huge issue on my end you must never ever have two restat statuses in the same request it's trying to send it two times once for successful and once for a 404 you can either have a return here so this is not executed or maybe even better you can wrap this in an if and then you can wrap a 4 4 in an else so hopefully this was a great lesson for you once again that is the reason why I want to include all of this is to teach you something because that's what really matters it's not just about building apps it's about getting stuck and I'm here right now with you to help you get unstuck so once we fix this we have to rerun our application and then go back to agents let's go to Adrian and there we go it opens it up we can see agent profile Adrian we can also go to my profile which opens up my profile JavaScript Mastery and in this case it also shows us our currently owned properties with that said we have the dashboard we have the properties we have the property detail page we have the agent Pages both for my profile and for other agents profiles as you can see they are incredibly similar but on my profile you can also see my properties we have the logout button and it is all getting close to being fully done we also have a wonderful sidebar provided to us by refine and finally now that we can properly fetch our properties and our agents we can go back to finalize the part which we started on the dashboard right at the bottom of the static data we can now go to the dashboard and do this we can showcase a property list or an agent list right on the dashboard it's going to be incredibly simple now because we already have all the backend and all the logic setup we we simply have to make the calls to the back end and then reuse the same property cards and agent cards that we have created over here so let's go ahead and let's get start with finishing our great application and we can do that by collapsing our browser closing all of our currently open files and going all the way to our home page right here we have total revenue and property referrals charts which are these two but now we are ready to focus on what goes below them and that's going to be of course our properties so we can create a new box right below this stack that box is going to have quite a few properties so we can open it up that's going to be if I just fix this a flex equal to one a border radius as well equal to 15 pixels and it's going to have a padding of 20 pixels as well as a BG color equal to Hash fcfc FC now if we save that you should be able to see a card appear right here at the bottom we can also give it a display equal to flex we can give it a flex Direction equal to column as well as a Min width equal to let's do 100 in this case and finally we can give an empty or margin top of 25 pixels to divide it from the top and there we go we have our card where we can put our properties inside of it we can create a typography and that typography is going to Simply say latest properties just like that we can also give it a font size equal to 18 pixels we can give it a font weight as well of 600 and a color equal to hash 11142d let's check it out that's looking good and right below that we can create a box that's going to act as a container for all of those properties that box can have a margin top of 2.5 to divide it a bit from the title and then SX property of display is equal to flex wrap is going to be set to wrap and GAP is going to be set to 4. and inside of there we can map over all of our property cards but of course first we have to fetch them so if we scroll up we have to utilize this use list hook and we already used it for a couple of times so far but now we're going to really make sure that you understand how it works so we can say const we're going to get the data we're going to get the is loading and the is error coming from or rather is equal to use list to it we can pass the resource we want to get that's going to be properties and there's also a special config we can pass config pagination and then page size is equal to in this case let's do five I think we can fit five properties right here at the bottom and use list we have it right here and it needs to be in a home which is a functional component so it starts with an h a capital H for home so you can fix that right here and now we have access to the latest properties just like that we're getting it under the data right here and as we did before we can pull the data from the data object by saying const latest properties is equal to data question mark dot data and then question mark question mark and then array meaning if we don't have any data just make it an empty array and as we always do if we are loading we can return a typography or a div of loading and if there's an error we can turn a typography saying something went wrong with that said we can now go over all of these latest Properties by saying latest properties dot map we're going to get a property and then for each property we're going to instantly return guess what it's going to be a property card a component we have already created so far the only thing we have to do is pass the right props to it we can pass the property dot underscore ID as the key we can pass the ID equal to property dot underscore ID we can pass the title equal to property dot title we can pass the location equal to property dot location we can pass the price equal to property.price and we can pass the photo equal to property dot photo and if we save that you can see all of our properties now we can only see one because only one exists right now but let's fill this up and let's test this application further we can go to properties we can go to add property and let's add let's do a star Sun Hotel description is going to be just dot dot dot for now the property type is going to be an apartment price can be 550 location can be let's do Croatia and we can upload a photo I'm gonna choose this apartment right here and upload there we go we have two and let's add one more that's going to be a almunder hotel and apartment this one can be a condo and let's do 420. we can give it a location of something like Italy one more time and we can make this one the condo and let's submit and as you can see we have three properties and on the dashboard we can see three properties as well so it seems like we can only fit about three with this size but if we expand we can fit about four so we don't have to fetch more than four so we can go back to our list and see how easy it is which is gonna say hey fetch for Max great with that said we're gonna have a layout that looks like this we have a wonderful dashboard all of the latest properties which by the way you can simply click and visit if you are the owner you can edit them which works really well you can delete them and you can also check the agents all agents on the page we can check their profiles and if you check your profile you can check all of the properties that you created isn't this great we built all of this today in this one video it might have taken you more than a couple of hours and that's totally okay as you noticed we encountered a couple of Errors while building this but that is what every developer does that's the whole goal and journey of building a phenomenal project such as this one I gotta say I'm incredibly pleased with what refine did to enable us to build all of this in such a simple and quick manner all of the routing error handling logging in and all of the abilities to fetch resources and immediately be able to just use the list or use identity these hooks are so useful and I love using them with that said as we always do on the JavaScript Mastery we are now going to deploy this application to the web so get ready for that right now before deploying our application to the web we're gonna first have to publish it on GitHub so go to github.com and then on top right you can create a new Repository let's call it refine underscore dashboard of course feel free to use any name you prefer we have to make it public and then you can create Repository now you can collapse this to the side of your code editor and we're going to create a new instance of get right here by going to view and then terminal first make sure to delete one terminal and then in the second one you have to see the dot dot to go to the root of our folder there you can run git init that's going to initialize this as a new GitHub repo now I here can see this dot get folder but it might be hidden for you if that is the case do control or command shift B and then type open settings Json you can choose either workspace or regular settings and then you have to add a couple of lines you have to do this files that exclude and then you have to add asterisk asterisk forward slash dot get is set to false copy this exactly and then you should be able to see your git folder once you do that you might need to reload your Visual Studio code but once you do you can see a git folder here and here now what we need to do is we need to delete the git folder inside of the client so completely deleted and say yes if it asks you any questions now we are ready to add everything we have from the client in the server before we do that we have to add a DOT get ignore file inside of the server and ignore node underscore modules great finally we are ready to follow the commands that is git add dot to add all the files git commit Dash M first commit git Branch M Main get remote at origin and finally git push U origin main this is going to push our entire application to GitHub and we should be able to see it right away there we go once that is ready you can open up render.com we're going to use their services for deploying our backend application make sure to sign in with GitHub as that's where we published our application once you do that go to new and then web service if you can see right here we have to enter the public git repository so find your repository copy the URL and then paste it right here and click continue we have to enter the app name let's do refine underscore dashboard branch is going to be main root directory is going to be server and then the start command is going to be npm start we can even check that in our application if we go right here server package Json we have a start script finally you can choose free and create web service while that is doing its thing we'll also have to add environment variables to here so let's wait a bit let's go to environment and then add environment variable now we can copy the ones we have here that's going to be mongodb URL as a key and this value right here and we have to add a couple more for cloudinery so just copy the key and copy the value and repeat the process for all variables cloudinary Secret cloudinary secret and I think I missed the key as well so you can add the key right here there we go so this looks good and you can click save changes once you do that you can go back to logs and we can wait for our application to be deployed since we change our environment variables we can rerun our latest deployment this process usually takes just a couple of minutes so you can pause this video and we'll be right back and there we go we can see mongodb connected and everything is working perfectly it is still in progress but in just a couple of seconds it should be running on this URL right here and there we go our app is live let's copy this URL and click it and as you can see we get hello world but this time not from localhost 8080 but from a real online deployed URL the only thing we have to do now is go to client and search for where we used the static 8080 it is listed in a couple of places so right here it's in the app TSX right here in the profile obj so we have to replace this with this newly created URL all the way to the first forward slash we have to repeat this three more times one time for the data provider as well so we can override it and that's it so it was only two times rest of Dimensions is on the back end so with that said we are ready to deploy our client side as well and how you do it is you simply go into client so CD client and then run npm run build this is going to create an OP optimized production build of our application while that is happening we can go to netflixy.com they allow us to really quickly and simply deploy our reactions applications you can log in log in with GitHub go to your sites scroll all the way down and this is where you'll be able to drag and drop your optimized production build as you can see it is still being generated we can right click it reveal in File Explorer or finder if you're on Mac and then once it is finished building you'll be able to Simply drag and drop the entire build folder right here but let's give it a moment and before dragging and dropping there's one more thing you have to do in the build folder right click create a new file called underscore redirects inside of there you have to add forward slash asterisk and then you can add two spaces forward slash index.html 200 just like so and then this is going to ensure that when you reload your page on a specific route it doesn't give you a 404. that's something we have to do when deploying applications on netlify and there we go it is done we can simply drag and drop it right here it is uploading as we speak and in just a couple of seconds oh already it is published we can even change the domain by going to site settings change site name to something like refine Dash dashboard and Save we can now click this link and check out our deployed live man stack dashboard and if you try to sign in you're going to notice that it's not going to work right off the bat with Google there we go something breaks so that's entirely fine we'll have to go back to the Google console to get that fixed but then we'll be Off to the Races you can go back to console.cloud.google.com and there you can open up your oauth 2.0 client IDs once you do that you'll see your authorized JavaScript Origins and redirect Uris simply go back to your application and copy the URL of the deployed app and then add it right here at the URI it's going to be this one you can simply remove the last forward slash and then you can add it right here for the redirect as well and click save it might take a couple of minutes for the changes to take effect but sometimes it works immediately so now if we go back to our application reload the page and expand it to the entire browser we can sign in and would you look at that the sign in appears so let's sign in with JavaScript mastery and it didn't work out correctly just fine so let's open up the console and the network Tab and let's give that one more shot we can click JavaScript mastery and we can see that the current origin isn't registered with the Google oauth so just maybe I went ahead and started it too soon maybe we need to give it a minute for it to work out because we did just add this refine Dash dashboard origin and would you look at that it started working while I was speaking so just to make sure it works one more time I'm gonna log out and I'll try to sign in again with a different account so right here we're gonna use the second one and we are in we can see that we have all of our latest properties we can see them here as well and we can see our agents our application is working perfectly I'm incredibly happy with how this turned out now there are a lot of adjustments you can make this application to make it even better change the name change The Branding make it your own make all of these stats real and connected to the database either fix it by changing the URL right here or Implement your own Google Maps integration so you can show your little map right here there are a lot of adjustments you can make take this app and make it your own but even with that said what we have built here today is something special it is a full stack mern application using two resources properties and users we have a wonderful front-end Builder to react and mui and we have an Express node.js and mongodb database once again huge thanks to refine not only for sponsoring this video but for creating such an amazing tool that allowed us to build this application today with that said thank you so much for watching and I'll see you in the next one have a wonderful day [Music]
Info
Channel: JavaScript Mastery
Views: 203,510
Rating: undefined out of 5
Keywords: javascript, javascript mastery, js mastery, master javascript, MERN, MERN stack, MERN development, mern app development, mern application, build a mern app, mern crud, crud principles, react crud, react crud app, react crud sorting, crud filtering, crud pagination, react crud mern, react mern crud app, react figma app, full-stack, full stack, full stack app, full stack mern application, mern full stack app, refine, refine dashboard, refine mern app, refine crud, typescript
Id: k4lHXIzCEkM
Channel Id: undefined
Length: 281min 22sec (16882 seconds)
Published: Fri Feb 10 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.