Next.js and Django Fullstack Airbnb Clone - Part 6 - React, Tailwind, Django Rest Framework and more

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay since you now can see the detailed page for the properties I think it's time that to start to make it possible to book a property to keep track of the reservations or the bookings we need to create a database model for this so if you go to visual studio code open up the sidebar um and then we can find the back end project here and the folder property models do Pi so in the same file as property we can create a new model here close uh reservation pass in models. model and here I want one field for the ID and I want one reference up to the property so this is going to be a forign key property equals models forine key property uh we can set the related name to be reservations so it's easy to see all of the reservations belonging to one res uh sorry it's easy to see all the reservations belonging to one property which is this object and if you delete the property we can also just delete all of the reservations so on delete models. Cascade um I want one field to keep track of the start date when you're going into the house so start date equals models. date field and date so this is when you check out models. date field um how many nights number of nights this could just be calculated between this but it's easier to just have a field for this and just calculate it up front so models do integer field um yes like that um guests so that we know how many guests are coming here models. integer field as well and we can have a total price total price models dot float field that can be a float field yes um I want one more forine key to the uh user who created this so created by equals model. forign key user and this comes from the user account models user just like the one who like the landlord um related name can be set to related name can also be set to rest reservations so it's very easy to get all of the reservations for one specific user on delete models. Cascade because if a user deletes himself it's not necessary to keep the reservations in the database anymore last field I want here is a created at and this is a model. DAT time field so it's easy to keep track of when this was created and if you then PA in Auto now add equals true means that every time a reservation is created in the database Jango automatically fill this out for us so we don't have to think more about this save so now that we have the database fi for sorry the database table we need to update the database so if I just go to the command line where I have this running maybe I can make this work without any problems so if I just search in my history for make migrations then hopefully Docker compose EXA web python mentioned by make migrations is the command to run um there was no output there make mation is that not correct web one let me just check here it was maybe supposed to be backand web one instead okay so there were no output now either let me see if there was any migrations field filr migrations only the initial one yes so it has not been run yet okay so there is something weird because the changes are not detected okay I can see now that this has been created and maybe it also run the migrate automatically and let me just try to run this command again migrate not running okay I seem to have stopped this again okay so execute okay let's just assume that this is running so let's say tooker comos up again um okay so that means that hopefully now we have this database table in the database um we can try try to import it in here and add it to the admin interface and then we can log in there to see if this there so just go to slash admin so here I can see that there are a new property here or new Option called reservations which means that it is created at least so that means now we can finally continue so how to keep working the back end to make sure that everything there is working so I want to create a new API view or end point for book property so at the bottom of api. piy we create a new API View and here I only want to allow post requests and call this book property and pass in request and the primary key uh I want to have a try accept here just to make sure that everything is working and if there are any errors we just uh send an error back to the front end so accept exception as e and we can print the error here if we want to see it in the console e and then we can say return Json response pass in success and set the value to be false which means that in front end it's not easy to know if it uh went through or not and then here we can get the start date from the front end by saying start date equals request. post. getet start date that is to be default empty and we can do the same thing with end date oops end date and the number of nights number of nights and we can do the same thing with the total price and last but not least we want to do this with the number of guests so guests and when this is done we can get the uh property from the database the one that we refer to here up in the URL and then we can just say property equals property doobs get where primary key is primary key and for example if this fails it will raise a 404 error down here and we noted in front end that there is something wrong and now we can create the reservation object so we can first begin by importing the model reservation scroll down again down here reservation doob do create and we want to set the property oops property to be property the one that we have here we want to set the start date to start date end date to be end date the number of night to be number of nights the total price to be total price the guests should be guests and L but not least who created this so created by equals request. user so now we have the API and the point as well so we just need to add this into the url. P so it's reachable from the front end so we can make a copy of the detail and just keep this as it is and append at the end here book slash and the name for this was book property and we want the to set the name to be API uncore book property so now the end part of this should be finished so we can head to the front end and start doing some changes there so just want to close everything with the back end and then we can go to the command line because we need to install at least one thing here so just stop this running and say npm install react date arrange because this is a calendar plugin that we need to make it was to select for example from the first to the fourth and similar so then we can just run Dev again so it is running I don't think that I need anything else right now so let's go back here open up app and find components and properties and now we have the reservation sidebar um I think we all also need one more file and that is properties ID page. TSX we need to do some changes here as well um but if you open up the reservation sidebar we can do some changes here first I want to convert this to a use client type component and when we have this it makes it much easier to use use State use use effect and similar from react so going to import this use State and use effect from react um and we can import the range that we just um imported or sry installed import range with capital r uh from react date range and there are probably some more things that are going going to need um ranges declare button values never read okay this will go away when we start using it and we can import the API service import API service and the import use login modu because we only want to make it possible to uh do a booking if you are logged in so then we have this um we can set up one constant at the top here const initial date range so I just want to set up that the start and end date that we open with for the calendar should be today so then we can just say start date colon new date parentheses and end date should also be new date and key selection because we want to select these stes so we already have this property here uh with the ID and the price per night um and we have the properties for these um I think that we need to get the ID from the parent so the user ID so we can say user ID colon string or null and since this is not uh required because maybe um maybe you are not logged in then we just get null and we know that you're not logged in as a user so now you can see how I get the warning here because the user ID is missing okay we don't have the user ID here so we need to get that and just fix the error right away so here where we already passed in property we can say user ID and then we can say user ID there so this does not exist so we need to get that so at the top here I can say import get user ID we already created this in one of the previous tasks and then at the top I can just const user ID equals await because we want a wait to this for this to finish get user ID so then we have this and we can pause it in here and we receive it in here and then we can also say in here if the user is authenticated or not nice let's also just append it to this list that are passed into the component and then in here we we can initialize the login module just so that this is ready to be popped up if we need it so const login model equals use login model and then we can set up some more um variables and or states that we're going to need here so const fee set fee equals use State this should be a number sorry load case number at the default to zero and this fee is the 5% that we take as Jango BNB or Airbnb const nights set nights so this is just a number of how many nights we are going to stay there let's just copy this because the default is uh you can say the default to one because you don't want to spend less than one night that's just weird and copy this and rename this to total price and set total price default there can be zero because we don't know what this will be in advance and then we can create one for the date range const date range set date range and this is also the use State and and it's a little bit different because here we want to use range which is then imported up here from react dat range and in here we say initial date range so now we use this date range that we created up there um and then we can say const Min date just so that we can set a Min the minimal date or the lowest or earliest date you actually can do a booking Min date set Min date equals use State and here I want to pass in date like that and set the default to date which will set uh this default to be today so you can't book yesterday till today and similar then we're can to have one more for the guests so guests set guests and this should actually be a string and set the default one to one um we also need something called a guest range because um this property up here has a maximum number of uh guests that it's allowing so we can set the maximum that will be in the drop-down list um the one you can see down here so I want to stop this at this number so const guests range equals array do from length so then me set the length for this to property. guests uh comma underscore comma index index + one okay so you can see I got a few errors um let me see if I can fix that first of all you can see here that guest does not exist on this property so we can fix that by saying guest number um so that means that now I get some more warnings up here that might be because no property property blah blah blah okay it might just be because the weird thing I have done down here so I just need to look over the code okay this is supposed to be parenthesis not curly Braes now the error is gone and that error is gone and this should now work um the number for the property should come from the back end and should just be passed in like we have done already through this object and then this type here will extract it for us so we can use it down here and the reason why we use a guest range is because we need to set up an array that the select field actually can use so then we should have most of this ready now so we can fix the select list since I have that here already so can move this to a separate line just to clean up a little bit and then we can say here value should be guest and that is the value for this one which is default one uh when we change this we want to set guests so on change equals e for event set guests now we can PA in e. target. value so now it's automatically set to the one we click on the class name can just be like it is but instead of hard coding it like this we can go through the guests range so guests range do map number oops uh parenthesis and then in here option key number so this is just from one and up to how many guests the house is allowing value is also number which is just the number we are extracting there and we can also print the number inside there so if I save this now go back there is not working Let me refresh maybe this is running running and now I can only select one because this house only allows one guest nice so now that is working at least um so I should find one of the other houses three guests that's a little bit better so nothing happens when we select this but we can do some calculations on the prices down here so um let's go back to visual studio code and instead of hardcoding it like this we can start to print out the correct prices so instead of saying 200 like that we can say property do price per night because you already know that instead of saying four we can say night and instead of saying 800 here we can and say property. price per night multiply this with nights like that since this is Javascript you can just do it like this here we can print the fee and down here we can print a combination no sorry already have the value for total price total price so now nothing here is hard coded if I save and go back it should say $100 the fee is zero which isn't correct but we are going to calculate that now so if I go back here now we can create a use effect which will be run when this page loads but also every time the C calendar or the date range changes so use effect and then we pass in the dependencies as it's called date range so when this page loads this will run and when this variable here from up here changes this will run again so in here I can say if date range. start date just see that this is set and date range do and date to see that that is also set then we can calculate the days between the end date and the start date const day count equals difference in days okay so where do we get this from you can import this and I think it should be built into JavaScript um why isn't this working doesn't have a it's probably because the react dat range is Javascript and not um typescript so it suggest that we run this command so we can do that before we continue stop paste and hit enter then we can run again and go back to visual studio code so now the error is gone and what that did was just to tell the built-in typescript there that what the difference things things in that file is so it was sort of just a warning and not an error but now I want to import this different in days so at the top here import difference in days from date- FNS um let's just remove that and add add the curly Braes instead because I want to import more things and this is built into react I think it is at least it's already installed but we can also each day of enter wall we're going to use that soon and yes so then we have these functions so let's scroll down and we have this difference in days let's continue on that now here you say the Cur the parenthesis and POS in date range do uh end date and date range. start date it's important that you begin with end date and end with the start date now we can say if Day Count just to see that it's more than one day and and property. price per night just to see that both of these actually exists there so there's nothing wrong with this now we can calculate the fee underscore fee so it's just sort of a internal or temporary variable equals Day Count multiply this with property. price per night divide it by 100 and multiply with five to get 5% of the total price and we can say set fee to Fe so I guess if I save now go back refresh that did not work okay it's because the date now is the same so there is not one day so it will work soon and we implement the rest of the calendar so we can set total price to Day Count multiplied with property do price per night plus fee so remember the underscore fee because this uh set fee state might not have run before we are down here so you can just use this variable we created there set kns so that we store this in uh the state Day Count else so if there isn't a day count and that is as it is then we can just say const fee so we generate it down here as well equals property do price per night divide by 100 ultip 5 then we set the fee again so set fee to fee set total price to property dot price per night multipli sorry just plus the fee so it just will be $100 plus plus $5 and set nights to one save so now this should calculate and the total price is also $15 great okay so now this works this works now we need a calendar here so that we can select which dates that we want to book this before I continue I just want to say thanks to all of my patrons if you do want to support me you'll find a link in the description below so the calendar should be a separate component so let's open up components folder and inside the forms folder we can create a new file called calendar. TSX and this is a client component so use client is important here and we can import a few things date range date range range and range key dict uh from react date range so this is functionality that comes from this that we installed a few minutes ago and we can import the default styles for this so import react date range SL this/ styles. CSS and import react date range slist SL them/ default. CSS so now we don't need to think about the styling ourself we just going to do some few minor changes now we can set up the properties for this because we want to pass in the value uh and onchange function and also the book dates which will will come back to so we can say interface date picker arrange so date picker props value colon range so is is type of that we get up here which contains the start date and end date on change so when we do a change here we want to pass in the value to the parent which is a range key dictionary void to just mark this as a function booked dates can set this question mark so it's optional for now date so this will then be an array of dates const date picker colon react so it's actually maybe a little bit weird that I call this file calendar and the component name date range but for now it can just be like it is so react. FC for functional or function component Plus in date picker props equals Cur bra so we can pass in the value the onchange function and the booked dates F Arrow function and then we say return like that and at the end we can say export default date picker so we we want to do some changes to this here sorry we want to add some mark up here date range this comes again from this package set some class names we want this to fill out the whole screen or the whole box it is in we want the border and the Border can be border gray 400 rounded Xcel so it has rounded corner just like the other elements there and the margin bottom four and we can set the range colors property add the array in here and just say 26 26 26 which is sort of a grayish color the ranges should be an array with value which is the value that we have for example when we click on the fourth and then eth then that is AR range date what it is now can just be new date on change then we just call the on change function and the parameters it'll be automatically passed on direction is vertical this is just a layout show date display we don't want this just want this as clean as possible so just set this to false can set the Min date to new date which means that what we did in here might not be necessary this here the matee let's come back and see if we need it later add the parenthesis and disabled dates should be the booked dates there are none yet but they will come soon so then we can save this and that is actually the whole component there so let's import it into the reservation side the bar the top pair import date picker from calendar so that's the name of the file this is the name of the component that we created then if we scroll down we can insert this [Music] down can have it above the number of guests so here we can say calendar or date picker POS in value which should be date range which we have already created on change so what happens when we change the date then we can say value call a function called underscore set date range pass in value do selection so then this value selection will be the dates that we have selected instead get a warning because this isn't created I will create it soon and the booked date isn't available yet so let's just ignore that for now but we can create this function so we can have this above the use effect and Below these here and we can const set date range and the reason why I don't just call this directly because I want to do a few things things first so const set dat range equals selection colon any because I'm not quite sure what sort of data type that can be and then in here I a const new start date equals new date and then we pass in selection. start date replace this with end date date and and date so now we have created two new variables and then we just want to make sure that new end dat is um yes we want to make sure that if the end dat is lower or earlier than the start date and we want to add date on that so if new and date is lower than or equals to new start date and the new end date can be set to so set date this is working because this is a date fi from JavaScript new start dat. get date plus one so then we just add one date automatically then we can set the state by saying set date range here we can say dot do dot date range because we want to keep for example the the key which is the only thing left there but let's do it this we just unpack this set it to that automatically and the values for the start date can be set to new start date and end date can be set to new end date so I get some warnings here now cannot find name start date that is what this is supposed to be so there is something weird Okay so the problem here is that I just forgot the curly braces like that so now that should work so let's go back here modu not found cannot import this maybe I wrote this wrong let's open up calendar so this can be theme slash default CSS then it's there so now you can see the calendar and I can click 19th to 28 for example or 27 to 20 and it's automatically fixed now nice so now most of this should be working but I guess there are a few more functions that we need but let's try to start submitting this to the back end and to submit this to the back end we need to create one more function in the reservation Side bar so at the top here we can create one more function const perform booking equals a sync like that and then we want to make sure that the user is logged in so if user ID and we go in here else and we can use the login model open so then this will be presented to the user but right now we are authenticated we const form data equals new form data with capital F form data append guests guests so we get this from the state copy this and replace this with for example um actually we can say start date this is a little bit different start date and here we want to pass in format which I will need to import soon date range do start date and the way we want to format this is y y y y Dash mm with capitals M DD so let me just import this format up here this also comes from this um this package here import format like that but since we're going to use this as a function I think we need to pack it in curly braces and import it like this which means that I actually could just POS it in there comma format okay so now that's important then I get a new warning here not assignable number I think I get this warning because this data range might not have this value so maybe if I set and and so not in there but in here if date range then we can continue and I think I still get this warning but if I a do start date then we can use this so we need to just confirm that this actually exists and that we also have a date range do end date so we can copy this replace this with end date and the same with end date and this is just something you need to do to make sure that D Jango receives the correct formed date so we need one more for the number of knights this is the value of knights night sorry um string blah blah blah why is that not correct let me just con convert it to a string like that and last but not least total price so total price pass in total price two string so when we have now this form data we can use the API service to post this data to the back end so const response just so that we know what happens response equals await API service. poost so we use the function we have created there use the back text to create the URL SL API SL properties slash and then we pass in the property. ID slash book which is the URL that we created previously and at the end here we just say form data because we want to pass in the form data now we say if response. success that means that the booking was uh good and we can say console log finished or booking successful we can see this in the console else console log something went wrong save and to then just activate this booking button we can scroll down and find this book button here or this div and when we click this we want to call that function so here we can on click then we want to call the perform booking function so let's try this we have this terminal open and we can have the inspector open just that we can follow along on everything let's write the book from the 20th to the 22nd that will be $200 we want two guests book okay I was not logged in yes so now I was logged in let's go into there again 20 to 22nd to guest book okay it still says I'm not logged in but that is not correct so there is something wrong with the user ID check so the user ID here console log let's find out why refresh ASF no user ID so I have this user ID and it is passed into the reservation side the bar user ID there so then I check it there let's see here console log perform booking now we print out the user ID there as well book so perform booking and then you have the ID so now it was working I don't know why it didn't work previously but yes I still I get a warning an error from Jango expected a response to be returned okay so open up API inside property I forgot to say here return Jason response success true but since it got there it might look like it was working so yes now we have a reservation nice the end dat is wrong on the other hand it's not good but let's try to make one more booking 20 223 two guests book so now we get the booking successful back there perfect go to reservations and now the date was working the other one was probably not because I had refreshed and hadn't selected the dates so you can see the total price how many guests how many nights Etc which means that now the booking is sort of working let me just see to do list book property there is nothing more subtasks there but um I want to show the already booked dates because now I won't be able to book these anymore I need to fix that okay so the first thing I want to do to get these properties is to create a new serial ier so let's open up serializers p in the property app say close reservations list serializer PA in serializer model serializer and then we can specify the class meta the model we want to use is reservation need to import that also up here SC scoll down again and I set which fields we want so fields we want the ID we want the start date we want end date we want the number of nights we want the total total price and we want the property so these are not really necessary right now because we know which uh number of nights it is ETC but we're going to use this later on we're going to show the reservations in the list so we can just have this as it is and we just need to use this property list serializers for this because we need some more information about the property later so here we can say property equals properties list serializers read only equals true and many equals false so now we get some information about the property here as well so now that we have that serializers we can go to the api. pi and set up the end point for getting the reservations so here we can say um reservations list serializer and scroll down and then we can make a copy of this these lines here because we want to get the property a little bit like that so just rename this to prop property reservations and we get this based on primary key and that and then we can get all of the reservations for this so reservations equals property do reservations. all then we use the related name in the model set up the serializer equals reservation list serializer POS in the reservations set many equals true because now we want a list of all of the reservations and then we can just return these by saying return Jason response and then Po in serializer do data so if we then open up URLs to p and just append it here oops then we no have done everything we need to do in the back end reservations uh property [Music] reservations API underscore property reservations so what you need to do then is to load this in the front end so if you go back to reservation Side Bar we can create this somewhere here for example under the set date range const get Reser oops reservations equals I sync create F function like that and we say con reservations equals await API service. getet now use the back text to create a URL SL API /properties SL pass in the property ID and append the reservations just like we did in the URL file and then I want to create a new array of dates so let dates colon date so this is just some typescript functions like that so now we have an array of dates now we can Loop through the reservations reservations. for each reservation colon any because I'm not sure the data type for this then const range equals each day of interval which was one of the other functions that we created here which just creates a new day for each of the day in this interval here parenthesis curly brace and then um in here we say start for when we start this new date pass in reservation. start date so here we can see this use as the lower case with the underscore which is from the database back in Python and new date Plus in reservation do and date then we close the const range and say date equals then we unpack everything that is in here since this is now a loop we just keep adding to it dates and we want to unpack this range here so dot dot dot range and when we then have these can at the bottom here say set booked booked dates to be dates and our you can see that a warning I get warning here because we haven't defined this booked dates yet so let's scroll up and set it up here const booked dates equals set booked dates you equals use State this is a type of date um add date array sorry and the default here can just be an empty array okay so now we have set the book dates now we just need to use this so we can use it down here in the date picker book dates equals pass in book dates and you can see we get no warnings there now because we are already expecting it here and since uh this was optional we had already set this to be disabled when we get something there so I think it was almost supposed to be [Music] working expected expression okay looks like I added a comma that wasn't supposed to be there [Music] semicolon refresh okay it doesn't look like these are disabled no set booked dates Okay the reason why is because we haven't called this get reservations yet so we need to do that and we can do that every time this here is run so we can just add it at the top of use effect so if I refresh now we can see that I get a new error from D Jango nice not but it's always nice to do some debugging let's see here if you can see what the wrong is in order to allow non-ict object to be serialized set the safe parameter to be false okay so here we can just say save equals false and as you can see now that should be working and the reason was that uh it's not a dictionary and a non dictionary can't be serializer serialized but if you set this to false then it will be materialized anyways so now you can see that these four days are disabled because I have already made a book booking for these dates nice so that means that now I can go to the too list and set this task to done so the next step then is to make the landlord page Dynamic meaning that when you click the this name I want to be sent to uh landlord page and I want to load information there with all of the uh properties that this landlord owns so if we first go to visual studio code and just find the page oops the page where we show this or the the detail page for the property then I want to make this clickable so instead of a div here we can say link close this link move this to a separate line and we can set the HF here so HF set back text here slash oops slash land Lords slash and now we pass in the property do landlord. ID oops like that you can see a new get a warning here because you can't find this so we can import this import link from next slash link then the warning is gone if I go back here now I can click this and I will be sent to the landlord page everything here is then hardcoded so that's what we are supposed to fix now so if we go to the sidebar here just Define the landlords ID page. TSX at the top here uh we can use the API service to get information from the back end con land lord equals a wait okay so now we can see that to get the warning here because we are not in asynchronous function so we need to convert this to an async function first of all but we also need to allow this to have parameters so in here we add curly bra say params colon new Cur Braes params colon new Cur brace ID which is a type of string close close and then close the parentheses now I can use the O8 function in here because now this is an asynchronous function with parameters so say API service and this was automatically imported do get use the back text to SL API SL slash and then we can just pass in perm. ID so this perms just refers to this one and the ID is this one of course which is the name of or the ID of the landlord um we can also get the user ID for the user ID we are because we going to need that later user ID equals await get user ID and then that was also automatically imported so if you save now go back see here let I get some errors probably because the O page didn't exist um where is [Music] that yes here you can see I got the 404 error because I haven't created this in the back end yet so maybe we should do that before we finish the front end so inside the back end folder open up jungle BNB user account and then we can create a new file here so api. Pi so we already have a serializer for the user so we can import that from do serializers import user detail serializer and we can also import the model for the user so from Models import user and we can import the Json response from Jango from Chango HTTP HTTP import Json response let's close this and we need to import a few things from the few decorators from the rest framework from restore framework do decorators import API view authentication underscore classes and cl list permissions classes so now we are ready to do this to sorry to get the landlords so at API view this should only accept get requests and we can set the authentication claes to be empty because unauthenticated users should also be able to use this then def land lord detail request and primary key and then we can get the user from the database Bing user or landlord equals user. object. getet or primary key equals primary key we can use the serializer equals user detail serial letterer pass in user and set Manu to be false then we just say return Json response serializer do data and save equals false in case it is not a serializer b object so now that we have that we can import this view into this file so from do import API we can just import the whole file and when the path is um this is already API o and then we just append uu ID name primary key and when the URL matches that one then we can use API do landlord detail and say name equals API landlord detail and save so that was hope it for the back end so if I refresh now I still get an error did you mean permission classes sorry did a typo there permission classes permission classes okay now there are no errors refresh and then I got the information from the bra back end perfect so then I can do some changes here instead of showing landlord name we can say landlord. name I think that will be correct yes Stein perfect and we can also replace the Avatar so instead of hard coding it like this replace it Cur braces and a landlord. avatar URL so I don't have an image for that one that's okay because it's just that I haven't uploaded it for this user and then we only want to show this contact button if this isn't you so above here we can say user ID not equals pam. ID if that is correct then sry if these are not matching then we show this button so then you can see that I still see this because this is not me and then we have the properties list here and here I want to pass in the landlord ID so that you can just use this to filter it and then this can be more reused so here I can say landlord uncore ID equals perm. ID and then I get the warning now because this is not supposed to be passed into property list so if if I then find that file property list then I can set up here that I actually do want it here as a parameter sorry as a property so below here I can say interface we need to set up this property list props curly bra landlord ID question mark because this needs to be optional and this can either be a string or the value can be null then we convert this to a react. functional component and pass in property list props and to make this available in here we say landlord ID and then I should actually just be able to pass that in here to the back end so what I want to do then is to say uh let URL so I just Define this as a base URL and po it in there and then I can say here if landlord ID so we can check if this exists then the URL should be changed a little bit so it's going to be URL plus equals question mark and then say landlord uncore ID equals landlord ID so I can't use this here without converting these two back Tex this and uh this like that so now if I go back and refresh nothing happens now but if I go to the terminal you can see that I want to get the properties where this is the landlord ID so now I just need to receive this in the back end as well so in the API for the property then we have the property list then then below here I can say landlord ID equals request. get. getet landlord ID and default this to be empty and I can check here if this is set and if it is then I can say properties equals properties doob sorry properties. filter where landlord ID equals landlord ID so so now we add some filter here we can a a little comment there just to separate and clean this a little bit so if I go back now and refresh I only get two properties because these are only two properties that this landlord is owning nice and if I go into this one which is a different host then we can see here that this only has this property nice okay so that means that now the landlord page is also Dynamic you can click on it and you can view the properties in there so we can set this task to done by the way if you want to learn even more D Jango or view from me you should check out my website codit stein.com the site has many premium courses and a lot of awesome blog posts and for as little as $20 per month you will get access to all of my content and you'll be able to track your progress you can talk to me and similar so go to codit stein.com after the video and sign up okay so let's do one more quick one which is the my properties that should go quick because it's very similar let me just close all of these files and find my properties then you can see that we use the property list here as well so here I can actually just provide my own user ID as the landlord ID and I will get my properties so up here I can say import get user ID and I get it automatically then I just need to convert it to be an asynchronous function async like that I think and I can say const user ID equals get user ID forgot to add the AWA there first and then down here I can say landlord ID equals user ID that was actually it there so if I go to the front end here and go to my properties that is empty yes that is correct because I don't have any properties but I can assign one to me right now I am the user Stein at Stein save so if I refresh now I should own this one perfect um just one thing that I can fix first to remove this since this is unused but I want to have a link up here that goes to this page so we can fix that by finding the component for the nav bar the nav bar there the usern nav I think is the correct one yes we have the log out but Buton so if you add some empty fragments to wrap these [Music] buttons then up here I can say menu link say label my properties and when we click this we can close this user nav bar set this open and when that is done we can go to sorry how did we automatically go to page so it's just this router that push not the correct URL but I can copy this go back here and we can go to slash my properties and I just close this on click and that one close the menu link and save okay I get the warning because cannot find router we need to import this import use router from next navigation and then at the top here I can say const router equals use router so now the error is gone let me go to the front page click here then we have my properties which takes us to my properties great so then I can set that task as well to done okay so then we have one more task my reservations so let's find that page my reservations since you already have the nav bar open let's create a link to this my reservations my reservations so we can go to that page my reservations so you can see this hardcoded here so I want to load this from the back end make it possible to go to this property and just see the places you have reserved or booked so I can just close the user now I can close my servations no I want that open of course okay so we can begin with creating the backend API end point for this so just close find the user account api. piy so I think I need to import the reservation list serializer here from property do serializers import reservation list serializer then I can create a view for this so I can copy this decorator say def reservations list POS in the request parameter we don't need a primary key or anything because this is only go to use the um request user so reservations equals request. user. reservations. all request sorry so now we just use the related name from the models. pi set up the serializer serializer serializer equals reservation list serializer pass in these reservations and set many to be true then we can just do it just like we did up there and that was it so now we can import this into the URLs here the above this here we can say part my reservations slash we're going to use API SL my or reservation list what I call it reservations list and the name can be API uncore reservations list and that was everything we need to do in the back end so close these two then we can uh get the API service here so let's import it import API service convert this to be an asynchronous function const reservations equals await API service. getet we just use that function SL API SL SL my reservations remember the slash at the end then we have a list of reservations that I can just Loop through them down here instead of hard coding them so I can remove one of these hardcoded go to the top here below the space Y and above this one and I can say reservations do map pass in obervation here in singular form and that is data type any we could set up a type up here if we want to do so we know that we have the start date the title Etc but I'm don't going to bother with that right now and then we set up the fat Arrow function like that if I just take these three I can paste them below this div and fix this indent ation so if I save now go back here you can see that this is empty there was supposed to be one I thought and but why can see here that it's trying to get my reservations but why is that empty request. user. reservations. all print user request. user so know that it is me print reservations just so that I know there isn't anything lost here refresh go back here user you can see here that there are two reservations so why do not they come through here um boom okay it's not a problem there I forgot to add this return here so return parentheses like that because every time you map through something you need to return the data if you want this to show so you can see here that these are still hardcoded data but it is working so let's replace the name with reservation dot property oops property. title you can see the name of that one perfect and we see when we are checking in reservation. start date copy and replace and replace with end date you can see number of nights and we can see see the total price so now you can see that the data here is dynamic so I need to fix this image now and this button so the house or the image should just be reservation. property. image uncore URL so now this is dynamic as well perfect and then it's just to fix this this one and let's just move these two separate lines there are two long this attributes and then on click and when we click this we can call a function and say router. push um and this should go to slash uh property slash and then we just pass in the ID so reservation do property do ID like the warning here because we have not imported this so import router from uh roue from next navigation it's supposed to be navigation like that import router from next navigation so it's it's actually [Music] use router so import use router from next navigation and then up here we can say const router equals use router so initialize it and the warning is gone so if I go down here use router only works with client okay use client can can I do that no I think that I get a new error here now because this router isn't supposed to be used in there so let's just remove this button right now um we need to create a new function or component just for this button so let's skip that for now we now have the list of my reservation and it seems to be working maybe I could import the link so import link from next link and use that instead sorry copy this contrl C just so I get the button back and then I can replace this with a link link and hrf goes to like that so then I think this should work so now we have to guess property and if I click that I'm sent to this page perfect so now I see that this image is wrong why is this [Music] wrong is this image hardcoded from the first one of the previous Parts yes property. image URL that is correct nice so now we have the my reservations page as well this button works we can zoom in this image a little bit we get this information that we need perfect done okay so now I want to make it possible to set the property as favorite okay so in order to make it possible to set this as favorite we need to change the database a little bit so if I open up models. Pi in the property folder then in the first one of the first part we set this favored just to be empty so let's change that to be a many to many field model. many to many field put in the user and this will just be a list of user users that has liked this uh property related name can be favor favorit so it's easy to get all of the favorites for one specific user set the blank to be true in case there are none who has liked this and save so I'm need to stop this server here and when this is stopped I can't run to make migrations so let's just start them here running and if I just click up a few times then I can find the make migration and the migrate and I think if I say Docker compos oops up Docker compos up now and you can see here that this migrations was run I add a new field to the property and everything should be ready there great so that was step one for making this work next I want to create a new uh API end point for this so at the bottom here I can make a copy of this one API view def toggle favorite and I said toggle in case you want to remove it as one of your favorites request and primary key and this primary key is the property and we get it just like we do it here we can set it like that and I say if request. user in property do favorited do all so then it checks if your user is in this men to man field list and if it is then we want to remove ourself from that one so property do favorited do remove request. user and then we can say return Json response is favorite false because now it's not no longer a favorite but if we are not in that list we can say almost the same but you say property favorite. add requested user and it favorite should now be set to True great so that was the end point let's define the URL and we can just make a copy of one of these and say toore favorite api. tole favorite and the name can be API tole favorite okay so that was the back end for this and now I want to have a button for setting the favorite so let's scroll up and and then can close the form you can actually just have that in the main folder here in the components so let's create a new file called favorite button. TSX this should be a use client component and I we need to use the API service to talk to the back end we need to set up interface because I want to have a few properties for the property not necessarily the ones that we've used other places so interface property props and then we say ID string and I want is favorite this is bllen and Mark favorite colon is favorite Bullen so we have a value here uh which is a bleen field called his favorite and this is a function so we set void and then um actually it's supposed to be favorite props favorite button props that makes more sense since it's just here we are using this const favorite button equals ASN colon react. FC for function ction component pass in the favorite button props then we set up the parentheses and curly braces and pass in ID is favorite and last but not least Mark favorite and I think I just get a warning now because this function isn't complete yet um that return like that now the warning was removed and then I can say export default default favorite button and in here I want to have a div that can that can be clicked and call a function so div on click and when we click this I want to call a function called toggle favorite and I want some Clauses on this as well so class name use the curly bra here because I want to pass in some variables so use the back text to say absolute top-2 right- two because I want to put this in upper right corner of the images then I pass in is favorite and if this is a favorite or if this is true then we PA in text Airbnb so it is red and uh else we put in text white and I use text here because I'm going to use SVG icon and that will make it red or white based on if it is a favorite or not and when we hover this hover then we can say text Airbnb so it's red when we hover this then we can close the div like that I get a warning here now because I haven't created this I will come back to that so where do I get the SVG for this if I go to Chrome and open up hero icons I can just search for heart and copy the jsx paste that in here like that so since I copied the SV the jsx and not SVG you can see that this already has the capital L and everything should work now out of the box great so now we can create this toggle favorite function so const tole favorite equals a sync and here we expect the event to come here and this should be a mouse event with the HTML div element so react do mouse event and what we are expecting to get in here is a HTML div element like that so that is how you define the function for this and I need to do this because I need to be able to say e do stop propagation because I don't want to make make it to click this multiple times Etc and then I can say con response equals await API service. poost and here I can just pass in slash API slash properties slash then the property ID which is ID which we get from one of the properties one of the props for this component sorry toggle favorite and to make this error shut up we can pass in an empty array and when this is done we can say Mark favorite response. is favorite so what we do now is to call this function with what we get back from the server and what we get back from the server is either false or true based on if it is now a favorite or not so then we need to do some changes to where this favorite button should be located so let's open up property list. TSX and do some change here um up here where we Define this property type we need to add one more property equal is favorite and this is a Bine value like that and then we can create the mark function sorry the mark favorite function that will be called when we click this here so above get properties we can say const Mark favorite equals and then we want to expect and have an ID here which is the ID of the property comma is favorite which is a bllen value create a fat eror function like that and I'm a const TMP properties equals properties do map so we just go through all of these property property colon we set this to be a type of property type which is one of this and then we create a fat error function out of this and we can say if property. ID is the one that we pass in here ID then we can say property do is favorite and we can set that based on the value that we have here equal is favorite and below here we can sorry below inside here we can say if is favorite we can just say console log added to list of uh favor properties we should have a toast or something to show this but we can fix that later console log removed from list and at the end there we can say return property just that this is returned and then at the end there we say below here set properties to TMP properties okay so now we just reset this so that the toggling should be working so if I scroll down now we have this property list item and we can pass this function and similarity into there as well so Mark favorite equals Cur bra is favorite this like that F function Mark favorite so when this is called from the children say property do ID is favorite okay so I get the warning here now any Mark favorite not theable yes because this isn't supposed to be on the property list I yet that is the next step to fix now and one of the last step to fix as well so again now with the property list item we import this from here so we have the same property type good and then we should have the property props here uh here we need to PO in the mark Pro favorite which is uh not required to have there is favorite colum Bine and this is void so a sort of function then we just pause it in there so it can be used in here and then we can put it down here so we can check that if this is there mark favorite and and then we can show it here so favor it button and it was automatically imported this expects an ID which is here property do ID it's expect it favorite value property. is favorite and the mark favorite function if this is called so is favorite F eror function and if this is clicked then we called the one that we get from there from the parent again Plus in is favorite value now we can close that one and save okay so if I then go to the browser you can see that we now have these Hearts here and let me try to click one of them then I get the 401 unauthorized given token is not valid okay it's probably because I'm logged out now so I need to log in again so let me just re refresh click there and this was now added to my list of properties or my favorite and if I refresh it's not red anymore so there is probably just because that I need to go to the serializer for the property and fix something here so if this is liked then I need to show it here okay so later I'm going to use a list of the properties that you have liked so we can fix that at the same time now so if I just find the api. pi uh where we get the list of properties so before we create the serializer favorite now we can here say if user so if we are logged in so if the user is logged in I will we will add this soon then we have for property in properties and for each of these properties I want to see if user in property do favorite do all and then in here I can say favorites dot append property. ID okay so this favorites should just be a simp array like that and then we just need to make sure how can we get the user because request. user will not work as long as we use this and we want to make it possible to actually have unauthenticated users so we need to do some changes at the top here so we can create an au commment there like that and just say try token equals request. matter h be authorization so we want to get token from the authorization dot split and then we want to get the bearer token Bearer remember this is space and we want to get the object number one and token equals access token so this is something we need to import soon you just need to validate this with the rest framework you user ID equals token. payload uh pass in or what you want to get here is user ID so now we get the user ID from the access token user equals user. ob. getet where the primary key equals user ID and if we are not authenticated we just accept exception s e and then we can say user equals none because I know that we are not authenticated so let's import these two things from user account. models import user that is gone and then it's just this access token and this is from rest framework simple JWT do tokens import access token so then we can try to say print user uh user just to see if we are actually authenticated so open up the console it couldn't find this package here okay this are supposed to be tokens as in plural so no errors let's refresh go there again then you can see user Stein at steo which means that we actually are getting this correctly just to remove this now now we know that we are getting the user perfect this is still not working but hopefully this is working we can say for example here print favorites favorit just to see what we get there refresh now you can see here that I get one uu ID perfect because I have only liked one object so I need to pass this into front end favorite favorite as is this is just a list of IDs we don't need to serialize them or anything like that so if I now go to property list and find where we are assigning the set properties down here in the set properties then we can do a little change here because we are now getting this here then I just want to Loop through each of these and set this is liked or not so do map property property type which is what we have here this has this value or property property property it's a lot of property now create a fat error function if TMP properties do favorites do includes so if that list includes this property that we are on now do ID then we can say property do is favorite equals true remember lowercase T since this is Javascript and not python but if it's not in that list then we set this to false and save so if I refresh now it is not working okay because I need to say return property since here we are using this map functionality and now you can see this is red because I have liked it nice so now I can set one more task to done and that was it for this time if you have any questions about today's code feel free to leave a comment below and I'll answer as soon as I can see you in the next video
Info
Channel: Code With Stein
Views: 2,915
Rating: undefined out of 5
Keywords: code with stein, django, learn django, django tutorial
Id: 7nw9wh2ZCIY
Channel Id: undefined
Length: 103min 17sec (6197 seconds)
Published: Tue Mar 19 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.