Next JS 13 Tutorial: Build an Airbnb Clone (React, Tailwind, Daisy UI, Zustand)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
are interested in learning about nexjs 13 and its new features like a router this tutorial covers Concepts like routing and layouts and you'll learn how to create nested layouts so to optimize your application's performance and avoid any unnecessary re-renders other very important topics that we'll cover is how nexjs has changed server-side rendering and data fetching in their latest version and how we should think about these changes and Implement them of course whether you're already familiar with nextjs and trying to understand their new patterns or you're a beginner learning the concepts for the first time this tutorial will be helpful in both cases not only that but you also learn how to create killer animations and modern responsive stylings to provide the best experience for you all covering these topics will build an Airbnb clone will focus on building search functionality that includes three different types of filters and and redirects to the use results page on that page we'll build responsive cards for every single result and an option to Heart the result as Airbnb has and in the end We'll add a mobile menu to make sure our application is mobile responsive please note that this video will only cover the front end and we will create server and client components but will not build the backend to communicate with from our application I'm planning to add that in the next video also this video has chapters and almost every chapter has its own branch which you can check out from GitHub the link of the repository is in the description that way I want to make sure that you're never lost during this tutorial and are always able to continue with the same code as in the video that being said let's get started with the tutorial and if you enjoy my videos please like And subscribe that really helps the channel grow as we are on the path to hit the next milestone 1 which is 30k in July we can start by creating a new next project and we can do that using this command create next app and after the next step comes the name of the project I named the Airbnb and if you want to use the exact next version that I'm using in this tutorial when I'm taking the videos 13.4.42 but if you don't add the version by default next will use the latest version but just in case everything follows the way I'm using and not to come across any conflicts and when we hit enter if you don't have already installed create Next Step command like in this case it's going to ask you if you want to install so I'm just going to say yes and proceed and then it will ask us how do we want our project to configure so this is what I'm gonna select for the project now for typescript and eslint but I would select um we'll use Tailwind CSS for styling and also for the source directory we're going to see know and we're gonna use the new app router which is basically a new paradigm next element for after creating like using Pages route this is the next Paradigm for creating pages and layouts uh would you like to customize um the default import Alias and on that one we're gonna say no it will start installing all the dependencies all right so I have the project open in vs code and I'm gonna run it by going to terminal inside it and using the command npm run that that should open our project on localhost 3000 and we navigate to it by command clicking that opens up in a browser and this is what our like a boiler play template is coming up from next year so where's this code coming from Mostly it is from this page.js which is as previously was index.js and this is all the code and we also have a layout which contains so far just metadata and what layout is that it's shared all the children that are going to be inside this app are gonna share this logic and be wrapped into for example body HTML okay let's see how easy it is to create a page and for that I'll just inside app create a new folder name it search I want the route of the page to be slash search so that's why I'm naming it and for creating page new file the name should be paid which dot dot JS inside here we're just gonna create like a functional component so that would be export default function page and we don't have any props in it so far and going to return just a header that says my page this is what we'll get and as you can see there's some like weird gradient lines so to remove that it's coming from styling from xjs so Global CSS is the file we're gonna go to and starting from media to the body this um styling we're gonna remove if we save this it's gun and now let's see how we can create a layout for this page that we have so that all the logic related to search right now and all the other pages that we're going to add are going to go into search folder which is convenient also the client component and this concept is called decoupling so organizing your code based on the functionality so without further explanation I'm going to create layout the JS file and so far what we want in the layout is the header and let's create the layout component first afterwards we're gonna import and create header into it so export default function we can name this search so if we do that right now this shows up at the top so let's actually create the header element now and then export that into our code so header new file Dot jsx and inside header as Airbnb has there's like a search search box input user can interact with it since it comes with some interactivity and UI this is going to be our first client component and way we Define client components in react next.js is by adding use client at the top so let's code the rest of it out export default function header we have no probs and we're gonna return I will use the HTML header tag and inside here we're gonna have three divs and then the other these rested in nested in there so the first one is going to be just the logo on the left side so that's airbn B and then the next one we want to do so this is where the search goes and at the end some like the user information and we'll make this a container um then we'll make this flex and justify is going to be beat ring and let's set the height to 10. save this and now we don't have any differences because we have not imported it yet so import Heather wrong so here we see our header at the top let's update add some inputs into search so what I will do I'm gonna close this out and I'm gonna move this to the side so while we're updating the styling we can see some changes so first we can change the color of this class name equals text red maybe like 500 so that becomes the Airbnb color and let's turn this search actually into div with multiple inputs in it so first class name I'm just gonna give it search container I also want to set it rounded um large and then I'll have so this would be for anywhere then we have any date and add guests it's interesting that it did not get updated or maybe there's an error so we open up console there isn't any okay so I realized the reason when we're saving changes here and they're supposed to automatically reload in the page and it's not happening is because Heather is not the name of the file is not Capital so for components we're gonna have Capital otherwise for Leo and Paige another like components that don't get re-rendered then those would be with the lower case so now it will ask us if you want to update the Imports if it doesn't ask you you have to automatically One Import of header is in layout so we'll have to update well we can wrap the children in the main and go back to header so now let's say if we turn uh search container Flex we should see the update coming in all right let me close the other files and I'll start by updating the main um pairing component of this one first so height we have that set to uh 10 now I'm gonna update for the bottom only then this is already set to flex background white also the index 50 what this is going to do is if it's higher than other components we always want header to be showing at the top we also want position fix and width to be full let's save this and we can see the border right here now moving on to the search container so Flex column let's add a gap in between those elements so Gap three and we also want to add the border on the right side for uh the first three and we'll add another D before search and we'll turn our search container into a button so when this button is clicked it will have expanded like a bigger container that contains all the other advanced search elements and those are have their drop downs and as well but to have like store the information that this has been clicked we need the state so here we're going to create our first date first we need to import use a state Hook from react so after doing that we're gonna name our state so constant uh this would be easy expanded and set is expanded how we are gonna update the state you state and and you stay we pass in the default value which in this case is going to be false unless user clicks on it it's not going to be expanded and once we have that we are going to create a function that we're going to pass into this button so constant toggle expanded name of the function and it doesn't taking anything only thing it does is that it would set is expanded to opposite of what is currently said so we're going to take the previous easy oops and set to exclamation mark when we're working with booleans is how we access the opposite of it so if this is true you'll get set to false and vice versa so button on click this equals to toggle expanded now if you don't already have I recommend installing react Dev tools it is easy to manage the state because we don't need to on click I'm spelled it and we wouldn't need to like do console logs and those sorts of actually this is going to be the opposite of not what is suspended but like a previous state let's say let's save this and go to components once we want to examine a certain component we use this selector here and if we for example press it here it should select for some reason let me reload and usually yeah so we target the header and we see the state here is false so now if I click it it should get updated to true as shown here great so now what we can do is if this is expanded we can um display the more as I mentioned the complex advanced search so for that let's inside a search component a search folder create a new components folder where we're gonna keep all this components and in here we can create a new file name it um search bar the jsx so oops that's I have an extension that Snippets should load automatically when I type this thing but it seems like it's not working it's like a vs code extension um so let's create a functional component uh search return [Music] export default okay and then in here let's first create a div element inside the once again we're gonna have like a three sections first one is gonna be for the location and this will be button and if somebody first will just display like um P tag that says uh search destinations and second up we have another div and the label of this one is going to be uh dates and Below like subtext is going to be select ranges so let's do dates and after that we can do and final input that we have is going to be add gas so I'm just gonna copy this over and say Edgars let's save it and inside the header here now we are going to import the search bar and if it is expanded we'll display this search bar so import search bar and remember this is inside the components folder so we have to indicate that now how we do how do we do conditional rendering that's going to be inside the header here we can um take this button that's for our like basic search so to call and we can say if is expanded question mark then displayed search bar and then if not the other search so this got reloaded let's see if there's search bar is not exported okay oh because it's a default export so I'm gonna remove the curly braces and save it now we should be good so if I click here I get the other search let's now leave this state open and modify some of the styling and change some logic uh so first I'm gonna start with the parents so make it Flex Flex direction we want it to be row self Center and rounded let's make it full also border around it padding to margin top eight and with about 3 4 of the whole um parent container and after that we can start with the button so what we want to do with the button is when somebody clicks on it we wanted to turn it to an input so user can type it in right so for that to say when it's um clicked we need another use state so import use State we already know how to create one and let's practicing now but this case we're going to give it a different name so uh something like ease search focused and set is search focused this one also by default it is false till user clicks on it and we can say on click and we can call like uh this is called callback function and this would be set is search focused pass the parameter true and in here we can Define the logic once again we are using oops oops the conditional rendering so if is search focus is set to true then we want to display an input and if not then we can keep just the paragraph of destination so input what uh type it is it's text and we can say placeholder same text as we have on this one so just copying that over here so now if I click it this is a search box and we can add some styling so that it matches that of an other element so class name we can do text slate 800 background transparent what else border none because it has like this border when I click it also outline none okay so that is better and let's do update also for the class name here we're gonna say text slate 600 and let's also the other ones have like the main title and then the subtitle so this is going to be subtitle let's also add the main title so this goes in both cases will show up so I bought this and class name equals let's do font bold for all of the copying this and title where all right that's good let's add that onto the dates and guess great and for the subtitles I'm gonna copy this class name that's slightly like um changes color makes it look lighter so we have visually we are able to distinct between the two all right what we're gonna add next is a drop down and we'll add it on our search for locations we don't need it because we already have a like a text box already in place but for dates we need to show the calendar and it's not going to fit in here same thing for guests we're going to add a counter inside of the drop down so what we're going to use for drop down is the daisy UI it is a component Library built on top of um Tailwind so you can still use Tailwind classes it just comes with a little bit more configuration so you can or use already build components and we install it by running this command which I'm gonna copy here go to my code in the terminal and add a new tab paste it while there is running let's take a look at the how we can add a drop down so here is the documentation and drop down can open a menu or any other element one button is clicked so the class name we need for when we're targeting the button is the drop down and the content itself is drop down content and they also have uh CL um code in here that we can take a look at so and the way we identify which drop down opens which tab is using tab index and here are our classes okay let's get into writing that we don't need to import anything at the top we just need to add those classes so first I'm going to add that on the dates select ranges let me just quickly update this name and so first the wrapper this would be classroom equals to and we can also configure which side the drop down shows up for example if it's aligned to the end this is how it is and then there's a like this class so we're going to do that one and after that the container for the drop down itself so as I mentioned this is going to be with the class name drop down content and we have to pass in the same index so if we temporarily add um range selector here oh we need to add inside telling call config.js file this plugins otherwise it's that's why it's probably not loading so here we have plugins and I'm gonna paste it so it requires it uses this UI now let's rerun this and since we updated the configuration we can rerun the app and refresh once it's done all right so now if we click on it click on it this will show up and it hides when we click away all right I'm gonna close this documentation now and let's add the same thing for the guest um so first one I am I can just copy this except for border on the right side because the guess is the last element so we don't need further on that and let's do labeled having text now we have to use a different number since we're targeting a different element so I'm going to add two in here and here equals true and we can add the rest of this classes so this is where the counter will go and for the counter we're going to create a separate component but let's first make sure that it shows up all right great so going back to where we have components folder this is new file so basically counter would let users select number of guests they want to search for so new file Contour Dot jsx and here we import we also need to track the number that users have selected so we need to use state for that and then we create our functional component export constant counter we can create this as a reusable if anywhere in the application we need um counter so what we can do is we can pass a label so what's going to show up in our this case it's going to be a number of guests and uh we also as I mentioned track down the guest count and set actually we can just use count since this is reusable and set count that equals to use State and by default this is a state so let's return so it's going to be um minus icon and then on the the label in between an N plus icon and by default if it is zero We're Not Gonna display because we don't want it to go to negative um so that would be let's create the outer container and we also want everything to be displayed under the same row so I'm going to create a flex container and justify between then we have our label at the top so label items Dot Center and in when um we are creating Flex element we can indicate Gap as in how big the space is between the children Flex items so as I mentioned the minus is only going to show up when we have um more than one so just count more than zero I mean more than zero and if this is true then we can show up and then this is going to be a button and then we display the count itself so I'm going to create another span for this one and finally we have the same and also we want when user clicks on minus or plus this to get updated so since this would almost do the same thing except for increment and decrement it would make sense to create another component and just be able to pass that component the props so constant count icon and this equals to icon which would be different and then on click we'll pass different functions so it's going to return a button reach on click would trigger the function that we are passing and then inside span we display that icon and then what happens on click is that we are passing a callback function in which we are taking set count and so previous count and previous count minus one right and we can copy this but instead we don't need this condition because it will be displayed all the time and update so this is going to be plus and plus let's save this let's import this counter in the search bar so import it was an export right so we need curly braces counter place that all right so now if we click we do see Zero and if we increment we see the minus sign now let's um configure this so the icons are like rounded they look more like buttons so we are going to go to count icon and inside of the button here let's add a class name so we wanted to have a border and it's supposed to be circular so rounded full then setting the width setting the height you can do Flex because we want uh this to be uh centered and and we have not passed the label to it so label equals to what's through adults too and then zero close this out now before moving to the search results and search let's add one more thing to our search that would be the calendar so for the calendar we'll use this module react date range and it has this like calendar date range selection which is what we need and what we're gonna show in the drop down that we created so first step is we have to install this react day range and then it has a one more uh dependency and let's add that as well so npm install say react take range and another package I'm gonna install is date FNS so it's basically uses this second package to display dates and we would also need that and all right that is installed enter user we have to import a the silent theme files we can either do this in the main file or we can do it in the file that we are going to be if it's only one place then that we are using this then we can just do it there which is in our case search bar so okay let's import the files and after that is important we need date range Pickers so I'm gonna import the module here and let's see how it works they have also just like the calendar one but um so we create a function that's going to handle the selection and then we pass it this object as a props here and this object contains like three fields which is start date and date and a selection so let's first create a state so we can keep track what is the start date and the end date so constant start date set start date that equals to so if you go to Airbnb it's gonna set the start date to like today so if you create a new date that's what it's gonna do it set to the current date and constant and it said and date this is going to be now because it's not set unless user selects it and let's create this um selection range object so render we don't have a class component so we can what we can do is just do that before return so but instead of new day we're gonna pass here our state and same thing for this one as well so key let's leave that to selection and handle let's write a handle select function so constant handle select that equals to so it's taking in um ranges as an argument and what we can do so this ranges contains a so this is what's inside ranges so we can take ranges that selection that started and set it to start date so start date ranges the date let's fix that one and second part let me just this and replace it with it all right so we have that and we can um add some like verification and so for example if we don't want like extra State reload so if the start date is already selected then we don't want to reload the state because reloading State also rules components right so let's let's check if range is selection that start date doesn't equal to start date then we place this inside here or actually and the same thing if ranges the selection that end date doesn't equal to and date let's do that save it and now we can um place our date range picker component because we created a function and props for it and it's gonna go inside here so to date range picker so for ranges we have and passages in Array selection and then we can also pass minimum day because we don't want users to select like past before today and also Airbnb doesn't let us so that makes sense so on change is going to be handle so select and we can also customize the colors because as you saw here it's using blues and we can use the Airbnb colors so that's going to be colors we pass it as an array you can pass multiple colors but I have one so that's what I'm gonna pass and I'm gonna copy the color hash and paste it let's uh um forgot the closing tag and save that see what we have here oh that's our calendar so because we don't have an end date it shows continuous but let's do this selection and in here and then if we close this out and open it again it should have the state um saved regardless if the drop down is open or not to add the search button here after our selections for search input we can go after the last drop down and add button so inside here we can add span search and this button class name let's add some styling so padding um on the sides text white rounded full also background let's set it to primary uh padding for flex and then we wanna Center our text and after that we're gonna add an icon so we want some space in between icon and text so Gap three and flags would be row so let's save this showing up search Okay so the primary color right now is set by default to purple but we can update that and set it to like the Airbnb color which is this one or we can just use Pink So to update that we go to Tailwind configuration file colors and set primary modify to this and we can also set a default border collar and that would be border color default and it's gonna be like light gray similar to how Airbnb has and we need comma in between this let's save this and um now our borders are more um darker so we can see them better and this is the search that we have okay now let's add the icon and afterwards we're gonna fix some of the styling in the header so and for adding icons we are going to use this package here here icons it is also made by the makers of Tailwind CSS and going into documentation let's see how we can install it and okay so we copied this command npm Install hero icons react and run it inside our application and then we browse icons from their uh website like library and then import it in this way and let's but instead of Beaker icon we need um let's do search okay so magnifying glass and I'm gonna update the name icon and it's also really easy to update uh The Styling of the icons because we pass class names Tailwind says class names work so let's add that right here and setting the width and height so five five and it's the color because the parent is um color white it will also Peak should pick up the color and that's our icon right there save it and let's update the parent component so adding some padding rounded full background primary once again and the height of this one should be greater than the part of this and we need to make this in the center so what we can do is we can make the parent container relative and then if we make the child um absolute that's gonna and add like how the position how each of the position it's going to position according to the parent so let me show you where you guys what I'm talking about first text white that's going to make it color white and setting this absolute so now nothing changes but if we indicate top should be one half and left should be one half so that would like Center it you can do also from the right Etc so that would push it down and then transform Translate from the x-axis and then when you start with the dash that means we're um going for a negative Intel wind and transform translate this is similar to setting it minus 50 if you have seen that CSS before all right and that's engine now we can update the styling of the header and one thing you'll notice is that when we have this or advanced search open we want to update the height of the header right so that would be like conditionally when this uh expanded state is set to true then we have we need different height so if we do that inside um here it when we pass the class name which is possible but then the class names and managing it would get messy and also Tailwind needs to know the classes at the render so not calculated when it's passed so let me show explain what I'm talking about so dear class name equals let's set height to 7.5 Ram and let's wrap everything inside header in this container so now we have the height of this one but if let's say this is expanded where's the div game coming from so question mark and then we want height 13 Ram right and then close it so anytime until we might want to pass like a custom value usually high can be small large then we use brackets I'm passing the value so let's see now the height is seven point if we inspected well I have 10 sets somewhere let me remove that okay so what we got here 7.5 RAM and then now if we open it that updates to 13 rep but if we want to add um other classes that are same to all of them for example I want to pass this is a container then it means that I have to update this one as well and it just gets messy to manage it so what I use instead is this small like utility package for constructing class names conditionally and then what you do is you pass default class names and then you can also pass in conditions and I'll show you guys how we can do that and first let's install this class name um like managers so to say and once we have the we're gonna import it at the top so that is how it's done either import works and we can Define header classes so either container classes equals clcx and first we go on with classes that's going to be um by default so container we want to Center our container then we wanted to make it Flex uh justify so we do have Justified between and background White then add some padding and now this is where we pass the conditions so that's a new object height would be 7.5 RAM and then condition is not is expanded [Music] 13 Ram that's when it is expanded all right now we can take this and instead replace it with this one and once we have that I'm gonna remove so Flex justify between we don't need this here fixed uh border bottom okay you're the our icon okay let's also remove container from this header since the inner element has it so that looks better and if we open this and later on we're gonna turn this into a model and add some cool animations to better display the transition it's in between these two like expanded search and not expanded one so make sure to not miss it out and stay tuned so border right and okay adding some heading and text left all right and we can do the same for search container classes so I'm here I'm gonna create a new object name it search container classes and that equals to clcx and start listing the class names that we want to add so that would include search container then we have it Flex Flex row and let's see so actually instead of rounded so we will replace this one with this okay and instead of rounded large that we had let's do fool add some padding justify Center items also Center and we haven't added the Border yet so let's add that as well and a little bit of Shadow which would be drop Shadow dot medium background white and also conditional statement that if it's not expanded border bottom is zero otherwise let's set that to eight so Flex okay so now we're moving on to building out the search uh page the rest of the search page with the results and what do we want is that by default when a user lands on this page we want to show uh just like a different page and once they click on the search we want to show them like search results results based on the search the input so these two are going to be different pages and what's great about like the new app router is that we can do nested layouts and right in between this uh page updates the layout components that are shared in this case the search component at the top those don't get reloaded so the states get retained and we navigate to a different page without losing anything or reloading that component so let's see how we can do that so first let's examine what do we have on the search page that is my page and we are on the search page right now but as you can see there's no text showing up that says my page the reason of this is because we have to update the layout so what's going on in the layout that we have header displayed at the top and then we have main children so this instead actually the page my page is in here but it gets overridden by the head so um header so we have to update the layout so if we examine here and type it in my page we're going to see that it shows up at the top and this change would be um fairly simple because what we have to do is add the class name to Main and you can make this relative and top sets to 7.5 Ram that's the height of the header then we have some padding in the tablet set four Also let's wrap this inside container and center the container save this so that should push it down it didn't get a class name okay now here it is now if we wanted to create a nested layout that we would do by so for example after search we go to another URL right so that would be inside um search and we create new folder that would be results and inside results if we create new file that is Page the JS and we create export default function page no problems we're going to return each one this is results page here so if we navigate into search results we get the results page and we didn't have to add this layout at the top it was already shared because it's coming from the parent layout so parent is a search right here and parent layout but if we wanted to results inside have another layout we can add also the same way that we did search so this is nested right so somewhere we did search layout page we can do the same for us but for now we're just gonna we don't need layout because we're not going to have any more nested pages in here and we're just gonna work off of this page and let's see how State can be retained so let's make this button actually a next link and see how we can programmatically navigate to the that page because right now I just updated the URL so that that is where next link comes in and if we go to the search bar and turn this button into a link we would have to first at the top import not this one but import it's not a wrong next link and lots of Link components so import link from next link and instead of traditional ahref we're gonna wrap this into link href so let's turn this button and this would be so we are already inside search so search results okay and now if we so let's for example select three guess and set the date for August if we press search we go to search results but this page is already open um so it covers up the page but we can see that if we examine this URL got updated right and then we have results page oh what I think I named it my results or results page yep results page uh in here and also if we open up the state of this search component that's part of the layout retained right data in the Json format inside our app folder and name of the file is listing stated that Json um you can create your own array if you want to or if you want to use this one exactly I'm going to include a link to the gist in the description so you can just grab this file or if you just want to continue from this point like all the code that we have you can check out the GitHub repo that's also going to be in the description and the name of the brand for this section of so far what we've done is 1.1 header routing so what we're doing in this part of the tutorial is we are fetching the data from an API so we have to create an API fetch the data and we're doing server side rendering so fetching the data on the server side in server compliance so first of all let's get started as I mentioned we have to create an API to fetch the data and that would happen the API folder usually in the previous versions in the source we had a sample API folder I don't see one in here but we can create it here we can create another folder for different use cases that's the file not the folder search and now the file which would be route.js so in here we need to import next response because we're going to take this data from this file and then return it as a API response so that would be next response from next server this is an asynchronous function so export async function and the type of this is get because we just return the data and the parameters can be retype script so we don't need to indicate type and we return next response dot Json passing listings data route which is API and search we should get back the data and here it is our Json now how do we fetch this from our component so this would be on the server component and depending on where we need this data so this is just general like all results so let's do it on my page which is on search and Page we can turn our page into an async function so we do that by writing async function page and then constant result equals a weight Fetch and since this is coming from API we don't need to pass the whole route just the route of our like inner based on our inner file structure and constant data equals to once again a weight result dot Json now we can um take this wrap so Theta dot map so listing and we can display like listing ID and then key also to mark that their unique paragraphs um here fill to parse API search if we have to indicate localhost as well so I'm gonna try that but previously we're not used to make API calls okay so this is coming in now so we have like six results um let's start creating a listing card so we can better display this data coming from um the server so this is the server component right and then we can either display that inside server component but if you want to add interactivity for example when a listing is coming in we want to users be able to favorite it or review it something like that then we need client components um the ones that we Mark with you use client so from page we're going to do rendering patching on page but then we're gonna pass this data using props to the client components inside components new file info card we mark this using use client import will need use a state for updates of the state whether it is favorited or not the listing so that's from react and we're also going to use heart icon and the start icon for the buttons so art icon so there will be two heart icons one would be when it's not filled one would be when it is filled uh so you need to import both of them but since they have the same names and they're coming from like different uh packages we would have to rename that and I'll show you guys how that's that so this is personal if you really like that we're gonna get in there and heart icon as field heart icon this is how you rename your X Imports next up is star icon this and that's it so in our functional component info card we get listing as props and then we can start displaying it so first we create a parent div and then inside here at the top we wanna show like the image so I'm gonna create new image with the image tag and so you may be wondering why I'm not using a Nexus image it does have an image component which you can import using this command and for local images good thing and new about the 13 version is that it automatically calculates the width and the height so you don't have to provide it anymore because it has access to it but if it is remote images you do have to provide with and the high which is harder when you are creating like Dynamic cards and you also don't know like ever that every image is of the same size that's why I'm using the source but if you like you can it would be the same code if you switch it up and use an x.js image okay so after that um at the top we wanna have image then we have this section for the other information let's add some padding to have a distance between image and that information and first part we're gonna do where we have like a title and then the description so I'm going to use heading 3 and this is where listing name goes and after we can have um this thing grading so star icon let's set the height and width to five text yellow 500. [Music] listing the rating okay after this let's do description followed by a button that's gonna show heart icon we'll do the button clicking logic and um the heart icon conditional display afterwards what else do we have I think that should be it export default info card and inside results we can create a new component that's gonna display all the that's gonna take in the data as the props and then it will using info card display it so new file results list that jsx and sport constant so let's take in data here and let's import card return and purely displayed First Data dot map listing and every time we um map the data out we have to pass the key which has to be unique so that would be a listing that ID experts info card okay so this results list we go to page and wherever we have this data mapped out and we'll replace it with the info card okay let's remove this and theta equals to okay here it is coming in here and taking a look in full card it's not defined so probably export default import it in um so it's oh I haven't saved it okay here's our okay uh listings with the images and uh let's just The Styling now so first heart of the star it shouldn't be oh interesting I did say it okay create this as a grid first so you can create great Elements by just adding grid and then defining what kind of conditions you want so on columns I want um on the smaller screen so by default we pass what happens on the mobile and then or on larger screens we want columns three as well as Gap between them and merging top just four so that on the the screen it's here on on larger screen it looks like this and let's also to observe changes of at least one component I'm gonna set aside like this starting with the the info card now parent container maximum width medium then we wanted to be centered let's also add some Shadow and rounded large well overflow is hidden and yeah we do get this around the corners with some shadow in it afterwards where's our yeah images here so width we want to set to full height let's do 40 it object cover transition transform so when somebody like hovers over we wanna increase the image so for that transition animation we are setting the duration now it's form so for the hour then we set condition scale and then let's do 100 so extra like 10 percent and yeah this is the effect looks nice now let's move on to the listing information let's stretch this out on this side so making it Flex items Center then we have justify between that's gonna move them side to side and margin bottom one two two so yeah now let's work on this piece we also want that to be on side by side Works items Center perfect uh update maybe H3 headers by default in a Tailwind don't have any styling so let's make it look more pop first increasing the text size then font let's set to semi bold margin bottom two and star icon text yellow great then maybe add some margin to the right side Ah that's too much okay I'm gonna modify the color of this text create 100 so it's a little bit less um this would be text Gray 600 margin bottom four and heart icon right now it's we're not seeing it anywhere and let's make it absolute in regards to this card that we have so I'm gonna make the card relative and set the position of the absolute which is going to be bottom right corner so bottom for right four some heading and minus C minus 30 set the say index so we height and text primary so it is of color pink now let's create this state to handle this clicking the heart so that would be constant is or is not the listing Fiverr favorite that determines it so his favorite set is favorite that equals to use state by defaults false and then the function to handle that toggle so constant handle favorite update that equals to we just take the state previous is favorite and then set to opposite of that I'm gonna copy this function and in the button that we have here going to pass it as on click is favorite otherwise just display this one yep and later on we're gonna add animation so this like transition and clicking on favorite we have um lit more animated More smooth smoother and it gives incentive the user to intro interact with it this is our next challenge and that would be to implement the search functionality but in order for us to be able to search our results and filter them out we need to somehow pass that information from the search to the results see where we can do that one way is as I mentioned we can lift the state up but that is the tricky part because the their parent component is a server component and what we can't do is server component is either use context API from react we are not able to do that or add the state but the both of them these two have a state because their client components but let's try it out let's see if we get an error so I'm gonna do import use state free to constant some sample say let's say search now let's save it and reload see we got the error that we are importing a component that needs you state and it only works with client component and same would be the case which I tried earlier by myself is I created context and then I try to import it and yeah and solution to this would be to use a state management Library you probably heard of Redux and Zoo stand those are the two that are most popular ones and in this tutorial we're gonna use a stand we first need to add this only like one package is needed and going to terminal I'm pasting that oh I don't need the comments npm install Sue stand let's hit enter and while that is installing this is a sample for creating a store we can copy it and then modify it based on our needs so for the store I'm gonna create in the root you can also create like a new if it's more uh complicated I don't store new file folder for it and this is so the way it works is it uses this create hook coming from this is that we passed the set function and then this is um what's inside the store so we have just a beers count uh two zeros that's the initial State then we have this increased population function and then remove all beers so if we save this and for example call it from the layout which I'll open to the right side so we first import and need to export to be able to import let's save it and we're inside layout that's in search so that would be the door and if we say we update the state so use bear store we can use these functions but um let's see how we can update without the functions if we don't have equator we can say set State and then update appears up and that's how simple it is to just create disturb and being able to access it from the other so if we reload this we're not getting error so that works now let's remove this from here and actually update to the store for so that it does like search so search and then if we look at our search we have like three components so first one it's gonna be location [Music] or the search input so that's empty then we have dates this is going to be an array and I'm going to add new date new date by default so we have guessed this this would be count so zero now what we can do is instead of increased population increase guests and that would be guess we do already have inside the state access to the guests so guests plus one and we can also do the same to decrease guess and filters and this is where it's good so that we don't have to redefine this again we can do is create initial say called constant initial state that equals to copy this and here we can do the structuring of and same thing in here we're gonna set it back to it now let's update the search so it uses uh the store that we just created and updates that and then we'll see how we can access the store from search results and filter the data so first going to search bar that would be here and let's see where we have so this counter right here we can access the counter and it has a state of its own and we don't need the State anymore instead we'll import uh user store at the top and this is how we access specifically like we don't need every element of the store right we just need the gas count so that would be in inside the counter constant count equals to and then we have use search store that takes in the state and Returns the cast state for us and the same goes for like the functions that is how we can access the function so if we say increase count oh the name is increase guests but inside our component we can name it whatever we want so I'm Gonna Leave the count as is so in here we don't have to access this day we can just pass the function so this would be actually this is increase and [Music] decrease also the count itself so count we already renamed it and this is it so we don't have to update anything in here let's save this and just test it out okay it works the same great constant search input and let's do this state paid the location actually we can name this one as a location input so it's more clear what it's for and let's write a function that's gonna handle the updates or constant handle application update so this is an input element so we need the event handler for that one and it takes in an event and then the way we can access the value is event.target.value so and we'll update this day we can update by using like this uh directly so that would be use search store and we can also check if this will reset the other states but yep let's try it location and location would be set to event the target that value and where we are calling this from is inside our put on change props and pass our function and we also need to set the value and that should be equal to location so we're able once we update the location as they were able to see the changes now let's test that out I'm gonna spend this and now this turn into input and let's do Paris and let's see if we update I guess to five and then if we update this state again if this state remains yeah so it only updates the this set state that I used here only of this location piece of it and not the other two and one more remaining is our date so instead of selection range oh okay I see what's going on so start date we do need the key selection which we don't have it here but we can instead of start date and end date we can use those two dates and that would be from here to do something like this and this would be dates the first element and then this would be the second date we can remove this too and we have to update the handle select because instead of set start date this is going to be using this one and instead of check and setting them separately because we don't have the State anymore we can instead do this so dates create a new array and then pass ranges that selection that start date as the first element and ranges selection and date as a second element all right and I'm gonna remove this code that's it we don't need to update anything in here because we're already passing selection range and since we updated start date and end date it should take it in so only thing is that location input or instead of location you probably put in location here so let's update the value for that and test our changes out ranges okay let's do this and this and yeah it's remained perfect now the issue with our search is that this is the expanded search and there is no way to close this out and to indicate that this is expanded we need like a model kind of like Airbnb has when um the rest of the page is darkened out so let's fix that uh let's first add the model and then add the option that if user clicks away it's gonna close so we are gonna go to the header where our Logic for expansion is so here we have hooks and all that and we'll add model here so model would be one layer over the rest of the page and it will only appear when uh the search is expanded so let's create classes for model model classes and once again using as clsx so we want this to set to Absolute then we'll have from the top it would be zero same thing from left as well we want this to take the full like width and height as for the Z index so we want the header to shop first then the model then the rest of the page so it should be less than that of header let's see how much header has and it does not have any okay so we can set this to a high number for example 50. and we can set this one to 10. so background would be black but it's not going to be um before back because we're gonna set opacity to somewhat lower so we are actually able to see the page and we also want this when it changes to have some like transition effect so transition opacity is the something that we want to transition on and duration 300 is in and out the style of transition and we'll add if hidden it's not going to show up if it's not is expanded and it would be display block if it's expanded also we want to slowly set the opacity same thing for this in here and opacity 100 that would be for now we can place a this model outside our header since it's the position is absolute it does not like the placement would not determine where it's actually placed on the HTML and for class name we pass model classes and here we have uh it's layering over the search page as we wanted only thing is that I think the the index of the hearts are higher so let's quickly fix that they're popping out so let's see let's say 30 and then oh interesting note so this is definitely higher because we set this to 50 so it should be search bar oh this one is 10. okay so we can set this to 40 then maybe perfect user has clicked away from the search we can use this package and it comes with a function uh it's called use click array it's a hook and inside the function we pass what we want to happen when user has clicked the way so let's first install the module it's called as I mentioned react use and to indicate on which element we want it to focus on we have to create like a reference so that would be use ref and this below where we Define our states we can create a new reference constant ref equals to use ref and by default this is null but then we go to go down to our element and pass the ref so that would happen to the header and because it's our Target element so ref very cools wrap and going back at the top we need to also import the function use click away from react and let's define what happens when use click away triggers first we need to pass the ref so it knows which element we're talking about then we pass in the Callback function and in here if it's clicked away so for example if header is expanded then we need to we want to close it so we'll set set expand set is expanded to false Let's test it out so I'm gonna click here reload open close and yeah it got closed when I clicked clean up the styling a bit in the header I have updated this Airbnb logo also the user logo with um svgs and this is inside public images folder and from the header we can just uh re indicate them using bypassing source to the image and once again this images and assets will be provided will be part of the repository on the GitHub and the link is in the description of the video so what I did is at the top I imported next image and using it I passed in The Source on the first where we had this here we had text instead before then I passed height and width and ALT text and afterwards inside user once again here we had just the user text and I updated I said the color so it inherits this color I also set flex and item Center so put this icon here was centered and yes I said the same within height synthesis a insert Perfect Circle and indicated the path to the SVG this acts of different file forms it could be SVG PNG or jpeg now what if we wanted to dynamically redirect towards the page so previously we looked at how to create links but what if not only we want to navigate to the link but we also want that certain button or link to do something else as well then we need to kind of dynamically call it inside the function and that could be done using use router hook and we're going to use user hook on this search button right here so let's go to the search bar first at the top will import the hook from next navigation and we need to create a router that references to use relative and let's see do we have a function okay so this is just a link and if we go we do get go to search results page but we also want to close this out right so instead of Link I'm going to turn this into a button and I'm gonna add an on click that says handle search click I have not yet created the function but I'm gonna do that next okay router that push and we also need to set the expanded to false but the issue is that our parent component header has the set expanded so what we're gonna do is we're gonna pass a function to toggle expanded to our search bar so it's here and copy let's uh not just I just needed the name all right and we're gonna call that from here let's save it click search and we do get an error toggle is when the expanded is not a function um I have not pressed saved on this one okay results page and close that let's try it one more time open this press search here it is it's closed and it redirected us so if we take this because this includes the list of results as well as like the filtering and fetching the data only thing we would have to update is this is the page itself for results this is already inside the same folder so now we if we go to let's say here we get to same pages I can see it didn't reload because it was um already cached but now what we can add on just the search page is for example before we display results we can also display things like categories Etc but we can add here for example a button and I'm gonna set this to flex item Center it would serve just like a hero section that websites usually have and we want the width of this to be screen I don't have that yeah background cover 24 so we are able to see the image and then I'm gonna add background image URL to this images folder and the name of the file so let's save this go to the bridge okay so we're able to see the image and let's make it bigger so it looks nicer 48 I don't know if that's gonna be too big okay that's not bad now maybe we'll pick a color for the button so text we want white so we have contrast rounded large I already set it um background color let's make it Pink 700 okay padding X4 padding y two but I sometimes use this color pickle I I drop her so maybe if we pick a color from here that might look nicer we can check if not this doesn't look bad so for custom colors this is what we do okay I can turn it up and we can add on Hover make it lighter so background maybe something a little further away this color very much reminds me of bootstrap color I think that's what they had it set as a default so yeah it gets updated on Hover and let's try to see if rounded we have large full looks better yep it goes more along with um airbnb's like love of running clock corners have this button to search results page and we can set this as a flex gross so it stretches all the way out so in both cases here I'm gonna add I believe it's Flex grow or either just like grow parent that needs yeah the bottom itself yep that looks a little bit better maybe we need padding also on this side so what if we make all sides too yep that's way better this to the top when this is expanded and the reason it's in Center is because we had set it a flex items to item Center but what we can do is also make this conditional so constant user icon classes I'm gonna paste them in here and we will have an object that's gonna have this so first is not expanded and I noticed this too shouldn't be should also be like oops string anyways save it EMS Center oh I have not applied it okay let's see yep it remains at the top it's truly fascinating to see how many animations go into building a simple interaction like this one but of course it's very like crucial for example for like this certain functionality for Airbnb and I even have a video here like a slow motion and as you can see the surge kind of like first expands it out and this like simpler version disappears and then when we are closing it this goes like Edwards goes up and becomes smaller and we are presented with the simpler version of the search and there's yeah there's small a lot of animations going on but it may look very complex you just have to trust me that it's not and I'll show you guys how to do that right now for the animations we can use this Library it's called framer motion and it makes creating different kinds of animations very simple so for example this one right here where the square shows up and this is how we can see it's done uh just like any div is turned or for example paragraphs pen you can turn into a motion element by adding that motion in front of it and then we can indicate initial stay which is when page when it initially appears and then we can pass another state which is what happens on the animate which is it rotates 180 and it also appears at first its scale is zero so it's not visible and then transition is what kind of Animation while it transitions from initial to animate we want it to happen and in this case we we press type there's a different kinds of types and stiffness damping Etc there's also a lot of um other variants that you can use to modify to your liking but let's start using this one first we can install uh as I mentioned it's a library so I'm going to copy npm install framer motion go back to our project and inside here I'll paste that in and the first element we're going to use this one is going to be actually here uh the header and we want to animate this right here so copy this first what we can do to animate is we can Define variant so let's take a look at what variants are so this is the animation and this is where we have variants defined it's basically you are passing different states but you're creating like a separate object so if you have like a lot of this you can also pass it in inside here but this is more readable and it's easier to find and updated so here the they have two states he didn't invisible and for us let's also we're gonna have three states first is going to be initial so let's define that now constant search container variance that equals to so initial hidden and enter on the initial opacity is going to be 1 height is Auto Y is 0 and scale is one so initially this search the one we have right here is shows up so that's why we have scale opacity one and it's positioned in its natural position but when it's turned into hidden which will do it like manually as in that on the page load or anything it disappears so opacity goes to zero height also goes to zero otherwise it'll take up the space in the Dom Y is 100 because it's also while it's disappearing it's getting pushed up and scale through because it's expanding it's it's being pushed down and it's also expanding so that it's going to turn into a more advanced search and the enter enter is going to be same as this one okay so how do we apply those variants we have to go to wherever button and how do we turn this into a motion first let's import motion from framer motion also besides this video if you want to learn more about framework motion I have or practice it I have another video where I create more like a landing page website so you guys can check that out and so turn this into a motion button yep that's it now we can stay past initial state so this is where we pass the name of initially what happens and this is coming from here so if we named it something else then we would pass that initially it could be hidden it could be um like whatever you name it and animate okay so animate is conditional because if it is expanded if the header is expanded then we want this to be hidden so animation will be heated and if it's not then we just set it to initial and on exit like when it's exiting out like disappearing and exit then we can also pass make this more extended so we have exit and then we have what kind of transition do we want this passing transition is um optional we don't have to but let's see how what type we can use I'm gonna do linear let's save it so once again initially animations kick in when it's either expanded or closed on exit transition and yeah that's it let's check it out I also noticed that when the animation previously was getting back to its initial State something was causing it to look a little bit off so I realized it was coming from maybe the new version of framer motion because when I installed it installed the 16 but I was previously using 14 hopefully by the time you're installing this they have in the newer versions they have that fixed but if it's also showing up for you and it's behaving weirdly you can downgrade to this version or any other packages that you want to check that you have same versions as I have you can always check the GitHub link for that and now going back to our header let's add animations for the search bar so the animations for this one is going to be kind of like opposite because when the first search opposite of the first search when the first one disappears this kind of like appears and we can Define three states initially it's hidden then it enters then on that expanded anymore it exits and we can also copy this and like kind of revert it starting off with opacity zero then we have height zero so y would be minus 100 and scale is zero now for the enter this is one this is Auto zero and one lesson for the exit height zero okay so this one we can have it same as the hidden which is initial and let's see where the parent okay we can wrap because this is the component so we can't say motion that search brush but we can create like addition D we can place it inside and make sure it shows up properly in this new D Flex column justify Center then we passing variance type variance so initial state is hidden animate is expanded then we it enters it otherwise initial and let's also do Transition same type as we have for the other one okay and and we can wrap this into container together and make it like Flex gross so it takes up the space um in the header there will be Flags Flex column and then grow and that would include the button as well pick this uh spreading the full width but other than that I think the rest looks good that would be inside the search container classes that's the button so with we can set to Auto and then self Center great you have the option for users to update uh the values of search and store them but this like the labels itself are placeholders so let's update and when user for example puts in the value this should also get updated and going to the header I think that is in search bar so location input we will check in here if there's an input if not then we will return like the default placeholder this doesn't equal to empty string then we display that otherwise what was the search destinations okay and then yeah it still says that next we have the select ranges that we want to update so this would be let's see what we have by default I guess because by default we already do have dates they are not empty right we can check that inside the search store oh not the state so yeah it's current date but we can update we can reset the name so for example if user presses handle select date selection you can say label use State and by default this is going to be select ranges once user interacts with this like range is selector then we're going to update our local state and uh put it as the first date and from the second date update this in here date okay so it it does update but it gives us this like the long expression so we can change this to a human readable thing function to date string because this this two are of type of date so we can use this function on them let's copy do the same in here and I select two date string is today oh not that's Ring the date string sorry about that okay yeah that looks better guests so this should update as well so we do have a counter that has inside like the access to the guest store but we also need that um inside the header inside the search bar like the parent of the counters the counter is the job down here because the label is in here at guess so yeah that should be a pretty simple change we get the count we already have the use source so we just access it and let's copy this so if count is more than zero we're gonna display I'm gonna return count if not add guests and close this out Let's test it out who three and then let's do count the number and the guess so that would be guests yep that looks great I think we're gonna work on is how we display the search items on the mobile and let's see how Airbnb has the mobile menu so as you can see at the top it has this component that kind of looks like a search input but indeed when you press it it's a button that opens up a model and this model has three components for three different filters first one is automatically selected and it's open but each of this single components are collapse um cards when when they're or like kind of like art accordions when they're clicked uh only one gets selected and expanded so inside each single one there's a different content and at the end it has um clear all to clear the filters and search button so let's replicate uh that make something similar for that one we're gonna first need to create a mobile navigation like a separate component that we will import into our header so let's create a component and let's import that so inside search components new file mobile nav so for now I'll create a very simple component and display it only on mobile that's the first functionality we're gonna do so export mobile default export default default export default mobile now let's import it into the header and we will add this below here what we have to do is also make sure that on smaller screens the actual menu that we use for desk desktop is hidden and we can do that using the hidden class so let's do this add this query from Tailwind so on hidden or by default will be hidden and then on medium screens the display would be Flex and let's do the same for this Airbnb or the logo and we can close these two out as for the Mogul mobile now let's wrap this into another class and in here in the class name we'll have on the medium other way around it would be heated and if not the by default it would be Flex grow let's place that inside and check so on the mobile we're not seeing the menu anymore we see the text mobile navigation put like button that opens up a model when clicked so for the model we're once again going to use Daisy UI so I'm gonna copy the label here go to our mobile navigation and start creating the element so in here I will remove this text and create a main parent component let's add a margin at the top set it to two and then we will add a label inside the label we are not going to say open model but we'll add more components like magnifying glass and the this text which is from Airbnb anywhere any week at gas so for the magnifying glass let's import that from the hero icons I misspelled this one and let's add a class name for width and height and also for the color so this will set it to five and then color text Gray 400 as for the our text we'll create a new div so first at the top we're gonna have head H2 and it says anywhere then we have the two for the class name let's make this flex and flex row would be the direction so first span is any week and then we have another spine that shows the dot and finally add gas okay and let's add a dot in between any week and add guest so save this we get an error because magnifying glass icon import was wrong so once fixing that um should be correct now let's update the stylings of the button so in mobile now changing class to class name and adding styling setting the width to full we're going to set display to flex direction would be row text we want to be aligned left adding some border radius padding centering it adding gaps and also we want to have a border with a drop shadow let's save this and this is the result and now we can move on to updating the content inside this button so magnifying glass icon that we already have styles for that let's change anywhere uh like that sort of serves like a label so we gonna make it in font size bigger than the rest as well as for the Bold so it would be fun semi bold and text would be of size medium and for the rest inside this Flex we're gonna also um Assa set the text color gray 500 so for all of them so that we don't have to do it separately we're going to do it to the parent container and let's add some margins on the right so span class name margin right dash 2 and we will copy this class name paste it on all of this uh three instances in here and save it so that got updated now what we want to do is adds a little bit of padding on the horizontally on the parent container so that looks better for the model we're going to once again use the Z UI and here I am on their documentation page where they have a sample code for the model which I'm gonna copy it and paste inside our mobile nav component I'm just going to add a comment for where we're going to start the model logic and we will that paste the command we have to make sure the ID for and the label matches each other otherwise if we click here it will not open but we do see a model with a sample code inside here and let's update the close add the close button with an icon for the icon I'm gonna once again import with the same package solid one it's called x mark icon so and copying the name here we're gonna go and display that at the end of the model so wherever it says close we can update that with our icon and Pla pass the class names to the icon so that it um shows up we need to set the height width and the color so and instead of class this should be class name because we copied HTML that's why we have to change all the classes to class names anyway I will replace this model backdrop with absolute I want to position it absolute to the model on the right top corner so right settings zero top setting zero as well but the margin from the top would be four and the right would be four and let's add the class button close that's from like the daisy UI example as for the icon class name setting the same classes we can copy from what we have for magnifying class icon and uh the text Square you can fix this should be Dash 400. now this will get updated as well as copy and place it for this one maybe try moving this inside the model box that way it my job yep here it is and if we press this it should close the model let's create an array of all the filters search filters that we want to have displayed and later on we're going to create a separate component for collapse card so we can reuse among these different filters so we will start with naming mobile menu and this would at first Simply Be array with labels where and let's this will be an array and it will contain objects with labels and we will add content in this object as well first we have a where then it's when and question mark finally we have whom and I am going to create another TV in here where we can map this menu so Dave and add some margin at the top of it to make sure that it doesn't overlap this button that we have here so this would be margin top let's do six because button is of width and Heights of five and we can map this out item and index and we can display item that label so that shows up and then let's add the footer at the bottom that would be for the clear all and the search new div tag class name we'll name this model folder and inside let's create another class for the footer content model footer content will create a new div for clear all and another one this one is going to be a button for search okay now let's make this to spread out and style them for that I will turn this into a Plex um container and add some padding around it justify between items Center and width is full perfect for this one I'm just gonna add an underline and so this is one cool thing I have the extension installed for Tailwind which lets me if you're new to Tailwind you can hover over the classes and it will show you what is like the CSS equivalent of it so that's a great way of like learning tailwind and success for this I just like named it but Flags we can inspect all of them all the utility classes and let's move on to the our button now class name I'm gonna set background to primary then we have some paddings on the side we want it to be rounded let's set rounded medium text should be white and margin or on the right side too we also are going to add a magnetic fine glass in here so let's turn this so we'll have two elements flex and then justify Center items would be Center and we already have a magnifying glass imported so we'll place it before search but let's first put a wrap search inside a spad place it in here one thing that I'm going to change is text make it white the same color as the search text and this pattern got updated I will also remove we'll remove this header and extra paragraph that was just from the sample code from their documentation and for the collapse card we are going to go to components create new file name it collapse card and this would be a reusable card that's gonna take in a children that would go inside when the card is or recording is like expanded we can also say is current we can because we can only have one card expanded at a time and a title so after that we can have a return and write so I'm HTML where we first wrap this in the div then we give um like a header to it so that would be class name collapse card header and here goes the title let's put this into an H2 okay and then here we're gonna have class collapse cards body at first let's display by uh default and children so how do we pass this children in the collapse card that is very simple and I'm gonna sure enough first let's import collapse card though I haven't exported export default collapse card and import that one from they're in the same folder and here instead of mapping the labels we can say collapse card but we pass this one as a title so it's props taking a title that would be title equals to item that label and then inside here this is how we pass the children for example first I'm just gonna say children and create this element um let's go here and refresh maybe yep so here we have the title first and then the children now let's add The Styling so we can modify this and show accordingly so going to close this one first and let's Import Sales CX at the top because we're gonna need some of the conditional styling here first we are gonna Target our selling for like the main collapse card and starting that naming it collapse card classes equals clcx so first collapse card just for naming purposes background would be white then we have rounded LG large add some shadow padding and margin then we have this condition where if you can see in here the shadow is larger on like the mode uh Open classic open tabs so we're gonna say shadow large if it's not current So currently selected otherwise Shadow to excel and that would be for collapse card classes let's pass it on so here we have by default none of them is the current let's update some styling for the the title that we have here and collapse card title classes text we can set size to medium [Music] font will make it semi bold and text Gray 600 S4 let's add some margin at the bottom and if it's selected let's make it uh the text bigger and pop like more bold than for the other ones next Gray 600 if it's not current 800 text Excel and pass that on and we need to keep track of what is um currently set and what's not that we can do by creating a new state and that would be import use state from react and constant current tab set current tab that equals to use state by default the first one is selected and let's inside this collapse card we can say we need to pass is current that would be if current tab equals equals to index so that will set our first one that should set our first one as the current yeah you can see the difference between first and the other ones um okay so one thing Shadow follow me remove this okay now we have a darker Shadow maybe let's do excel too Excel is too big okay yeah that's better as for the children we have to show the conditionally so if is current so let's do this otherwise no so we only see the children of the first one that is selected now now we need to update when we click on the element on which gets like opened and get set as a current so since the logic for current state is inside mobile nav here we can create a function and then pass that function to the collapse care cards so constant handle current update this take in um the new tab index and we'll just return set curve rent tap to that tab index and copying this one I'm pasting it to the collapse card update Tab and we will also create this props inside the collapse card update tab handle current time update save this and in the destructuring here we're gonna add this update tab okay so now for us to trigger the function we can turn div into a button but then once the card is open right in that case we might have inner filters in here so for example if this whole container is a button we won't be able to use this inside a separate button so once it's close once it's open we just wanted the parent container to be just a regular div once it's not then this right here should be button hopefully that makes sense if not I'm just going to code it up right now and um that would be more clear so if it's not current then we can return and this would be button and technically we can pass the same thing we can remove this children action and what we also need is to get the index so when we call this function we can pass the index update Tab and in here key is also index because we have to identify that these are unique and index when we're mapping out things so button and here on click and callback function and this would be update tab while passing index save it I'm interesting either show up as a button it did change the because we have the styling on the div not the button so it looks different okay let me remove this fragment frag fragment so collapse card classes with full great let's update also the text to be on the left side and that would be in collapse cards classes it's text left and and now we can start adding like the children it's all for the filters and first one we're gonna have an input box here and it would be similar to how we have on uh without like the mobile but just the styling would be different otherwise it will update the same state um and for components we can create a new folder name it mobile and inside here we can create a new file I'm going to name this this t input the J and we don't need this one destination input that equals to that equals to last name let's do destination input and before we add any Styles let's just like display the content and see how we can like dynamically displayed the children for each of these filters so span I'm gonna add mag magnifying plus icon so for this one we need to add some styling because otherwise if we don't add width and height it's not gonna show up and let's do text grape 400 and outside of this span we can add input type equals text and Export default destination input so if we go to our mobile navigation here we we can import this component and save it but if we just update and place it here then it means that it would show up for every single one of them but what we can do instead is we can add another field that says content and we not only can pass like primitive values primitivity which is string integer Etc in inside the values but we can pass like the component itself so I'm gonna do destination input and now we can update the same way we're using dynamically like the item.label we can use item that item that content is that it would show up only for a this one because the other ones don't have that value empty for now until we add um their components well let's go back to destination input now and update The Styling so starting off with the main container we're gonna do background white so we added some board intermediate flags and Border radius now let's update input okay adding some background color so it's transparent and rounded would be full outline man uh one thing is their alignment it should be side by side I realized that the class names and styles are not showing up because I misspelled this here so and let's update that and that's great so what we can do is we can use the same functions that the other the desktop version of the header has to Once user starts typing in here to update um the value for for example location and dates and the number of guests and also for maybe like the date picker we can wrap that into a separate component and reuse that component across the mobile and the desktop so I'm gonna do that right now and afterwards update the search function as well so what we did here is we passed the value of already State search or did the state inside the store and also the function to update the store only for the location I assume my import is one more loved because I just copied it from here so if we start updating this should update the state because if we close this out return here here we should still see the Germany now let's move on to the date picker and display that here foreign is we extracted out the logic that we need to display the date range picker and also all the according functions since this is kind of like reusing some of the logic copying some of it but also applying to the specific need so you can create reusable components I would say that you should try to do this yourself and then if you can figure it out like to learn and practice it come back and like watch it and same thing for like the third content that we're gonna add but first let's see um once we have that uh test it out so use state is not defined because we need to import that as well okay and now we can see the calendar only thing is that it does not fit the screen um you can look into how we can update so maybe we only get the Picker not this in here let's take a look going towards the react date range documentation we can say that there's different options on how this calendars to be displayed so the one we're using on desk desktop is the full view but there are others like separated for example this one multiple range uh inserting are your labels and just the date range so this is probably what we need without like this defined range um because of the space so let's um copy this date range use that one instead and I'm gonna update this hopefully its props are similar if not we can check how we are able to update that in the page we only see the date range and let's update and remove the user icon on smaller screens because it's stretching out our width of our application so we can add the same logic as we have for the Airbnb logo so it will be hidden by default and then on larger screens display would be flags and that's going to go inside this user icon classes and if we command click it will take us there and we would add that extra logic in here removing the flex and now we reload we don't see that icon anymore let's also fix this little bit like overflow and on the info cards we had set the maximum maximum width which is medium but we'll set this only for larger screens on smaller screens it's kind of resets and fits into the screen like with as in here it shows on the screen no cards are overflowing great now we can also update the margin of the card so the heart icon is not overflowing the text and here we have a little bit more space and next thing we can do is we have left to add a Content inside who and that would be the counter since we created a reusable component for counter here in the search bar we're gonna grab that so let's copy that and navigate back to our mobile menu so let's put this on the side here so we can see and once again command Click mobile now that would open our component and the file and on top here we're gonna import the counter so I think it is default import so it's other way around not default so curly braces import counter from and we are inside components folder so we directly say counter and in content here um on the third item in the array we add that in let's save it and check it out yeah it's here and if we test it it gets updated now I have used um store file open to the site and inside mobile nav I'm gonna import use search store so that we can use remove all filters function on clear all link that we have inside the mobile menu so let's import use search store and it's coming from the store then we create a function remove all filters and this would equal to use search Source we access the state and then State function State removal filters as you can see on the right side inside the file and we take this function and go find where our clear all is here it is we have a div but let's turn this into a button and pass on click the function now I'm going to save this can't resolve I think the import statement of the stories incorrect were missing one more folder back and now we have that let's update to the state and test it out so if I type in something here and I will show up clear all was there initial State um I think yeah it's spelled wrong that's why it says I'm just gonna copy and paste save it uh let's try one more time Germany clear all and now state gets reset now we will Implement animations when user Hearts the listing and for that we're gonna use use animate function from framework motion that function can be scoped to elements like list items Steve SVG Etc and can be used for more complex use cases like animation sequencing and it gets cleaned up after element is removed so first to use that let's import motion and use animate from frame of motion inside our info card prong primer motion and then we create also we would need to create a use effect hook so I'm gonna import that from react as well and the next step would be to create a scope and the function animate and that would equal to coming from use animate hook scope would be the scope of what we are animating and then anime function would be what we would call when we want that to happen so this use effect would be only triggered when is favorite state changes so that means when usual either clicks the heart or clicks again to undo the favorite so let's add the timeout ID we're going to use that later but to add the logic so if is favorited then we want an animation and we're going to Target this on SVG because our heart is SVG and this would be scale 0 from 1 so the field heart icon that we have is going to go from being non-visible to having a scale of one and then the next thing we can Define is the duration so how long does it take to do that and that we can create a separate object duration and pass or I'm going to pass 0.5 which is five seconds and the type of the animation that is going to be the spring so then there's another use case where um user the favorites it so we can Define that inside our else statement and we can copy the animate just change its logic so from scale it's going to be already one we're gonna go from one to zero and save that one next thing would be defining the scope so wherever we have this filled heart icon I'm gonna remove this conditional rendering because if we do have conditional rendering we're not going to be able to see this animation so let's first create a separate span for heart icon and place it in here and after that one we are going to create a separate div that we will pass our scope to for the animation so div ref equals scope and then we can also create a class name same as the other button has only thing is we can update the same text so the pattern remains clickable and inside here we wanna pass this field heart that's gonna actually have this animation of scaling and like descaling let's close that one and by default set the skill to zero save it so if we click it slowly grows and then it becomes smaller and disappears so another animation that we're gonna do is this confetti effect and react reverse is a perfect package we can use for that they have different reward animations that you can add and we are going to copy the install command and paste it inside our terminal once that's loaded here in this code sandbox there's different kind of props it's taking so you can tweak some of them and understand what how it changes the animation and test it out right there so it's very simple for example we increase star velocity and it goes like faster in the beginning then we have DK let's see what that does yeah and I'm going back to our info card where we're gonna be also using that I'm gonna import use reword that would be the hooks from react Rewards and I'm going to paste the reward configurations that I had to Define but you can always change them so here we create constant reward and is animating is a state that tells us if the animation is in process or not and we call this use reward hook so what we want is this animation to triggered after our um first animation is done and also we want this only on the listing that user is clicking on so that's why in the first argument inside this user word we are passing reward and listing ID so we want it unique to the listing we don't want every listing to get animated that animation type confetti they also have balloon I think emojis and finally the third argument is reward configs that I just defined on line nine next thing uh we do is the logic of this and when is it triggered so duration of our first animation as we have is 0.5 right so we can delay the trigger of the reward and we can do that using set timeout so timeout ID that would equal to set timeout then I'm going to call reward function and passing 5 500 so that would be 500 milliseconds later um trigger this but when we're doing set timeout inside use a fact we have to like clean it up when I guess component is not mounted anymore so that would mean returning this function a clear timeout so that should reset our timeout um so and passing timeout ID and the next thing would be uh passing which um ref like which element we want this uh to be positioned at so we have span on top of heart icon so we're going to say ID equals to and the unique ID that we passed to use reverse so I'm just gonna copy this from here and capaciting the span so let's see if this and we got the confetti animation when the heart that we're targeting icon gets filled let's go over one more time what we built which was the search functionality with three different types of filters created Pages we built server as well as client components with data fetching and the mobile responsive design that would be all for this tutorial and if you enjoyed it please subscribe and look out for the next one I'll see you in there
Info
Channel: webdecoded
Views: 11,461
Rating: undefined out of 5
Keywords: build airbnb clone, airbnb clone tutorial, nextjs 13, nextjs tutorial, nextjs react
Id: 1kON7Q9MBak
Channel Id: undefined
Length: 183min 1sec (10981 seconds)
Published: Tue Jun 20 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.