Part - 1 Lets Build Fullstack Hotel Booking App with Blazor SSR - .Net 8 | Complete Course by Abhay

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys I am back with another video and in this video we are going to build uh complete fullstack app using the new blazer with net8 using Blazer SSR so I was actually uh surfing the internet then I came across this cool template so this is the template which is hotel booking template so I remember uh I got a couple of comments on my couple of videos that people want me to create a hotel booking app using Blazer so when I saw this template so I thought let's integrate this in Blazer and let's create a PO tag application using Blazer SSR for this one so I have not prepared anything I just saw this template I like this template and I I have just started to recording I started to record this video so we'll integrate this we'll work on all these things so and right now I don't have anything in my mind we will see what this template has we'll try to add a couple of other features to it we will uh I got a couple of comments to integrate the payment as well so we'll see we'll integrate stripe payment as well for hotel booking and then we will create admin panel as well for this application right now the template it has these only this basic pages so this is the homepage which has this main hero section main navigation bar then this is the small booking form till when so checkin dat checkout date then number of adults number of Childs and then submit then a little about us then rooms okay we can go to view details where we'll see the detail of the room and I think okay that page does not exist in this template but we'll create that page we'll try to uh use the same theme so we'll create the detail page and then it has this amenities description view details book now and then that means on this book now we need to create a lendy form we'll create a new form apart from this all right after that we have this our rooms Booker room explore our services I think all these Services also we should uh create these database driven so we will we will try if we can integrate the this also as a screen on the admin panel so that all these things can be handled from admin panel as well then we have these testimonials explore our stuff subscribe to newsletter and then this is footer then let's see what else we have we have this about page Services page so all these pages are uh sub pages of this homepage we could say because all that information is already on homepage so we'll create reusable components using Blazer so we'll render those on homepage as well as we will render those specific components on these separate pages on rooms we have same thing just number of rooms we are displaying six rooms here on hom page we were displaying only three rooms all right after that we have this Pages booking page do we have yeah we have this okay we'll use this booking page name email checkin check out and everything looks fine here as well cool our team so this is that same page testimonial then we have contact we have contact form and we have this map cool overall it looks fine it looks clean and we will have a lot of feature actually it is looking small but it will have a lot of features so now let's start working on this and uh before that I got this template from HTML codex.com so here is it I'll add the link of this this template in the description box if if you want to check out you want to download or you can buy the premium version of it as well all right now I will fit the complete demo of the complete app after this section so right now I'm just starting to creating the project and when I will merge all those videos and I'll create the final video at that time I will simply inject the demo here so that you can see that what we are going to build this is the basic template but the final app demo I'm going to add that here and after that we'll start from here okay all right so here's the demo of the application so this is brly the app we are going to build in this uh course series and this is blazing Hotel okay so this is the app this is completely fully functional app okay first we have this main header so this information this contact information email contact number air and then same thing we have in footer this contact information this address contact number and this email then on contact us page these three email ID all this information this is coming from our app settings Json and we are using eye options pattern for this so all this stuff is coming from there after that we have the Social Links right now these are pointing to my social profiles then we have the school uh navigation bar so this is the main homepage I'll work you through for all these pages but first let's see the homepage on homepage we have this carel where we have these two options two buttons our rooms which will navigate to the rooms all these rooms are coming from the database then let's go back to home again then we have this Booker room button if we tap on this it opens up one page where we have this booking information where we can provide a first name last name email contact number password so when we book a room it actually creates our user account on this so that we can see our bookings we can make payment afterwards if payment was cancelled or maybe we did not make payment at the time of booking so we will have our uh user profile as well and my bookings as well then we have this checkin checkout dates we have number of adults number of children so that these room types we have these room types so these will be filtered on the basis of these things right now we have these four so if I select let's say three adults now I can see there is no room which is which allows three adults if I select two we can see these three if I select two children I can see only these two so these are Dynamic then we can select room type we can add some special request then it shows the price so right now this is some dummy price if you select this so it shows and this is driven on the basis of this is per night price actually so right now this is 6 to7 if I increase this if I make it 6 to let's say 8 now this is 2 days so this price got increased to 24 100 rupees and then we have book now so that we can book a room right now we cannot book because these fields are not failed I will show you other things as well but again let's go back to homepage this was this main homepage then we have this filter this search section so all of these things all of these are separate components and we are reusing the components for example this component this search component if you check this is on all these pages so this is a common shared component which we are using all right so using this what we can do we can search rooms on the basis of this thing so we have this filters we can choose these children adults then we can search it so it will navigate to Rooms page where we can see only two rooms because these two rooms allow two adults and two children right if we remove all these and then we search we will see all the rooms right now we have four when I say rooms these are actually room category so this junior suite it has this it will have multiple rooms in this so guest is actually going to see room type and they're going to book a type then staff or admin they those people are going to assign the actual room number actual room to this booking that also I'm going to show you in this demo all right let's go back to home after that we have this small about section here we have Explore More which goes to this about page only then we have three rooms here these are also coming from database we can click on this book now if I do this book now this is first room if I click on this book now it will navigate to booking and here we can see this select a room this drop down is already selected because we came from there directly right so this should be selected so we have we are using this state also go back to home again after that we have this small uh call to action section so our room it goes to Rooms Booker room goes to booking we have the services staff then we have this newsletter we can subscribe to this newsletter ABCD at gmail.com so subscribe successfully this is fine then we have this nice footer all these links are working okay then let's go to the next page which is about so this is kind of static page there's nothing Dynamic yeah this section is of course dynamic this newsletter is of course Dynamic and this this information is also Dynamic then we'll go to services this is the main content of this is kind of static then we have rooms all these rooms are coming from database as I already showed you and we can book any room from here if I click on this book now it will go there and this room will be selected Auto selected on this booking page all right here are rooms then we have this contact page where we have all these information then we have this contact form inquiry form so here also we can add something maybe uh demo user demo gmail.com Oh that was email this is email subject is demo subject and then some random message will go here and then send message we can inquiry sent successfully so inquiry also got sent all right now we can login or we can register as a new user so complete user authentication and authorization using ASP net core identity we're using that so let's create a new user right now let's say a demo okay email is AB demo atate uh maybe gmail.com contact number some random contact number password it needs all the uh restrictions from aset core identity that means one special characters numbers lower case uppercase characters all of those things I'm going to create at the rate uppercase a lower case a 1 2 3 4 5 6 at the rate a a 1 2 3 4 5 6 all the data annotation validations are working if I make it like this then we can you can see these are not matching we need to so on this page this is static server side rendered with streaming rendering so we'll registering it it came here ao@ gmail.com we can see this password we can login using this account now we can see this user here okay everything is same now instead of login we see log out button and we see this additional menu here where we can see my profile my booking has change password so if I go to my profile I can see my profile and I can modify this so I can modify name first name last name contact number email ID then I have my bookings so here I can see my bookings right now I don't have any bookings so on bookings page we have upcoming bookings ongoing bookings and past bookings we don't have any booking yet so this is all these sections are empty right now then we have change password so we can change our password from here if you want all right now let me show you one thing if I go to home and if I go to let's say contact and here you see because I am already logged in so it knows who I am so this name automatically filled this email got automatically filled in this contact form same thing if you go to book a room here you see now we don't have those additional fields which we had uh name email contact number password confirm password because right now we are already a user and we are already logged in here so this system already knows who I am so it can easily make booking right I can show you that if I log out from here you'll see I need to provide all these values right if I log in again and if I go to contact page I not contact Booker room page now I just need to provide these things okay all right now let's make this booking so let's select some room maybe junior suite and if I have some special request I will provide it I I if I don't have that request then I'm okay now we'll book now so this is processing and now it move to stripe payment Gateway so we have payment integration in this let's add demo gmail.com we can cancel this payment we can add this payment so let's do the add everything I'm going to use some dummy values here demo and if I pay so this is payment is processing after that it will payment is done successful it moved back to this payment success page where it is saying dear AB demo this is the username then payment is confirmed you will be alloted a room soon so we are good now if you go to my bookings we can see this booking ongoing because I select selected the same date so this is in ongoing booking and here we can see status is payment success and pay now is disabled but cancel is not disabled so we can cancel this booking if we want to cancel it and payout is disabled it will have let's make one more booking so what I'll do I'll go to book a room let's add some future date so let's say 14 to uh 16 okay room let's say saver and some special request some special request okay book now it came here now I'll do this I'm going to back so this payment is cancelled your payment is cancelled okay now if I go to my bookings upcoming bookings I see payment cancelled so payment was canceled that means I have this pay now button but cancel booking we cannot cancel a booking because that that booking was not made actually but we have the entry in the database so we can pay from here as well for ongoing booking you see pay now is disabled but for upcoming booking this is enabled so from here also if you click on it it will again go to there on the stripe and then we can do all this stuff again if you want okay now let me log out from here and now I already have an admin account so I'm going to login with admin account so there I will see I will show you okay so this my booking space this was specifically for the guest only so this is access denied for admin because admin cannot access that URL that is guest slm my bookings that page is specific for guest only so let's remove that and now we are here this is the name of the admin so first thing let's update the name sub have prce updated let's remove this updated and yeah let's update profile so profile updated successfully now let's try log out log in again now we can see AB prins now we have all these options here we have managed stuff so if I come here we can see this is the staff list we have we can add a new stuff from here first name last name email contact number password confirm password then designation or we can go back we can addit some existing stuff okay we can demo designation we can add anything update to file this is demo designation okay then it has it we are using quick Grid in this so quick grid with paging and all this stuff template column property column so you will learn about all these stuff as well now after that we have add stuff the separate button also I have given so we can create a new stuff from here then we have manage bookings so these are all bookings which we have created so far so here we can see ID room ID room number everything guest details when this was booked check in check out all the special some special request current status and remarks everything we can see this is also quick grid we have this paging we can move around this so if I go to page number one this is the the current booking for this payment was canc so if you see room type is sa no room assigned right so room can be assigned only after payment but payment was not completed that's why this status this says you cannot assign the room and then you cannot approve and you cannot cancel it so admin also cannot cancel or approve it because this booking was inserted into the database but this booking was actually not made because booking will be made only after payment success right if we check the second one here we have 103 room assign already to this booking and this payment success Abad demo this is the one which we just did we to which we uh actually made the payment so you see no room assigned assign a room button we have this here this is the information we can approve or cancel this booking if admin or staff want to they can approve or cancel this so right now let's assign this room so there are no rooms for this room type available this is junior suite so what I'll do I'll go to the manage rooms I I'll show you this so we'll come back to this but before that we'll go to manage rooms it was junior suite this room so from here we can add a new room we can provide room type price maximum number of adults allowed maximum children allowed then description then we can upload image from here and then these are the amenities uh from from where these amenities are coming we have manage amenities page so this is the manage amenities page this is a simple HTML grid this is not quick grid here we have this we can create a new Amity here okay we can provide some icon for this we are using bootstrap icons I don't know can say 24 hours water or maybe water supply water supplied don't if fa water is a class if I save it we can see this directly here fa water water supply we can addit this it came here we can delete this if we want let's add some maybe uh [Music] some testing okay we'll save it we'll add some test amenity save it icon is required save it and we can delete this so that got deleted from here okay so these are the amenities now I have added this water supply they should come on this manage rooms and if I add a new room I should see that water supply as well so you see we can see this water supply then we have this unit values as well for this so this unit values is kind of uh if we go to homeage or maybe rooms here you see one add one gizer so this this one this is the unit value for Wi-Fi we don't need to have any value so this is fine bad I have not provided any value so this is fine lift is fine okay for this thing I have provided two so this room has two beds that's why we have two this is the unit value this is coming from there only let's go to manage rooms or maybe add room type again so all these thing we can manage the rooms and we can addit any existing room as well we can change the image we can modify these values after that we have in manage rooms we have this rooms this thing okay so if we click on this room we will have it will navigate to this page where we can add rooms to this add new room so let's say 61 I'm adding it this is available yes 61 let's add one more 62 this is also available we can delete the rooms we can made this aable or not available from here this is Junior suit both of these rooms are available right now let's go to bookings manage bookings here this is Junior we now if I go to assign room I should see 601 602 okay now I can set 62 I will save it now you see Junior suit 62 room is assigned we can change it from here we will tap on it and it will show only the available rooms if you go to manage rooms junior suite if you we open the rooms here we should see is available this is not available now 62 because this is already assigned to someone right all right then we can manage inquiries all these are inquiries which are coming from this contact page so from here whatever comes whatever we post those gots added here all this information same thing we have manage subscribers so these are that the footer subscribe section this subscribe and newsletter this is this section so all these things we can get here in manage subscribers then we have change password so this is for admin okay so admin can see these many things manage stuff add stuff so if you login with some uh staff login account then this manage stuff and add stuff these two options they are not going to sa because these two are specific to admin okay let me log out and let me check here this is one staff account here you see my profile manage booking manage rooms add room type manage Amity inquiry subscriber password there are no manage stuff because stuff cannot manage other stuffs okay now we can go to manage bookings here also we have all these things now we can cancel some booking let's cancel it when we will cancel it will display JavaScript alert if you cancel nothing will happen if I press okay then it will ask for me a cancellation region if we canc it it will not cancel the so we need to provide cancellation region so here say demo purpose and I'll say Okay Okay so this was cancelled by staff or admin the cancellation region is DMO purpose the status is cancelled okay now we can approve some booking so if I approve this confirmation if I say okay then this is booked so this is done so this is how we can manage bookings from admin and staff side so I think there is a lot of there are a lot of things you're going to see a lot of different features I think we have touched almost everything related to Blazer and related to this new blazer SSR we are using shared components we are using multiple layouts so if you go to layout we have admin layout we have inner page layout we have main page layout we are using enhanced form navigation we are using enhanced navigation we are using multiple forms on single page we are using different reusable components with multiple uh parameters we are using quick grd we are using EF code data first annotation uh data annotations code first approach we have migrations and there are so many things in this okay all right so I guess that's all about this demo now let's start working on this and this is uh it is almost more than 6 26 hours complete recording so what I have done I have broken it down into three different videos which you'll find I'll add these to a single playlist you can check this from here so the thing is YouTube only allows uh 12 hours maximum of 12 hours of video we can upload so I'm going to break it down into three different videos then I'm going to upload these so I would recommend you to go through each and everything from start to end and you will learn a lot that is for sure I'm guaranteeing you so there should there must be so many things that you will not aware of and one more thing this is not this was not planned so I stuck somewhere and I you will get to know that how I think about some things how I debug so we will stuck somewhere we will find different ways I will explain each and everything in detail that what so sometimes there were two or three different approaches to tackle one problem or tackle one one uh maybe use case so I have explained everything all right so enough talking let's directly jump to the coding okay all right so you might have already seen the demo and now we'll start working on it so I am here in Visual Studio 2022 and I'm going to create a new project so I'll select Blazer web app next then the name of the application so let's say hotel booking Blazer location is fine F let me change it hotel booking blaz okay and next then net8 yes authentication type we'll use individual accounts configure for https yes interactive render mode uh I don't know what we are going to use but let's have server only if we'll need web assembly we'll simply uh ADD web assembly later okay and do let me know in the comment if you want a separate video in that I can show you that how can you uh use the interactive web assembly or interactive auto mode with an existing Blazer application so when I say existing Blazer application that means a Blazer web app which you have created without interactivity or interactive server and now you want to add interactive Auto or interactive web assembly to that existing netblazer SSR project so do let me know in the comment I can create a dedicated video for that all right include sample pages that is fine we'll remove those pages as per our need okay so I have this default page now let's see uh I had downloaded that h template so what we have here we have index page contact booking about testimonial team service room so we'll start from index.html but before that let's see we have CSS then we have IMG with images and JS for JavaScript let's do this live I don't know maybe we are using live but we'll see what we can do so right now let's copy all of these okay and let's add these to our www root folder because from there they are going to be served right I pasted all those all right then okay after that let's see what else we have index let's have the index page here so I'm just copying it and just adding it to trip wot just just to check it I'm not going to use it in here I'll simply see how can we extract out and what is the uh structure of this page so we have had in head we have this couple of fonts then we have animate CSS how cor carel what is this T us Dominus bootst 4.css this is also using bootst 4 okay maybe these templates are old I don't know we'll see then we have this boot step. min. CSS which is coming from CSS let's see what version of bootst they using now they're using five okay okay cool then what is in style. CSS they have this separate style okay all right in body we first have this spinner then we have head then we have this Carousel booking start booking end then about section room section video section video model okay maybe we can play that video in model Services testimonials team newsletter footer and then back to top and after that we have these scripts all right all right so let's extract the code from this file to our layout and our main app. Riser page okay so for this what I'm going to do I'll go to components app. raiser which is the main entry point for our Blazer application this is the same as index.html we could say in here first We'll add the Styles so let me pin this index.html then from here let's go to head and in head we have Google web font icon font style Library style sheets boot step and style let's copy all of these come here and inside this after this I then we will simply remove the bootstrap and app. CSS which came with this Blazer web app so I'm right now I'm going to comment these out and I'll paste all those style sheets here now uh just remember we should add all these Styles before this line which is the style for hotelbooking blazer. style.css that means this is the one in which it is going to inject the component label Styles right so how it should work first we we will have the third party libraries then we will have this me this where style. CSS which came with this template which can override the this third party wendor libraries then after that we will have this component level Styles so that we can override the styles from library and from this common style in our component so this is how it should work okay after that let's again go back to index.html then we'll see what else we can add in JavaScript librar the bottom section let's copy all of these scripts and go to app. raser and we will add all these scripts at the very bottom save everything and we should be good now all right after that what we will have this spinner I don't know why they're using this spinner we should use but as we are using SSR for homepage we will use SSR that means static server side rendering there is no point of having this loader spinner right because we are not using interactivity on homepage so we can simply get rid of this thing so inside body we will directly start with this div we'll start with this Dave and add the variable bottom we will have this anchor tag which will be for back to top right that button so let's add those like this and then we'll move this routes to inside this component in the inside this container now we are good our app. rer file is ready okay now we can start working on all these sections so first thing thing let's do this let's copy all these things or maybe before that let's check what we have in header in header we have this name of the application after that we have this number let's have it in the browser so that we can see that what we are looking at so this name this section and then this menu bar so this section is the header so it should be on all the pages right so this is on all the pages if we go to home Okay so we can act move this thing to our main layout and then after that we will have this footer so we'll have this footer as well on all the the pages and I think we have subscribe newsletter as well as a part of header we could sorry footer we could say we have these two sections subscribe newsletter and this footer on the main layout and then this header on the main layout and booking yeah okay so let's do this we have this header after that we have this section which has the contact number and all the after that we have this nav bar cool all right so let's do this uh this image was also on all the pages right this image let's see if they are managing the height or size of this image because I think this same image is on the inner Pages as well right the same image or is it different no this is the same image right this background image okay they have different image they have this image Carousel here and on inner Pages they have single image let's see how they are maintaining it on this never expand this never this thing never expand home about all these things okay carel starting from here oh all right all right all right so this header we can directly move this header section to our layout so let's open components layout main layout okay in main layout we'll start our page directly from here from this header section we'll move these two sep separate components but right now we are just trying to integrate the template into our Blazer web app okay we have header after header this belongs to this car and all these sections belong to the homepage so we are not worried about these on the layout level but then we will have this newsletter and footer these between these two we will have our body header we have putter we have newsletter and in here we should have our body while render body directly then we can remove all these SC move these save these and now we should be CL now let's extract the homepage content so all these team booking Carousel we'll copy all these we'll go to our components pages is and home home. Riser page okay and here we'll paste everything now we should see this homepage with the exact same look and feel on the template we saw right let's try it out so I'm running it all right it came and it is looking great everything is working right all right let's try to uh use the complete screen for this so it might be using container class from bootstrap let's see container clue container XXL what if we remove this thing or we could say container fluid let's see how it looks now I removed it and nice yeah it is looking nice all let so we'll use this we'll use container [Music] fluid on inside direct child of body we'll use container flu and our this thing is working all right so let's go to app. Riser we have this container XXL instead of XXL we'll use container flow to save everything and we successfully integrated the abdor raser layout and our index page now we'll start extracting out the things okay okay let's create create a new folder in components folder so I'll call it first let's stop it stop the app I'll call it shared okay and in shared now we'll start adding the components so first we have this Carousel [Music] so shared I'll add a new razor component let say home carel home carel Razer let's copy this section and add it here save after that we have we have this booking start booking end so let's say booking uh this is a small form right and we had one more form which is a bigger form so let's call it booking small or booking yeah maybe booking small let's copy this booking section copy and add it here then we have about section so in shared I'll create new razor component let's say about let's copy it after that we have room start and room end so it is rooms maybe we need to revise these components but right now let's extract these out so this is uh we could say rooms let's let's copy rooms after that we have video start so let's say video video all right after that we have Services the Shar add new razor component services then we have testimonial let's create a new laser component testimonials and we'll copy this HTML to testimonials component save everything then we have teams team section the shap shed at razor component teams and we have newsletter shared add razor component newsletter after that we have footer so we'll say footer and add it okay so we have added all these uh raor components we didn't create header component right so let's create one more header so it would be header and let's copy the header as well so this head all right save everything now we can close this index.html we don't need this now now let's use these components in our main layout and home. razor page so first thing we need to access these shared components so first thing we'll do we'll add the name space into this underscore imports. Razer file so that we can directly access the these components so using hotel booking Blazer do components dot shared so save cool now let's go to our layout and Main layout on Main layout we have this header section so we'll remove this and we'll add our header component then we have newsletter so we'll use our newsletter component here after that we have footer so we'll use our footer component save and everything looks fine now let's go to homepage so components Pages home page we have this carel so let's use our home carel this component after that we have this booking so this is that booking small component then we have this about section so about after that we have room section so rooms then we have video so video component after that services this is then testimonials after that teams save everything and I'm going to run it we should see the exact same thing which we were seeing earlier we just extracted out the HTML into different different separate components that's all we did in this current thing so we have this we can see main booking about rooms I don't know what this section is called or what it should be called okay this is that video section if you click on it YouTube video opens up yeah then we have Services section testimonials teams subscriber this newsletter and then footer so everything is still same and this is also working move to top great let's continue now what we'll do uh what we should do now so because I have not planned this video I have I don't have any agenda how I'm going to proceed so you will see some uh brainstorming or maybe some thoughts around it that what should I do next and maybe we'll do something now and then we'll modify it later let's see so what we can do we can uh simply create all those pages what we can see see in the navigation menu right on this template if I open it we have this about Services rooms and all all these Pages separate pages right so let's do this let's create these separate pages our team testimonial I think we can remove these two section we don't need these because these are already on homepage but booking we we can have this okay let's have this page right now then maybe we'll set this booking form on the detail page when we'll work on this uh room detail page that room detail page is not a part of this template but we will add that form in this detail page that's what we'll do so right now let's do this about Services rooms booking and contact these 1 2 3 4 five pag Pages let's create this about service room pages so in pages I will create a new razor component this I'll say about page I'm not naming it about because we already have about in shared so okay let's do this in shared we'll rename this about to about section okay and then we'll go to homepage and we'll rename this to about section and I guess same thing we should do with rooms Services testimonials teams testimonial teams is fine services and rooms we should do the same thing for those two as well so Services section and rooms section all right go to homepage rooms section section and services section save cool now in our Pages we can create our about page so we'll just call it about and here it should be page about us okay this is going to be the uh the for this then inside this we'll see what com what uh elements we are going to have after about we will have our services page so we'll say Services then we are going to have what was that uh booking then we had contact contact and [Music] rooms RS okay let's add the routes for all these pages so this is room so here I'll say page SL rooms then for services we'll say at theate page slash Services room space then contact let's say at theate page slash contact save and booking let's say at theate page SL booking and then about we already have about us so save everything now let's add these links from uh main layout so we'll go to layout main layout and we have this header so let's go to this header and from header let's add all those links the first thing on the main name of the app so let's call it maybe I don't know hotel booking or hotel AP this is a prin okay so index.html instead of index.html we'll have simple slash so it will navigate us to the homepage after that here also we have the name so we'll say hotel AP then these are the navigation menu so we can have these like this slash slash or we can change this anchor tags to nav link nav link nav link nav link nav link and nav link I changed all of these to nav link okay now let's fix the Hrs so homage is slash this is only we can remove this active which is the default active class it will be handled by nav link then for about we know we have about us Services we have Services room we have rooms for booking we have just booking teams and testimonials we do not have these as separate pages and for for contact we just have contact so save everything and let's run it we will see the default H1 temp H1 on all those pages but at least we can see that navigation is working and all the pages are loading so we can go to about we have about us this is the about header Services okay we matched up the route it should be Services if I add s then we can see it fine rooms we can have it then home is H home is selected and rooms is selected both of these are selected if I go to about about is selected home is selected why so this is because how this nav link adds that active class it uses uh match so for this match we can use nav link match so it is a enim which has two values one is all one is prefix the default is prefix how it is working right now if we are on the about page the URL it creates it is slash about us so first it matches slash which is for home then it matches this about us which is for about page so it considers that this page belongs to both of these routes both of these navigations that's why it is adding active class to both of these okay so but this one the first one slash we need to tell it that just match this only so nav link match. all we will use all that means the complete URL it will check if the complete URL is slash when we say URL this is path actually so after domain or we could say after Local Host colum Port after that whatever it is it is going to check that if that is just slash then only apply active to this thing now if we save it and we should add this thing on all other nav links as well we have anchor tag only for there and this one so save and let's f Services URL as well services save everything and let's open that again you see now it is only on about if you go to home it is home about Services rooms booking and contact okay so URL is working pages are getting loaded and the active class is getting applied correctly so we are good all right now let's start adding the contents for these about Services rooms and all these pages so I'm going to stop it stop everything save and let's check the template so in template let's start adding let's add all these pages in our project we are going to delete these Pages I'm just having these inside this so that I can easily check the HTML and copy the HTML to our razor components okay okay so I'm going to copy all these Pages add these here for now so let's start from about so the head section is right after that loader not loader yeah this spinner then we have this header and after header we have this page header start then booking start about teams newsletter and footer so what that means is foter newsletter and this thing this is already in our main layout and ABD raser then this header is already in our main layout we just need to have these sections on our about page okay so this page header start this is the main page header what is it page about Li page header start let's check what we had on about page so if I go to about page okay these things okay and if I go to Services Pages services so you see this section if you can see this section this is common across all these uh we could say inner Pages non homepages right so we have the same background image we have name of the page we have this breadcrumb after that we have this booking form so this thing is common on contact yes this section is common so we can extract this out in a layout now the problem is if we extract this to main layout then on homepage that section does not belong on homepage right belong to the homeage page so we cannot use main layout for this we can use another layout but if we use some other layout then we need to copy the same thing which we have on the main layout because the main header this contact Section and that footer section and that subscribe newsletter section all these also going to be part of this the second layout right so what we can do in this case in Blazer we can have nested layouts okay so what I mean by nested layout I already have this main layout in the same folder I'm going to create a new razor component and I'll call it inner page layout okay so for any layout first thing it should Implement layout component base if you see on Main layout it will be doing the same okay after that we can set layout for the layout as well okay so this is interface layout we'll say layout main layout that means this layout this inner page layout also has a layout which is this main page main layout so now what is going to happen if we check main layout we have header we have newsletter we have footer inside that we have this body so that nested layout that is going to be rendered at the place of this body so the header newsletter footer it will be there and then body which is in this case it will be inner page layout and inner page layout now we can go to about and we can simply extract this thing page header start we can add it here here and after that the actual page thing booking start is also a part of that right so here also we can say booking small we already have this component after that we can start adding our actual content so that means because this is a layout so we will say that whatever content we have we will simply use atate body so now all the pages can use this layout which is the inner page layout let's see this if we go to about page not about section about page on this page if we do not add any layout by default it uses main layout but for this we will tell it that don't use main layout use inner layout inner layout now it is not coming in the page layout right we need to add the using and if you want to use it everywhere we can simply cut this using and add it to uncore imports. rer so that we can use it throughout our Blazer Razer Pages now we can use this inner page layout like this okay let's see what we had after the layout we had about and teams okay on this we can say about section and team section save and we should be good now let's try it out I'm going to run it there is some error what is it inner page layout cannot have multiple base classes what is the issue in a p layout main layout class inner P layout cannot have multiple base classes component base and layout component base somehow it is thinking it as a component but why layout component base oh not implements it should be in my bad inherits in layout component B okay run it okay we have homepage we have about page with the actual thing whatever we need to have cool now let's work on other Pages as well but before that now you see we have this about us and this breadcrumb this is kind of fixed because we added these directly to this uh inner page layout right but these links and this heading these are Dynamic so we need to find a way by which we can make these two sections Dynamic so we can have sections right we can try out sections what we'll do we have two approaches either we can simply create this as a separate component and then we can remove this from here and we can use that separate component on all the inner pages and we'll simply pass the these parameters we will have this about us and all this section as parameters but that is not what we are going to do what we'll do here we will do we will add sections so instead of this about us here I'll use a section outlet with Section name and I'll say let's say page name okay and then we can use this page name on our inner page so let's go to the about page and here what we'll do we'll use section content with Section name so that it belongs to that same section what was that page page name so page name and we can add about us any same thing we can do for other pages so for example for booking page we'll do this but before that Let's do let's copy these two things layout and this so we'll go to booking page we'll do this and the text we'll use booking then contact we'll use contact us then rooms we'll use rooms then we have services so we'll say our services and one more thing if you want you can we are repeating this layer out for all these inner pages right there is one more approach if you want to try that out you can addore Imports page to this Pages folder uh sorry H yeah this Pages folder we can create underscore imports. Razer and we can add this layout on that Imports _ imports. rer then it will be applicable for all these pages in that case we just need to go to the homepage and explicitly Define atate layout main layout because for home page if we addore imports. rer it will force that layout to all the pages but for homepage we don't need inner layout we need main layout so for this one we will add layout main layout and we will remove that layout from all other pages that is also an approach you can try that out as well but I'll continue with this approach but I'm currently using let's run the application and we can at least see the page header that page name on that inner Pages let's see this is homepage about us our services rooms booking contact us so that means this thing is working and this is dynamic okay then this section as well we need to modify right home pages about us room services and there is no point of having pages in between right we can directly have home and above and because we directly have the two sections we can simply remove this if you want to you can have it there is no problem you can create one more section and you can use that section but for us there's no point of having this pages in between we can directly have home and about about is the same page and home is actually we could go from navigation menu or by clicking the main name of the application it will lead us to the homepage so we are good we can remove that this uh Brad Crum action okay you can try it out if you struck you can uh add a comment in this video I will try to help you out okay what we'll do we'll go to interface layout and we will simply delete this bradom actually all right so save everything and now we are good cool now let's start adding the actual content to all these razor pages so for these let me do this I'll close all the tabs first thing then we'll start working one by one so about we already set let's go to booking we had header then page header then booking start and again booking start this is different section then newsletter putter so that means this first booking start this is that booking small and this one this is the actual booking form so we'll copy this and we'll go to our booking page which is in our components Pages booking and we'll add that HTML here we'll extract this out as well into a separate component but right now let's have it like this only let's close these Pages then we'll go to contact let's see what we have in contact we have headers we have page header we have booking stat then we have contact Section so let's copy this contact Section and let's go to our contact page and let's add it here cool save everything close these Pages after contact we have room so let's say what we have on room booking start room start testimonial newsletter so on rooms page we have rooms and then we have testimonial so if you see in rooms we already have a room section the only difference is on room section it has three items but on the separate dedicated rooms page it is going to have six items right so what we can do right now let's have this thing only later we will extract that rooms list into a separate component and we will pass the dynamic data which which we fetch from our database and at that time we can Define the number of rooms we are going to display there right so for now let's have these rooms or maybe yeah let's have these rooms directly on rooms page where is Rooms page okay and after that it had testimonial section so testimon save everything after rooms we have Services page on Services after header page start routin start we have services and testimonials these two section so let's go to services so here we'll have Services section and testimonial section save all right after the teams we have not created testimonial page we have not created so I think we are good let's save everything and let's run it okay about we have this about section Services explore our services we have our services section rooms we have our rooms section booking we have our booking section contact we have our contact Section and everything looks fine now cool we have integrated all the pages which came with this template all right after this okay right now it has these some static information we'll made these also Dynamic maybe we'll get these from App setting configuration or maybe from database we can create a page on admin panel side for these things as well so the email ID contact number okay all right let's see what next we can do I think we should move to our backend now right because the main uh template integration that is done that means we can at least see the things now what we'll do we'll simply start by adding our uh entities first but before that let's clean uh this out we added all these about HTML all these HTML pages so let's delete these Pages now we don't need all these pages so let me delete and scss file also uh this folder also we can delete then we are not using this boot step folder it was added from our Blazer web app we are using from this CSS and then this app. CSS this is what we added or we could say this Blazer web template added so we can delete this file as well from here we will simply get this Blazer error boundary we will copy this thing and we'll add it to the style. CSS inside CSS folder which we got from template so we can have this here at the very end We'll add this and then we can remove this app CSS delete and we are good now okay H now let's start working on entities but before that let's see the design and we'll see what all things we want okay so this thing can be left like this only we'll have these things but after that about us these things also we can make these Dynamic all these we can have a maybe some config table and we can manage these from there only then comes explore our rooms so that means the main thing is room here okay but before room we will have our users so for users we can have three type of users in this application right one would be the admin the main admin who owns this product this website who can see each and everything inside this product each and every screen he can visit then we will have one staff role so staff maybe we will have some restricted access to stuff they can maybe uh create bookings and apart from that what else they can do maybe they can uh manage rooms as well and then we will have the guests that means the end user who is coming to book hotel room so we will have three set of users so in data folder let's create a new folder and I'm going to call it entities okay let's go there and we are using asp.net core identity so the roles table it will we will use the identity role only so there is no point of creating role to the this uh uh a new entity for rules there is no point of having that but we will go to application user and what we'll do we will add additional information to this application user by default this identity user this is going to have only user name it is going to have just username email normalized email all these information which we don't need right now we will just need to have access to this email which ID and email which we will get from the base application user but we will add the actual name so we are going to have name and we can have first name and last name as well if you want so let's have first name and last last name okay and apart from this we can have one property for role name as well although we can get it from Identity role but when we'll create the user we will simply have a normalized uh role name the simple string so that we can directly use this role name if we want to display somewhere we can use this so if this is admin or maybe staff or maybe guest we can use this directly okay after that let's add some data annotations so this is going to be required and max length we will allow in first name maybe I don't know 15 it's a lot let's have 10 only and then we can have a pattern which will be regular expression we do not want any special character in first name okay so here we can say that it just should be a to z and A to Z the lower and upper case A to Z nothing else so it should start from here and it it should have at least one character in here and it should end at this place okay cool then we will come here and for the last name it is going to be n label and we will have max length again 10 then role name it will be required and it will be with the max length of what was the admin guest staff let's have eight I don't know what was that s t a f f 2 2 4 5 g u s t 2 2 4 5 and H doain 2 3 5 five only so let okay let's have 10 and I think we are good we have our application user ready now we need to add migration for this we will add a separate migration for this one then we'll add our entities then we'll add our separate migration for other entities as well so adding migration for this we'll go to package manager console and we'll create we'll run a command add migration and the name is up to you you can name this migration whatever you want I will say add name Ru to application user succeeded and it is here let's see we have first name and we 10 last name role name and H okay so save we are good we added migration for adding these three columns and uh first name is notable role is not aable but last name isable right yes all right so we have our application user ready now after this let's start on other entities in entities I'll create a new class do we need other information as well for application user [Music] H so let's say we have staff or admin or guest right now we are just having first name last name email password nothing else we should have uh contact number at least contact number we should have for sure right H we should have contact number as well so let's go to application user let's add one more so string we'll say contact number and this also we are going to have it required and max length 15 okay and then we can have regular expression for this as well so we'll say that H it just should have 0 to 9 and then in India this is fine we just need 0 to 9 nothing else but for other countries we might need plus and then this parenthesis and then space we need these as well so I think we are good you can modify this is not uh 100% accurate but this can do our job it is not going to allow other things but we are good with this and after this we had this required and first name so this if you go to our latest migration these are n worker right we don't want to add any special character anything to this we can have this Ware only that means we can say Unicode false these are not going to unic code so we can modify these things previous ones and we can add this uni code Falls to this one so now all of these fields are going to be workare not andw and does this these plus and these things comes under uni code or no I don't know let's remove this from here but save and let's uh create one more migration here we'll say add contact number this migration should alter previous columns yes now it is worker eight earlier it was n worker worker worker and it is going to add a new column contact number cool save everything all right all right now let's add other entities so we might change these entities later so I'm just uh I am not preparing it so I do not have any thought how I'm going to approach these entities but whatever comes in my mind right now I'm going to use those only we might modify these on entities on the way or maybe you can think of some other approach for these as well so we could have different uh thought process for creating these entities so we are good the main goal is to uh complete the application to run that application with all the features which we are saying and which we want to add okay so let's add a room entity for this room entity we can have integer ID we can have name description tool room level what is this level room type I don't know what is this room type I'm just having these suggestions room name okay let's see in our template what all we can grab from there so for rooms we will have name then we'll have image we'll have description and we'll have price 1 2 3 4 these four things we are going to have for sure and ID so ID name price image description ID name description string image and decimal price and then description then room label and room type this is a simple site we are not going to have any any room type or room level right save after that we have these features we'll add these okay let's think about this but right now we are good with this let's have some audit properties right now so we'll say bu is active if this room is active then we'll say date time added on when this room was added to the system then we'll have who added this so we'll say added by after that we can have last updated on and last updated by and both of these things are going to be nullable after that what we can do we can have a helper property helper column of type bu where we'll say is available so that we can simply display this on our homepage or maybe on our rooms page where uh the guest can check the room and guest can book this room okay H and now I need to think there's one case let me think about it so what I am thinking are we going to add all the rooms if I have let's say 20 or 50 rooms am I going to add all of those so the name maybe the number can be diff your number will be different right yeah the number will be different so we can have this name as a room number yeah for for now let's have it like this only if we will uh need to modify this with some other approach on the way then we'll sa okay right now let's have it like this only cool now we have these navigation properties in this added and last updated so let's have added h we'll have added by so we'll say application user and this would be added by user and we'll make it virtual cool added by user this is from this added by so we can tell it that foreign key is going to be this added by and we are good with this one so room is ready we have image we have all this what these are saying show potential fix what is suggestion what is potential fix oh the labor I don't want this okay so this is going to be key primary key for our entity which is fine uh by the way I love data annotations I use data annotations most of the time if you do not like this data annotation you are free to go to application DB context and just override on model creating and after base. on model creating you can have your model configuration here okay I like this approach so I use data annotations all the time all right so name is required and let's have a max length of maybe 25 not more than this image is also required and it is again going to have a max length of maybe 100 not not more than this price is required and for this we can have range which will be from it can't be zero but let let's start from one to maybe I don't know double do Max double dot Max why we use this method group to me so this is not that Max Max value okay so description is also required and it will have a max length of let's say 200 is active is available added on added by everything looks okay after this cool let's see what other entity we need let's check the template we have this section this three bed two bathroom Wi-Fi so all these uh let's say amenities so what we'll do we'll create a a table amenity table so public class amenity I hope this spelling is correct then and we can have an ID and then string name and we could have string icon so this icon in this particular case we can see these icons okay and fine now we need to map this is a master table for amuni okay and then we can map these rooms and amenities so for this okay we need to think about numbers what I mean is that amenity table that is going to have this bath which is we could say bathroom this Wi-Fi then this bed but this number three this number two all these things we should uh okay have this unit as well so okay okay let's see so what we can do we can have a class here the one table for we will say room Amity which is mapping so so how this is going to map in this we will have room ID then we will have uh amenity ID and both of these will create the primary key for this table so this is one case where I go to the model builder that fluent API to configure this entity although we can do this when we have composite uh key when we have a collection of columns for a primary key we could set this column then we can Define that the order zero for this this is going to be key and then we can do same thing for this one like this but for this particular thing when we have a primary key is a combination of multiple uh columns then I use this approach so here I'll map this so I'll say model builder which is builder in this case so Builder do entity and this is going to be room amenity this entity and this has p and this is a object with RM sorry not RM r. room ID and ra dot amenity ID so this is our primary key for this this table all right okay on name let's okay let's let's add data anation on Amity first so this is going to be key which is default if we have a property inside a class with Name ID it automatically considers it as primary key for the table and if that is Amity ID then also it will consider it as key but I like to set explicit annotations so it will be I have assigned it explicitly that this is the key for this table all right for name this is going to be required which is actually required because we are not using theable string but still I like to use explicit annotations so required after that we can set max length and this is Amity name so maybe 50 my not it's let's have it like 25 that's fine then for icon let's have it as required and Max 25 for this as well okay now room Amity we have these primary key after that let's have that number and I don't know what we should call that and it should be nullable because maybe uh it can be example for Wi-Fi we don't need to set anything that there this room has one Wi-Fi or two Wi-Fi there's no point of that but for bedroom yes for beds yes for bathroom yes we need to specify that it has two bathro three bathro or two bed three bed and all those so we can have it nullable if the value is null we will not we will directly display the amenity name for example Wi-Fi and if we have this value then we'll display The Amity name with this number so I don't know what I should call it maybe unit I don't know let's have it unit do let me know in the comment what should have I named it this problem okay and then because these two room ID and Amity ID these are going to be a reference from Amity table and room table so let's use these as uh navigation property so here we'll say public room and then public amenity amenity to define the relationship then let's add these virtual so that these can be lasery loaded virtual okay [Music] and maybe for this room uh I don't know maybe we should change this because the way I am seeing it maybe this can be the category of room or the type of room room type or category type room category something like this and then we can have maybe five rooms of this category of this room type we could have three rooms of this type right so yes we should yeah we should do this right so here we should we can have public class room type this is going to be let's use short because room types cannot be that much then we'll have name room type name basically and that's all I guess let's have the is active and added by Modified by and all these properties is available there is no point of having this inside this ID name and all others fine now let's make it required and max length uh maybe 50 so this is room type and now room class this is when we have this name it should be actually room number I'm having it as string because maybe they can can have it a202 something like this so let's have it as string okay and then image H we can extract this image and price or maybe all these things yeah maybe we can extract all these things out from this table room and all these can be added to room type which we could say room category or room type do let me know in the comment what you would prefer should it be room type or room category okay so ID room number after that let's cut everything out and add these here in the room type because the description the price everything can be set on room type level and then room will simply we will have that this particular category or this type of room has uh six rooms right so there we can set the room numbers that this is a 2011 202 203 204 something like this we can have this room number here and then is available we should uh we can have this here this is going to be a kind of uh computed value out of this room table so here first let's have ID then have room type so here we will say public short room type ID okay and this is also going to be required which is actually required so let's remove this so in this room type if we have this these room numbers and now here we can have that is available property is available right and then this is available on the room type level this should be let's have for let's consider that this room type ID for this room type we have five rooms okay so this is going to have five different rows let's say four are available and one is or let's say four are already taken and one is available so in this room type this Avail is available is going to be true because there is still one room left inside this room type if we have five rooms and all are taken then this is available is going to be false we could use this or maybe we can uh maybe we can remove this from here we'll see if if we think if I think that at that level when when we'll reach at that level if we need that then we can add that uh this property in that room type class okay so here in room ID room type ID room number is available and now this room amenity it should be room type amenity because if we have one type of room let's say uh single bed AC room this is a room type so that room type all the rooms which falls under that room type those are going to have the same amenities so that's why this Amun this should be room type Amun now we'll change it to short and this is going to be room type ID and this is going to be room type this is again going to be room type and we'll go to our DB context here we'll say room type amenity and then room type ID yeah now it makes more sense so that is what I was telling that this is not planned so we might change so many things on the way when we so using this you can know how I think maybe how I approach things on the Fly basically all right okay now we have these classes in room do we need any other things ID room type ID room number is available and what else we can have I think this is fine after that after that what we can have what we need about from this room related things we will have let's work on bookings okay let's work on bookings now so we already have application user which is the user for guest also that is going to be the user so now we will have public class booking okay now in this first we will have a booking ID so I'm taking it as long after that for this booking we will have room ID this is going to be room ID because we are going to allot room to some guest not the room type okay we can get room type details from this room ID we have room ID after that we are going to have user ID so in this case we'll call it guest ID okay we'll have guest ID I room ID guest ID and then H okay we need to have other properties as well in the room type you remember we have this thing checkin date check out date then we have this adults and child so that that means we should have some logic or some property or column in which we can Define that this particular room can have at most two adults or three adults and two child or three child or maybe something like this if I go to Rooms no what was it booking here what I have name name check in select adult select child then select room then special request this is [Music] different H yeah we should have these two things right so let's add these two as well and these can be defined on room type level only because one type of room can have uh this setting so for this after description we can and say public in Max adults and then we'll have one more we'll say Max child or children okay this room type can have maximum this two or three adults and two or three children something like this okay okay we'll see if we need to change this or we are good with this fine now we are bookings we have guest ready after that we can have in adults then we can have int children and then we can have date time checkin date and check out date okay and then we can have that special request what was that name special request special request yes or we can name it some remarks maybe and this is going to be n label and then uh yes we can have one more and that is going to be when was this booking uh generated or created right we will say let's say booked at or what approach We are following at or on updated on added on so booked on booked on okay looks like we are reaching somewhere okay this can have one more field which is going to be decimal total amount okay total price which uh was paid for this booking now the payment related columns field we will add later when we'll work on payments okay so for now I guess we are good then this room ID and guest ID let's add navigation properties so first we will have room room then we'll have guest which is going to be our application user guest and both of these are going to be virtual fine after that this ID is actually key guest ID this is required and and total amount same thing this should be uh range one comma double do max value this is just for simple validation so that we don't add we don't insert some invalid value for this that's all we are using this range for and then okay we are good I think is something missing inside this yes it is missing uh or no it is not missing anything right everything is in place okay we'll see if there is some missing piece if we'll reach that point then we'll fit this all right so I guess we are good right they can boot can do all these things this is going to be filtration on homepage we have this section which is fixed we have this section which is fixed this thing we can get from our tables if you want so number of rooms number of Staff number of clients that means gets guests all these things we can get from our tables explore our rooms we can have our rooms image price room type name amenities description then I don't know how we can use this section maybe we'll remove this section then comes our services so we can have these fixed or maybe if we want to make this Dynamic we can have table for these as well and this only static if this video does not get so much long then maybe we'll create entity and tables for this one and we'll add one dedicated screen for this in our admin panel okay testimonials maybe uh we can show one form for the guest when they log in to their account there we can display this form so that they can add their uh experience then comes staff so the staff this is going to be okay name and designation so in application user we should have designation and we should have image as well well yes we should have image as well all right so let's for this uh this testimonial we'll work on this when we'll reach at this point but first let's add the image Avatar and designation to application user okay so where is our application user is here s contact number we could say string and designation which is going to be a label not required but we'll have a max length of maybe 50 only then uni code fals and there is one moreat image so public string and image and let's have this also as a label say max length as 100 for room image we have max length description let's add unic code falls to the images as well and here uni code fals and if we go further is there any other string property added why this is required then and room name uni Code false then amenity uni Code false booking special remarks first we'll have max length of maybe 150 not more than 150 then uni Code false on this one as well okay I guess we are good save everything and let's move these types to their separate classes okay so I'll use this refactoring move type to room type room is already here then we'll move amenity okay this icon as well let's have uni Code false and then amenity move to type to ammun room ammun booking save everything and we are good now right so now we need to add the migration right now all these are simple classes these are not bound to EF core or rdb context that's why if we run migration right now nothing is going to happen we need to bind these types to our application DB context and we have two approaches for this either we can have these as a DB set properties DB set room type room types and this room type amenity this is already going to add to this uh DB context so how this works you need to do one of these things either add the type as DB set property or use that type in on model creating with this builder. entity and do anything with this so it will attach that class to this DB context and then when you'll run the migrations it will add the migration for that particular type okay so we have room types after that what we have amenity but before that we have rooms so room and then we have amenity amenities then we have room type Amun we can have room type amenities and after that we have booking bookings and we need to have users as well so for that what we can do we can access the application users using this or maybe we can use user manager to fatch the users we'll use user manager and I don't know if we can directly yeah user manager should give us I variable right it gives us I variable let's try I'm just testing it checking it right now what it gives us if I go to login I'm just trying to see if I need to add user specific property in DB context or no login context login you password sign in where is user manager sign in manager okay maybe on register page yes we have user manager dot users this is I variable okay we can apply where and all those things here all right okay we are good we are good we are good all right now we have added these DB sets in here but when we will access the room type access amenities as well right so inside this let's add that also so here we will add uh virtual I collection of room type Amity amenities so that when I will access room type at that time I can directly access list of amenities that's why I'm using it like this all right let's see if everything is fine and we can uh create our migration or no okay so here I'll say h migration and this is going to be let's say [Music] entities Hotel entity or let's say add entities let's see if there is some issue or everything is fine we succeeded and then all right okay all the These Warnings these are related to the uh decimal columns so we are good if you want to fix these we can use has Precision or has column type has Precision I think there is some data annotation level property as well for this first let's see what we have in uh migration so for aspet user we are adding designation then we are using adding image then amenities table we are creating which has ID name icon with primary key amenities fine then we have rooms table which will have ID in identity room type ID room number and is available we have primary key PK rooms then we have room types ID image price description Max adults Max children is active added on added by last updated on and we have this foreign key in rooms this room type ID this should be a foreign key room table if I go to room okay this room type ID I should have added that so this is missing I'll add one more migration so you see this checking this makes sense if you have followed previous tutorial that complete full stack blog application using netblazer SSR there also we had one problem with one of the type and it cost us uh a lot of time basically to check there was that problem if we could have checked the migration we could have detected that problem earlier all right so we have one problem now we'll fix it after that we have room types everything is fine in room types we have added by uh this foreign key after that we have bookings ID room ID guest ID adults children checkin date check out total amount booked on remarks H primary key bookings foreign key guest ID and and room ID which is fine then we have room type amenities room ID amenity ID unit and it has two foreign Keys fine then it is creating couple of indexes so we are good this migration looks fine only thing is this room it should have a property of type room type we'll say room type and let's make it virtual and it is room type ID so we should be good with this right room type has short ID short ID yes all let save it and let's add one more migration so for this we'll say add or let's say fix room type or maybe room room type navigation something like this or we could have said maybe uh fixed room type uh foreign key something like this okay so it is creating an index and adding a foreign key for rooms room type ID so we are good save everything and now everything is fine our database is pretty much ready for basic operation I think maybe not basic it should have uh maybe I don't know maybe it has covered all the cases or maybe there might be couple of cases missing we'll fix those when we'll encounter some problem and or we'll reach at that point okay so now first thing what I want to run on the database side I just want to run these migrations on the database so for that first thing I will fix the connection string so I'm in app settings. Json I'll fix it so I'll add it dot which is my server then database I'll name it portal booking Blazer only I'll remove other things Ted connection true multiple active result sets true then I'll use encrypt false I'm using it on local so I don't want encryption encrypt true and and we are good let's run these migration on the database so for that we can use update database command update database like this and now it will create database and run all these migrations which is and we have some errors what is the errors a connection established but is there an error occurred during the login process the certificate chain yeah that's why I added this encrypt oh sorry encrypt false I don't want this encryption so by default starting from ef7 these connction strings for EF core these are by default encrypt true I need to set it to false update database queries on the database there is some errors the error is failed executing DB command room rooms room types room type ID on table rooms we cause a cycle or multiple Cascade paths if I go to data room I have this room type know that this okay I should have changed it to referential action dot maybe no action first let's see what all tables it created so I'll use server Explorer here let's refresh this and add a new connection Microsoft SQL Server continue server dot Windows authentication yes option false first database what is the database name portal booking Blazer okay so here I'll check I have migration stre amenities these are ESP net then bookings rooms room type room types if I check here Amil amities so table data there is going to be nothing in this table I just want to see ID name icon okay after that we have bookings from here then we have room then we have room type room room type and then we have room type amenity room type amenities okay that means everything is fine just that index or that is not created [Music] ID rooms how can we verify the h remarks booked checked guest ID properties I don't know how can we check the keys here foreign keys and all those things okay let's do this for this one we'll say referential action Cascade instead of cascade we'll say no action so for this we can go to our application DB context here we will have Builder do entity of room it has or maybe on room type dot has many in room type did I add room navigation property collection of amenities on room type let's add one more collection for room rooms so has many RT RT do room and this is let's say with one and then delete delete Behavior dot let's say no action do we have update Behavior as well on no we just have on delete right so we have is good let's see if it helps save package manager console we'll add a new migration for this so we'll say add migration room type room delete no action something like this both relationship between room and room types do room and between room. room types could use room type ISD as the foreign key to resolve this configure the foreign Key Properties explicitly what what first let's say with one r dot room type if I do this just dropping that and adding this new foreign key let's try to run update database command again update database and we still have that problem introd for constraint rooms room types room type ID on table rooms make or cyles or multiple casket Parts maybe I'm missing something let me see what am I missing so I did some research search and I uh read a couple of particles read couple of stack Overflow post so I found out that this thing if we have uh this error in one of the previous migration and then even if we fix this it does not we could say it does not pick up because it has the incorrect uh mapping in one of the previous migrations it will throw error the solution is is two we will keep on reverting removing the migrations which we already added until we get that uh error that says that it can't revert now and then we'll create a new migration and at that time it will pick up the latest thing so let's try it out so I'll say remove migration and I'll keep on doing this remove migration it removed it again remove migration and all right again remove migration so you don't need to do all of these things because the source code you will get you will have the final actual migration which will not have this mapping issue so you would be able to directly run it this is just for debugging or we could say the fixing it in the first place now we got this error that this is already apply to database it cannot revert it now we are good now if you check it actually deleted all these migrations now we'll create a new migration we'll say add migration we can name it whatever let's say fix and now it has generated now now if we try to update the database update database do we have that application context delete Behavior no action yes update database run let's see if it works and it worked okay cool so we have our database ready we have our mappings ready so everything is ready now we can now start working further before that let me push these changes to my GitHub now what we'll do first let's uh create the super admin user first okay so for that what we can do for creating that we can have a seeding service which will seed the database with the admin user so for this I'm creating a new folder first I'll call it services and here I'll say this is going to be a class with the name let's say seed service seed service okay and we already have DV contact registered right yes so let's inject this and because we are working in Blazer so sometimes there could be raise condition multiple uh threads comes and try to access the same service at the same time we could have the problem because the DB context by default it can be accessed by only a single thread so we can have exception so it's recommended in Blazer to use DB context Factory instead of injecting direct DB context so for that what we can do where we have this builder. services. add DB context which was added by ASP netore identity when we created this project so we'll modify this and we'll say add DB context factory factory okay so we can use this now we'll go to our seed service here we'll say oh do we need this here I don't think we need this here we need to se the admin user yes we need to se the admin us for this we don't need the DB context but because the point here is this aspnet core identity it uses multiple tables with so many settings and all these things so instead of adding all that data manually we will use the approach they take using that uh user manager user store role manager Ro store which were given by ASP net core identity only so if we go to components accounts pages and if you go to register. Riser page here here this was automatically generated by BP netcore identity when we created this project so here you see we have all these configuration there is a lot of things so we're creating user creating an instance of application user then using user store to set the username email store set email create user all these things okay so we'll follow the same approach all right so we are here on SE service we can inject all those things so first we need to have user manager of type application user that is our user so here we'll say user manager after that we'll say I user store of type application user underscore not underscore user store okay then we will add role manager and this will be of type identity role which is default role class we can override it the same way we have application user if we want to add any additional information to role we can override uh we can create a new class which will be a subass of identity role so if you check application User it's Base Class is identity user so using this application user derived class we can add additional properties which we want in our identity user so same way we can follow for identity rule if we want but we don't need any additional information in rle so we are good with this we have this role manager manager then we will have IR Ru store we'll see what all we need right now I don't know what all we will need but we'll see what all we need and then we'll modify these accordingly we'll remove or add other services so roll store and I think we are good let's create Fields so user store roll manager and roll store all right we have all this information here now we'll create a method here public ASN task and we'll say seed database async all right now for this users credentials in my previous video with blazer ssrn net 8 that uh blazing blog version two so that was the complete full stack blog application if you want to check out I will drop the link of that video in my pin comment and description so please do check that out that has a complete uh huge course I think around 10 hours of course in which we have gone through from scratch to and we will we have built the complete fullstack blog application there for admin credentials I have used direct hardcoded values here but in this case what I'm going to do in this current project with will get those from configuration I am adding those in app settings. Json only here let's say admin user or maybe we can have one users and here I can have or let's say I'm going to use only single value right so let's call it admin user okay here we could have couple of things so name let's use my name only AB Prince then email we'll use that username so here we will say AB at blazing blazing Hotel yeah we should name it blazing hotel right that's what we are following blazing ad blazing Blog then blazing Hotel yeah let let's change it so I add blazing hotel.com then name email what else we need we need password now this is just dummy simple thing so you could have one approach that either you cannot have these in app settings you can provide it from other source or we you can uh have have it here for the basic initial setup and when your application runs for the first time at that time you can uh show a change password screen to the admin user so they can simply Mod change the password so that we won't have this issue there are multiple approaches to tackle this so here I'll have some strong password so I'll say let's say atate AB 1 2 3 and it has everything right special character then Capital uppercase lower case and numbers right so 1 2 3 4 5 6 7 8 9 so we can force the password uh format using this identity uh settings from here but we will go with the default so default needs all these things that it should have one special character numeric values and then uppercase and lowercase combination of character you can modify this if you want cool so I'll have this now in order to access this we have multiple approaches we can use options pattern do let me know in the comment if you already know about options pattern if you don't know about options pattern I can make a dedicated ated video for that options pattern so I'm not going to use that options pattern in this particular video do let me know in the comment if you already know it or you don't know about it you want me to create a dedicated video for that we can have a small tutorial of maybe 15 20 minutes so that I can explain that in detail how can we use this options also we have uh three types of options so one options are we can we will inject these and the these will be the same we cannot modify these or we could say we can modify these but it will not pick up the latest values and there is one type of option pattern in which we will have these and whenever we modify anything here it will automatically pick the new values and it will use those all right so in this particular thing I'm going to access this manually so when I say manually I'll go to seed service and I will inject I configuration okay so I'll use this configuration and from here I'll get the admin database values so here what I'll do I'll say word admin user email something like this okay let's access this so we can access this from configuration dot get and yes we can get string and the value we will need this will be admin user colon email okay so get value like this this is a short hand of configuration. get Section admin user. get value this thing so this is a short hand we don't need to have those get section and get value we can directly have get value and we can uh uh separate sections using colum all right now we have this admin user email here now we'll check if this email already exists that means we already seeded the database or we already seed this admin user already then we'll simply skip it for this what we can do we can sa uh DB admin user so here we could say user manager dot find by email async and then admin user email we will await it now we will check if DB admin user is not null that means we have this value so we don't need to do anything we'll directly return from here we'll say database already has uh admin user no need to do anything and we'll directly return from here cool now if that's not the case then we will follow the same approach which is being followed on register. Riser page okay so we can use that thing here we will say first we'll create our user so we'll say where application user equals new application user this one which is our application user identity users derived application user now we'll add values okay we can directly use this like this oh okay we have first name and last name where is application user first name and last name okay so we need to modify our setting I'll say first name first name and last name first name is AB last name is Prince all right so here I'll say first name equals we can follow this admin user first name then we'll say last name then we'll say email is from there so we don't need to set explicit email it will be set by The Next Step which we'll take so we'll add the values here which we have added to application user directly we will not add identity user values so we have first name last name then we have role name so role name this will be using we have role right did we create rule entities and we did not create user uh roles all right so let's create a new folder and let's call it Conant cons T and constants I'm going to although this is not constant but enms we could say these are kind of constants so here I'll say r or let's say roll type so it will be public enum Ro type and here I'll say super admin or we could say admin after admin we are going to have staff and then we are going to have guest all right let's add this name space to our did we create Global usings no right okay maybe we don't need this everywhere we'll see if we need this so Ro type we can use this Ro type inm directly in seed service so here we'll say Ro type dot admin. two string after roll what else we need we need contact number so for this also we can go to our settings and we can add one contact number so here we'll say contact number it can be any contact number so contact number equals like this then we have designation and image so designation is actually admin so we can directly say this is administrator administrator then we have image so right now we don't have any image so we can skip this we'll work on this later I guess we have added all these values let's use this admin user last name contact number and this is telling us that this was be a label so we know these are not going to be nullable if these are nullable if this is null so we will simply it will throw exception and we are okay with that because that should not allow this because we need at least one admin user in our application to it to run successfully basically all right so we have application user ready here after this what we'll say we'll say user store dot set username isnc it needs application user so that we have here application user then it needs username so for these usernames are email ID actually so for this what we can use we can use this admin user email we'll await it and then cancellation token so we can provide default so now we have set username async after that we'll set the email so for that we need to have access to email store which is actually uh if we go to register page we have this thing email store which is G email store if you go here we have this thing I user email store of type application user we can convert user store to this type we can cast it to this type and this is actually underscore user store so now we have email store and on email store we can say set email isnc okay let's AIT this as well now wait and we have set email store set email store application user same thing right after that we'll simply say create user async so let's copy this section here we'll say result equals uncore user manager. create async user which is our application user and the password we can get from our configuration so we'll get the password from our configuration like this all right now we have result if there is some problem with this result if it was not able to create this user we will simply say that result consider this section we can get the errors this errors is actually a collection of I numerable of identity error so we can say errors equals result. errors dot select e do we have description so now we can merge this into a single string so we'll say string do join with the maybe comma or maybe environment. new line and then we will have all these errors here we have errors here we will return from here uh we can simply Pro exception from here so Pro new uh I don't know what type of exception it could be but we can have just exception so message and inner exception so we are good with message only all right now if this was succeeded after this we will check if we already have admin role uh added to our database so for this we'll do the same thing we did for admin user we try to find this user by email so here we'll say were or we can directly add a if statement here we'll say await role manager dot find by name async and the name we are looking for is admin okay we should add all the roles at the same time right yes we should all right so here we will say rooll type do admin. two string if this is null that means we do not have role in our database so for after this what we'll do we will insert all our roles to the database so for this we can say for each allthough we we have only three rules we can use these one by one but let's have some fancy approach we'll make a dynamic so here we are saying the roll in we'll say enm do get values and we can Define the enm is our role type so get values it will return rule type array so this r Ro is actually Ro type get value get names so this is role name String role name and we can use role manager dot create a sync and we'll create a role and this should be identity role okay here we could say R equals new identity role identity role identity rule H and here we can have name equals rule name and then we can simply create a sync this will be R we can AIT it it will create one by one or we could have these in a collection and then run uh task. van all kind of thing but we are good with this one by one so now it will create all our roles we have three roles so it will create all these three roles in the database after that now we have ready we have our user ready we have our role ready in the database now we need to map this admin user to the admin rule right so for this we can say user manager dot add to r a sync add to r a sync not roles so here application user which is our application user and then we need to map it to string rle so this role is going to be Ro type. admin. two string and here also we'll say a wait and it Returns the same identity result so we could we could reuse this result result equals this and if this was not succeeded we'll simply throw the same exception here all right so we are good I think let's have uh this exception message tell that it is while creating user or adding user to the role so here we'll say error in create in user and then we can have it like this let's copy this line add it here and here we'll say error in adding user to admin Rule and then these errors and now we are good so we have created our application user and then we have added that we have created our roles and then we have added the user to the role so we are good now all right cool now let's do this the seed service let's register it SE this seed service roll store we are not using Ro store we can remove this R store where is R store it is here it is here all right okay let's save everything and register this seed service to our di container so we'll go to program.cs and here before builder. build we'll say Builder doservices do add transient seed service and we are good and after this we will modify one thing in the default identity setting first is services. ADD identity code it is saying option. signin do requir confirmed account we will make it false we are not using emails right now so what it needs when we are creating any user it will generate a it should generate a unique code verification code then it will be sent to the email and from that email user will click on that link it will come here it will confirm the account it will set it into the database that email is verified and then only that user can login right so I am skipping this thing if you want me to create a dedicated video for this flow for ESP netcore I it does not have to do anything with blazer this is purely asp.net core identity it will be same for Blazer razor Pages MVC and and any other approach okay so if you want me to create a dedicated video do let me know in the comment if I got couple of comment then maybe I'll plan a dedicated video for this but for now I'm simply skipping this thing all right and after that by default it does not add the role identity role related stuff but because we are using role manager because we are using identity role so we will say here add roles and it will be of type identity role like this and it should be before add identity framework store because this order matters because in our previous video when we were working on the Blazing blog application in netblazer SSR at that time I added it here and it was not working so maybe I don't know if this should be before this if this order matters if not if I was missing something so do let me know in the comment if you know about it that this this order matters for this case all right so we have the setup we have the seed service now what we will do this seed service we will run this seed database seed asnc method when our application is running for the first time then only we need to do this there is no point of using it again and again or on demand because this is a kind of a required boot step step for our application so we'll run this at the very beginning so for this what we'll do we will create a method here after app. after everything in the same file here I'll say a sync task and I'll say seed database or we could say initialize a syn or we could say initial setup we could name it whatever we want right now we are just using database so we can just say initialize users maybe or we could say initialize admin user okay and we will get service provider here like this okay now what we'll do we'll say service provider dot h we should create a scope here so here we'll say using word scope equals service provider do create a sync scope or we could just use create scope then we can get our get our seed service seed service equals from this scope we'll say scope. service provider. getet required service and now we have the seed service we can simply run our seed database asnc method we'll say AIT see database ASN and now we are good to use this initial admin users and this we'll do after V app equals to builder. build now we'll say ini initialize admin user and here we'll say app do Services we'll provide this Services here and now we are good okay what is saying local function can be made static yes make static no problem all right now let's do this let's add couple of break points I'm adding it here after that let's go to this method I'll add it here so we'll see if everything is working fine or we have some issue let's try to run it it should create our roles and the admin user let's say finger crossed all right it hit here continue continue and we are here we have our admin user email yes then it is trying to get it from database now we have it null that means we have not added this admin we have application user now if we check it we should have last name is last name is a first name is a oh I messed it up or okay in Settings app set things. Json I have it and okay I'll modify it but for now what we can do we can modify it here only so I'll make it to print all right okay now user store set user email email store set email now this result it should create it is succeeded that means it created this user in the database now we are here we see result was succeeded that means our application user it will have all the values filled up normalized email username password hash everything is here that means our user got created now we'll check for roles it came here it is null because we don't have any rule in the database right now let's see what we got from this enum we have admin it creat this rule fine then we have staff second rule then we have guest the third rule it is also got created then okay we already have all these rules now we will just add this application user with this Rule and this was also succeeded that means we added this Rule now if I continue it it will open just fine now let's do this if if I stop this and run it again okay break point got hit again this is a this will run only when we are starting our application it will not run for the if our application already started and if we are making request to our application then it will not run so we are okay with this see database now this time if we come here we should have this admin user so it will directly return from here because we already CED our database with this user so if you continue we will be here and everything is fine we can move around it will not hit that thing again so everything is fine great so that means we have created our entities we have set up our database we have created our roles and we have created our admin user now we can EAS easily start working on the the admin panel before that login page we can start working on our login page okay great first let's see if we got this thing in database so I'll go to our app settings. Json we have this hotel booking Blazer this database here this is the one right yes let's connect we have tables here so if we see the ASP net rules it should have store table data it has this guas administer these three rules which we added right now if we go to spet user rules it has this user ID and role ID this is our role ID is FC 57 right so if we check FC 57 this is admin rule then if you go to spet users here we should have our admin user which is this one right admin user all these things and this starts from the c23 so if we check here we have this c23 so it got mapped to this so we are good right now let's start working on login page all right so for this first let's work on uh the function ality then we'll work on the UI what I mean is if I run this uh I need to remove that breako we don't need that breako now so remove this breako as well continue and if I go to slash account slash login okay okay because I modified the main uh main layout all right great first thing we'll do we'll remove this third party login provider we don't need this then second thing we will uh maybe remove this recent email confirmation and forgot password these two things we are not going to work on these two functionality inside in this project then we'll move this login user to the center of the screen okay okay let's do this first so we have this Inc components accounts pages login. risor okay so first thing we have this call md4 after that we have this call md6 we will remove this md4 and md6 okay it has MD ofset to call MD upset 2 if I remove this if I remove this we have this call md4 and let's use offset 4 so from starting leave four use four and then after it there will be four so we are good with skipping those and then we will remove foret password and and we'll remove recent email confirmation all right save let's see what we have now we have it here and it did not get moved to the right and these offset classes so we have where is it we added that offset class right call md4 MD offset we don't have that maybe because this is some mismatching of the boot step versions We are using okay we'll use our favorite Flex box so for this what we will do we will go to this container this row on this row we'll say dlex which is display Flex and justify content Center so just move it to the center and let's move this H1 as well to the inside this only insert section we are good save it and let's check it and it is in the center all right maybe we can add some spacing from the top and some what we'll say that uh maybe border Shadle something like this it like this only okay right now let's leave it like this only we'll see if we want to modify this all right so first thing we have this thing now uh pay attention I'm going to click on this login without adding anything so if I press this the page gets reload and then we get this email file field is required password field is required okay so these things should not reload the complete page but because this is a SSR there is no interactivity on this page using maybe IND server web assembly there's no direct interactivity it is a form we are logging in we are clicking on this button complete page gets post to the server and there it checks all these validation and then it Returns the complete page so in blazer with net 8 we have one thing which is called enhanced forms what that does this is a edit edit form on edit form we will add this enhanced parameter so this is same as enhance equals true but for this thing we have this Shand approach that if we say enhance and if this is of type buol it will automatically consider it as uh true so by adding this enhance we are telling Blazer that this form should be enhanced what that mean is you should not post the complete page to the server there should not be full page refresh you should simply use fetch the ax request to submit this form okay now if I added this enhance and now if I open this and now if I click this you see we directly got these errors and the full page reload was not happening right now all right and these messages these are duplicated so let's remove the top ones we are okay with this email field is required and password field is required in here so for this let's check here we have validation summary so we can remove this validation summary save now it will remove those top error uh list now we are good we have email field is required we have password field is required we have this thing we have login okay let's start working on login now if you go we have this login user if you go to this method we are seeing here we have signin manager. password signin ising after that we are simply checking for all these cases and it is logging in now with this password sign in isync method in our particular case there is a problem and the problem is how it works it will use claims it will use cookies with the claims with the logged in users details and by default it uses just ID and the username which is email in this case so it will have only ID and email but that is not all what we want right so we have application user we want user name that means first name last name we need role name and we need image and maybe we need the designation as well to display somewhere so what I mean we need all these information with of course the user ID which will come from Identity user so we need all this additional information this is not going to add by default to the claims using this password signin Asing so we need to change this approach we need to modify this code to make it compatible for our use case Okay so the main point is we need to add additional claims to this uh signing in process so for this what we can do we cannot use password signing ising it does not allow additional claims so the approach we will take we will first check if this user actually exists in the database so that we can use our weight we have our user manager we can check the same thing do we have user manager here we just have signin manager right let's inject user manager so we'll say user manager of application user and it will be user manager so we'll use the same approach we were using in our seed service so on this okay let's stop debugging all right so here on user manager we'll say find by email I syc and this email we have in this input. email email all right now it will give us the currently the user which is associated with this email ID which is of type application user now if the this email does not exist then it will return null simply here we will check if user is null okay so we will set this error message in login attempt okay we are good with this uh message and here then we'll say error invited login attempt and then we'll simply return from it we don't need to do anything further now if the this email exists this username exists that mean this is correct this user exists now we need to check if the password is correct so for this what we can do from signin manager sign in manager we have a method which is check password sign inle it checks password for this user so we have application user then we have string password this password we have is in this input do password and then we have lock out on failure we are not locking out user for invalid attempts so we'll say false now it returns signin result which is I guess password signin result also signin result so we could use this thing here so we'll say word result equals a v and this thing then we'll check if this result was succeeded or no so let's do the opposite we will check if it was not succeeded that means there was some error so let's use the same error message if you want to explicitly tell what is the invalid login attempt you could modify this so here we know that user does not exist here we know that incorrect password now if this was also not the case that means this user does exist in a database and the password is correct now we are good now we can allow user to uh enter in our system we are allowing user to login now this signin manager it has one more method signin manager dot we could say what is that sign in with claims I think so it needs user and then it has is persistent and then additional claims which is an i numerable of claim so this is the additional data which we want user to persist to keep in the identity in claims so that we can use that data to identify the user and its uh other details for example first name last name image rule name and all those things okay so for this we'll create a collection here so I'll say claim claim array I'll say additional claim equals I'm going to create an array here in this array I'll use new claim and we can provide type and value to this okay so this type we are going to use let's say first name or we can simply use one name only we'll just say name or let's say full name and the value will be from this user dot now we have first name and last name right first name and last name we need to use this or we can create uh computed property on this application user label so here what we'll do we'll say public string we'll say full name okay or we could say display name it it's up to you so here I'll say full name and it will be the first name space last name and then we'll apply trim because we have last name as nullable if user did not provide last name then we will have first name space that does not make sense so the stream will simply remove this space so we will always have the actual correct username without any additional uh trailing or uh yeah okay so full name now if I add it directly here it is going to be part of this application user that means this application user is an entity that means it will add this to the database it will try to use this from the database but that is not what we want right in database we just want first name and last name we don't want this full name we want this to our application label only not go to database just use it from here only so for this we need to tell this we need to tell Entity framework that do not consider this full name property as a database property so for that Entity framework EF code provides us not mapped attribute which will say that not ma to this database so if you're creating application user don't use this to create it if you're patching the user don't get it from the database that is what we are seeing now we have this full name now we can directly use it here here we will say user do full name all right we are good now for this name instead of hard coding we could say name of application user dot uh full name or maybe we can create uh some constants we already have this constants folder right let let's go here and let's create a new class here we'll say maybe app constants I'll make a static because this is going to be just for constants inside this I'm going to create a inner class I'll call it for the simple mapping not mapping simple we could say grouping so public static class here I'll say custom claim type okay and here I can say public on string full name full name and then we had role name role name in the application user right what else we had contact number I don't think we are going to display it anywhere so we can skip this designation we might show this so we'll use designation then we have image we can show this image and then email and uh the okay let's use email as well we'll Express this at email ID so it by default uses ID and the default claim types that is that uh name identified claim so we can directly use it from there all right we have custom claim types we can use this now for the key names so here instead of this name and all this we'll say app constant app constants okay let's use this using statement this constants to the imports. Razer so that this will be available for all our components and razor pages okay so I'll add it here underscore imports. raser like this save and now it will be available in all the razor Pages app constants do custom claim types do full name okay now let's add all our claim types which we want so here we'll say I can copy it a couple of times after full name we have role name then we have image then we have email then we have designation all right just this so for R name we can say user. R name for image we can say image but this is notable so we need to have some default Valu so we'll have simple default empty string email email this shouldn't be a label if this isn't aable by any means we can use the same us username all right then comes designation username also anable okay we know this is not going to be aable so we are good user do full name sorry designation designation and for this also we can have empty string now we have additional claims now we can use this so with this sign in with claim sing first we need user which we know we have this user after that we use each persistent so we have this input. remember me field and then this additional claims cool now it returns nothing it is simple sign in so we'll simply say up wait it does not return anything because we know that password and everything is fine we already checked that so it will simply sign in directly without any issue all right after signing in what it was doing earlier it was simply redirecting the user it will doing this thing so we'll do the same thing here we log it user logged in and then redirect manager redirect to return URL whatever return URL we have now we can clean this method of the existing code we are simply removing save everything and now we are good let's try it out let's try I'm running it and we should be able to uh login using the admin credentials okay let's quickly check the admin credentials we have app settings we have AB blazing hotel.com and password is this one okay application is here we'll go to account SL login here in email I'll say AB at blazing hotel.com and password and then I'll simply login and we are good it moved us here and we cannot see anything that's because it successfully logged in but we are not displaying anything anywhere so in order to dis displ let's go to the main tab bar main navigation bar so in layout we have nav menu are we using this no we are not using this on Main layout we have header if you go to header in header we have Hotel AP first let's change it to Blazing hotel and then we have top section where we are displaying email ID and contact number right there only or maybe we have all these navigation menus after all these navigation menu let's add one more navigation menu just for or uh we'll we'll modify it but right now I just want to display the logged in users name maybe so here we could use authorized View inside this we will say authorized if user is authorized then we will display something here let's copy this nav link only so this will be whenever we are inside authorized view it gives us access to context variable which is of type authentication State inside this context we can get user which is of type claims principle and on this user we can get our claims so here we'll say find First and we could say we have to find first value as well right find first value find first value should be find first value okay we have find we'll check this now so on the user. find what is it user doind first we can provide type so the type maybe we can use our app constants dot custom claim types dot full name okay and then from here we can get the value we'll modify this we'll fix this thing we will create some extension methods and all these to simp ify this approach but right now I just want to display that we at least have something all right I'm saving it if this is authorized then only it will display this okay code stop and let's run it again so we'll see if the login was successful and if we are getting these additional claims because this full name comes from the additional claim we added so you see we have this sub happiness which came from the claim so that means login process was successful we have successfully logged in and we are able to add the claims and fetch the claims all right it looks great let's continue then let's see what we can do next all right so let's do this this premium version button let's change it to login or log out if user is not logged in we'll display login if user is logged in we will display log out button here okay so for this what we'll do we'll say same thing authorized view inside this we'll use two things first authorized and then second one not authorized so if user is not authorized let's copy this paste it here and let's call it login and then change the url to account SL login okay now if user is logged in we will display log out button now out is a bit different in Blazer SSR this thing so there is no page or no direct route for log out the way we handle log out that is in our components and identity component endpoint routes so we have log out route here so this is uh minimal API endpoint route basically so here we can directly navigate to this/ logout but because this is a post endpoint we need to make that log out inside a form and we need to post that form it will come here it will sign out and then redirect to the whatever default return URL we have provided okay so for this we can take help from the default nav menu which we got with this Blazer SSR template so here we have that log out form this is the log out form so let's copy it go to our header and paste it inside authorized and in here we will change this button type submit to this anchor tag should we do this or maybe on this button let's add these classes which we have in log out so let's use these classes on this button so button and these classes and then log out and then this icon like this this is completely about this current URL first let's remove that this thing so we'll see current URL is actually the current URL which we got from navigation manager to base relative URI navigation manager. URI okay now we can use this same approach because current URL is going to be different for all on all the pages so the thing is how it is going to work it will have the current URL in this current URL uh variable it will when we tap on log out button it will simply post that form to our that endpoint then it will log out from there and then it will redirect to the same current page that's how it is going to work okay so I think we can copy this all of this thing in here with code so inside code and we need to inject navigation manager and Implement I disposible so we are implementing I disposable injecting navigation manager and then doing the same thing with this current URL and we are good now let's check it so I'm running it now we should see this login and log out button okay it's here we can see the log out button and now we can see login button right now it is login uh this Arrow should we have this Arrow like this only this is right now uh Arrow right what if we make it Arrow left and use this before this login okay for login we will have it left and for log out we'll have it right right now let's have it like this only let's register login and now we can see log out and we can see our name so that means login log out this link is working let's fix the the icon so for login I will use the icon first and then make this icon icon left okay icon left and on the log out let it be like this only so save log out login so on this one Let's uh it has ms3 which is margin start three so on this log out button we will say margin and 3 me3 and it looks nice now right so login and if we log in it should say log out great this is working now login we are saying register as a new user let's work on this page now we want user to register into our system this hotel now there is one point this register this should uh only allow guests to register right so there is no registration page for admin but there is no point of that then for staff admin will be able to create or we could say register staff users staff cannot register themselves and then this register so this will be only for uh guest whoever is looking to the hotel viewing it and trying to book some hotel room so it will be for that only okay all right let's fix the UI first move it to the center remove this third party uh external login providers and add a login button and then add the additional Fields here which we need if you remember we need all those fields which field uh first name last name email contact number all those things right all right so first let's move it to the center so we'll go to our register page in components accounts pages and register okay on this register first thing we'll move H1 inside our column D4 and then on row we'll say d Flex display Flex justify content Center okay and then we'll remove this second call md6 cool so save everything let's see how it looks in Center register create a new account find register now first thing let's add the login button here same as we have on login page right this register as a new user same thing we'll add here so if we check login page login and this one after login div we have this div so after register we can have this it was inside a d that button so let's wrap this inside a div only and then we'll say account account login and here we'll say register as an user we will say already have an account login cool so save everything and let's see it how it looks okay login and now we are login we can go to register let's add some spacing between these so maybe on this P or on this div we can add a class class we'll say mt3 margin top three okay so let's add this on this T we'll say class mt3 and same thing we'll do on login page class mt3 all right save everything now we are good now first thing let me stop the app go to register page and here we have input model which is here but we need to create a different model for our user registration because we want additional thing so it is right now having just email password and confirm password but we need others as well and what are those others first we need first name then we need last name after that email password confirm password we already have then we will have contact number string contact number and then what else if you go to our application user first name last name role we will assign uh from our back end contact number we are getting designation it will be for staff only image we can work on this or maybe we can allow this for staff only or maybe we can allow this for guest also but not from here we will allow this thing from uh manage profile maybe from inside so I think that's all we have for this section so for first name it is required and the max length we need is around 15 after that last name is going to be n label this is not required but we will have a max length of 15 only then comes contact number is this required yes this is required wi let's use these things only the same data annotation which we have on the this thing okay so first name and last name also we can use the same regular expression first name last name I think we are good now let's add these fields the first name last name so we are here P floating mb3 this is H let's do this instead of call md4 let's make it call md6 we will use uh two column layout after validation summary I we don't need validation summary we can remove this P now here we'll say div class row and now we will have div class call sm6 so the half of this call md6 here we will have this form floating for our first name so input do first name first name in do first name auto complete remove this we don't need this area required true is fine placeholder first name all right first name let's copy this call sm6 and here we'll say last name last name name last name last name and placeholder last name after that we have email this is fine after email we will have our contact number then password and confirm password right okay so after email let's have m contact number contact number contact number auto complete remove it and this will be contact number all right then password and confirm password so we are good save and now we should see all these uh new properties and sorry new fields on the UI okay let's run it have it here we'll go to login page register first name last name email contact number password confirm password so we have all these fields here okay maybe we can make these email and contact number and then password and confirm by password also with the same md6 yeah let's do this but we can check validations are happening but still this form is completely posting so because we do not have that enhanced attribute on this edit form so first let's first add the enhance so that it uses enhance forms navigation after that we will wrap all these things into call sm6 so Dave class call sm6 2 3 4 all right email contact number then password and conf confirm password password and confirm password all right save everything and let's six Wier lot let's use call md5 on the top then save it and let's see how it looks now so it's a lot better now and the validations are working all right now let's work on the saving this user part registering part actual register part so for this let's go to our code and let's stop this we'll see what we have on this page and we'll modify it according to our need so so this is register user here what it is doing it is just getting the user create user which is I guess application user and then set user store all this and it is doing that basic stuff that creating the user only without our uh additional fields and rle so that thing we'll do manually here so where we have user the application user now we'll fill out other values the user. first name equals we'll get this from input. first name then last name user last name we'll get input. last name then we'll got email this email is from user identity user so we don't don't need to set this explicitly we'll set contact number input do contact number and what else we added on this page we added these three Fields only right right but we'll set couple of other things so role name it should be Ro type that was Ro type right Ro type dot guest do two string and after this Ro type contact number doign we are not setting and apart from this everything is fine cool so we have set these additional properties after that it is creating the user create setting the email it is creating this user using Create as sync if there was some error it would simply return this if that's not the case it will come here and now we need to map this user to this guest rule so this rule name which we just said this is just for our display purpose this is not actually going to be used directly uh if you say in any logic which we have so for example when we have uh when user logs in then we have this particular couple of claims right right so in those claims that actual role that will be set automatically by this aspnet core identity so we can get that from that rule so we need to set that so we'll follow the same approach we did oh no we can directly say user manager do add to R ising yeah we can do this application user which we have as user and then role this role is going to be we could say user. R name or we can directly say this thing and we can await it okay and we will have this same if statement here let's use this result equals this like this createing identity result identity result all right so we have this now after that this section user ID code call backs email sender all this is happening if we are allowing uh email uh confirmation that thing this code is doing so in our application we are not doing this right now so we can simply skip this section we can remove this for the sake of Simplicity only after that what it was it was doing it was signing in this user and then redirecting this user but what we'll do we will not sign in from here the reason being we have a different uh additional logic to user to sign in we have other things as well so we can remove this from here we'll simply log it and then we'll redirect user to return URL or we can redirect you user to login URL as well if you want so we can say account SL login if you want like this all right I think everything is fine now let's have default values for these the way it was having these pleas all right all right let's try it out run we'll try to register one user gas user let's see how it behaves okay application is running we'll go to register a new user here we'll say guest AB let's say guest at blazing hotel.com contact number some random contact number 1 2 3 4 5 6 1 2 3 4 5 6 and 7 incorrect password so the field must match the regular expression this we need to fix this this regular expression this is fine right if this is not 0 to9 let's fix this but it is all 0 to 9 only okay let's check this but before that we have this uh password thing that is fine let's see what the issue is with contact numbers regular expression oh it should be it should be 0 to 9 and all these right so if we are having it here stop and run it again okay application is here login register and guest user guest one at blazing hotel.com password 1 2 3 4 5 6 1 2 3 4 5 56 register and we still have this must match the regular expression this is the regular expression which it must match this this does not sound good uh online C regular expression regular expression we have this 0 to9 Let's copy it from our code oh that means it should start from here and [Music] then start use 0 to 9 and all these and then end here okay so stop it and run it we modified this regular expression a bit regular expressions are always tricky okay let's try it one more Time guest one at blazing hotel.com 1 2 3 4 5 6 1 2 3 4 5 6 register and yes this works but now we have password must have at least one non alpha numeric character and all these things so let's comply this so we'll say at the rate guest 1 123 at theate gas1 123 with g capital now it move to the login page that means the registration part was fine and if we try to login it we should see guest that means we can see this user so this thing work everything is working fine we can log in using a guest account and we can log in using the main uh what we say admin account all right okay now let's do this what we'll do we'll add one link here which will be uh logged in user specific links so for admin user we will display uh manage staff manage rooms manage booking all those and if the logged in user is guessed we will display maybe my bookings and if it is stuff we can display manage bookings not manage stuff right so let's do this only we'll open login registration is working we are happy with this now what we'll do we'll go to our header in header we will simply copy the there are some drop down right this is Hotel AP first let's change this to Blazing hotel and then blazing Hotel this is the main homepage after that we have Toggler then we have this thing item drop down this this section Pages section we'll simply copy this Pages section and maybe after contact we will add this section okay inside this instead of pages we are going to display okay this should be in authorized view only so let's cut this from here and it should be in authorized View authorized view in authorized section so I'll add it here it is saying Pages it should display user name so we'll use this section in here so now it is displaying username after that we are going to display all our links so first thing we should have uh my my profile let's use let's say my profile so this will be common for all regardless of the authorized uh user but now we have one situation on this context dot what all we have we have user dot identity add identity claims clone find first is in Ru okay we can use is in rule but I wanted to display this outside of this but looks like we are in here can we use authorized view inside authorized view uh I don't know what I wanted to have on this authorized authorized we can set roles R rules something like this let's check Blazer authorization maybe like this if we go here ASP net code 8 okay roll ru R claim mpal data that is fine this is fine route view authorization authorize view rule based on authorized view we can have roles okay we can next authorized view authorized view great all right you have the admin Ro claim you have the both admin and super user Ro claims great let's do this rules context then this is inner context we can Define if you want to access something all right let's try to use this so this is authorized view we are in authorized oh in authorized view okay we can set the rules on authorized View okay for this authorized view we don't need any role in here because we are good because this section we want to display for all authorized users regardless of their role then after my profile I will have one more authorized View and here I'll say rules equals let's say guest this is can be assign Dynamic Ru type dot guest do two string like this cool we have this so for this we'll say my bookings now we'll add one more authorized view with rules uh typ at theate Ro type dot T do two string so so whatever staff can see uh admin can also see that thing right so inside this rules we need to provide multiple values I don't know how to provide those comma separated like this but we'll do this staff comma admin okay so we'll make a copy of this we'll say uh manage bookings and then we'll copy this one more time for admin only where we'll say manage staff manage bookings we already see my bookings so let's move it before this staff and admin so now it will see now now let's see what we have here so guest it would see my profile and my bookings then comes staff staff will see my profile and manage bookings after that comes admin admin will see my profile manage stuff and manage bookings okay we'll add other menu items as we approach there there then we'll see right now let's see if these roles and all these things are working as expected all right let's run it and let's see if this thing is working we have some error what is the error content element authorized of component authorized view specif the parameter name like child content authorized authorized authorized authorized [Music] what is it here it was saying if we come here but this authorized view can be for both authorized and not authorized authorized view authorized View let's see what it is saying it is saying child content element child content of component authorized view uses the same parameter context okay okay okay okay okay context whenever we have authorized view we need to change the the context name so that it can know that which context you are using so context we will say let's say guest context then on this admin we'll say admin context then this section here we'll say staff admin context like this save it and let's try to run it and it ran we don't have anything here let's log in we are loging using guest to guest of my profile and my bookings this is fine let's log out login and this time log in using the admin role so Prince here we can see my profile manage stuff and manage bookings that means the role is working right and these menu items are Dynamic on the basis of currently logged in users role cool now we can start working on this all right so we first need manage rooms and manage amenities these two things we need first because these two are going to be the main building block of our hotel booking application right because that is what guest is going to come and see all right let's do this so first let's add those items so manage amenities and manage uh rooms so I think both of these options can be accessed from both staff and admin so let's copy these things here we'll say manage rooms and manage amenities manage amenities save and we are good now let's remove this section all right now what is this Conta this authorized view we have that contact naving this is empty let's remove it I don't know why it is there okay now we will work on these sections so first we need to create the pages for these okay or before Pages let's create services so we'll start from let's say am service so surveys then we'll be having one let's say room service then we are going to have one oh we need to have room type as well right or maybe we can have the this room type related stuff in room service only break these Services as admin Services when I say admin that means admin and staff and then we could have public facing services or we can use the same service for both of these uh should we use same let's create separate so amenity service or we can have save only okay so what we'll do amenity service room service we will have room types inside this only and then what else we need need what else right now we don't need anything else okay so we'll start working on here first we need to inject our idv contact Factory of type our application DB context okay it will be context Factory like this and now we can access this Contex Factory so first we'll start working on listing the amenities so public async task Amun let's check what all we have ID name icon that's all so we don't need to create separate dto for this so array of amenities and we'll say get amen is a sync and here we need to get context DB context from this context Factory dot create DB context or create D context thinkc we can use either one so and then we could say return context dot uh amenities dot to array to array a sync and we'll use a we all right so this section this creating and now then we need to dispose this we need to dispose this context context dot dispose or dispose processing okay instead of doing this we could say we can add using here only like this now it will be disposed but this context and this section this is going to be repeated for all the methods so we could use like this only or we can create uh separate method which will work as a we could say some template pattern so it will provide this context we will query that context and after that it will simply dispose it either approach is fine let's go with this approach all right so I think we are good we are listing down all the amenities then we'll have one end point public as sync task Amity Amity I hope the spelling is correct we'll say save amenity a sync and we'll get the amenity object here okay first thing we'll create the context after that we will check if the Amity object we got if this has is uh ID equals equals z that means we are creating a new Amity if that's not the case we are updating an existing amenity so update update existing amenity all right so if we are creating a new one we don't need to do anything we just need to add that Amity to this context so a context do amenities dot add as sync amenity and on this amenities we could say when we're getting we could say as node tracking you could use this as no tracking uh you can Define this on the uh DB context label itself if you want how that can be done we can come here in the application DB context we can override a method that is on configuring and after calling this base Doon configuring this we are calling this so that we have this uh base identity DV context so if there is any identity related setup in this identity DV context so that that can also execute if you are creating your DB context as a subass of DB context only then you can skip this there's nothing in this in DB context all right so here what you could do on this option Builder you will have used query tracking Behavior track all which is default no tracking you could use this so now as no tracking will be applied with all automatically we can skip this and whenever we need tracking on the query basis we would allow that using as tracking like this so whenever we need tracking then we'll use as tracking and if we are not using that then we are good because it will have automatically that as no tracking all right so context. amenities. add sync now if we came here for updating an existing Amun for this what we'll do we'll first get the Amity from database so we'll say DB amenity equals await context. ameni dot find a sync Amity do ID okay now we have DB Amity and in this DB Amity what we'll do DB Amity dot name equals Amity do name and DB Amity dot uh icon equals icon because these are the two things we are allowing uh user to modify now it could be aable if we are trying to modify and Amity which does not exist in our database so we can check it here if DB Amity is null we'll simply throw from here throw new maybe invalid operation exception we could say Amity does not exist like this and if that's not the case we are simply setting this now what we can do on this amenties we would say as tracking and then instead of find async we could say dot first or default async a. ID equals equals Amity do ID like this all right so we are tracking this and uh this Amun that means whatever modification we are doing on this TV Amun it will be uh tracked automatically we don't need to call update method if we are not doing this if we are removing this as tracking then what we need to do we will need to do context do amenities do update and then this DV we need to do this explicitly right that's how EF core change tracking work so we can remove this because we are tracking this change here now after this we will simply say a wait text do save changes async and it is going to modify this amenity if this is the uh it will going to create this amenity and if we are in edit mode updating mode then it will simply update this what it is saying fix formatting okay use calls operation okay this is also fine we are good with this all right it will save it after saving we will simply return the same amenity object so we saved it we got the list and I think on Amity we just need these two operations only yeah so our Amity service is good let's do the this on The Amity service we will uh extract out an interface so extract interface add to the current file only we need both the methods we'll say okay and now we'll simply register this Amity service we'll go to our program.cs we have our seed Service registration after this we'll say add transient and I Amity service and Amity service now we can directly inject this I Amity service in any of our page where wherever we need it we can inject this all right let's go to components and here we have pages and inside Pages we can maybe create a new folder and we'll call it let's say staff admin something like this so that just a physical grouping so here what I'll do I'll say uh create a new razor component and I'll call it manage uh amenities amenities and I'll apply at theate page here then here I'll say staff hyph admin slash manage hyph [Music] amenties like this cool now we want this page to be accessible by staff and admin only no one else so what we'll do we'll add an attribute here that will be authorized attribute and on this authorized attribute we are going to Define roles and these roles are going to be staff and admin these two roles can access this page no one else can access this page all right okay so on this page let's inject our [Music] I uh munity service let's in let's add this at theate using both of these usings let's add these two underscore inputs so that these can be accessible from all the razor components Imports we added these save everything and it should pick up from there why is it not let's close this and open it again all right we have this Amun service so we'll say Amun Serv cool now here we can H have a list or let's say table of amenities so here I'm going to create one state variable here so private Amity Amin array and I'll say aminities with default array blank empty array and then I'll say override on initialized async and here I'll say underscore amenities equals a weight aminities service dot get aminities assing like this now we have our amenities here we can display this but right now we do not have any Amity so so it will not display anything we should have some one page which will have the form to create or modify this Amity now what we can do first let's have one H1 where we'll say manage ameni is okay now if we create a separate page for this a dedicated page H that page it will have just two uh Fields name and icon right nothing else now now for these two things if we create a new page that is fine if you want to do this and then we have another approach we can make this page interactive and we can have that form on this page only so we can have it interactive server or interactive web assembly or interactive Auto and then we can have uh the form here if we tap on create uh this uh create amenity or edit amenity then it will simply open up that form here only on this page and then we can modify that but it will need that interactivity but let's try another approach what we'll do here we will not do both of these things we will not create a separate page and we will not create uh we will not make this component as a interactive component let let's do this here first thing uh let's have a table we could use Quick grid as well if we want but first let's we will use Quick grid but let's first have the data displayed in table format I'm having it here like table class class table and then inside this I'm going to have t head TR and in here I'm going to Define our th so first we'll have ID then we'll have name and then we'll have icon and then we'll have have addit blink all right then we'll have our T body and in t body we will use our 4 each Loop and here we'll say a in underscore amenities and here we'll use our tier with first TD at ID so at theate a. ID then second one would be name and third one would be icon this is fine so right now we are not going to see anything now we need to have one form let's do this I'm going to create a form here we can use edit form addit form and for this we need to have one model here H so I'll say private amenity and let's call it model get set with the default value get set what is doing oh because of this okay on edit form we can Define our model which will be the model only model property and then we could have it as enhanced form and because we are using this in a statically uh rendered page so we need to provide form name as well so here we'll say form name hity this is fine and here we can have first we'll have our data anotation validator after this I'll have Dave class mb3 margin bottom 3 then I'll simply have one label with class form label here I'll say name then I'll have one in put text with the bind value as model. name then classes let's say form control form control and placeholder placeholder we'll say m& name like this and then we'll have validation message for model. name with class bootst step class text danger to show it as red color okay now we can copy this mb3 name and icon [Music] icon icon icon and then third one we will have simple button submit button so here I'll say button button type submit and then I add a couple of classes BTN btns BTN let's say success and here we'll say save and I think we good right now if you open this page manage amenities from staff admin let's copy this thing go to our header page and there we had that manage am is let's add that link here save everything and let's try to run it right now that page is static uh SSR page that does not have any interactivity so we'll be having that problem that that uh edit form that will be displayed on the page from the beginning only but we do not want that so we'll fix that uh if I okay this thing oh this problem was in that also let's see what we can do manage amenities and we are here on manage amenities first we have this form right after that we have this table so we do not want this form always to be here first first let's move it to the center what I mean is I'll have all this data the complete section everything on this page inside a sorry container da class container okay and then this edit form after manage amenities let's add one HR and then for this addit form let's do this let's move it so I'll have a div class row with display flex and justify content and align self just that property was I never used it it's a good time to use it so I'll say div class justify self we don't have that justify justify or just align self align self okay we'll see so right now I'm adding justify justify content okay let's do justy content and right H in here I'll add this thing but inside this addit form let's have it as Dave class call SM see have it in here well let's see how it looks it is here the list is here now manage amenities we have okay we can yeah we can have it like this have this form on the left and have this thing and yes is we can have this form always here right and then we can have this table on the right side yeah because this Pages were not part of the template which we are using in this and I have not planned this video already so we you you'll be seeing this a lot that I'll start something then I'll not maybe I'll do something else and we'll be some somewhere else so let's do this only so this is fine let's move this table to the right section so let's REM moove this thing let's have div class row we don't need the display Flex now so first we'll have call smm3 like this and then we'll have call sm9 div class call sm9 and we'll move our table to to this section all right okay now inside this T body let's do this if our amenities dot length if it's equals equals zero that means we do not have any Amity so we'll simply have one TR and we'll have one TD with call span three because we have three four columns so call span four and then we'll display one let's say H4 with class text danger and we'll say no amenties yet create one from the left form something like this and if that's not the case it will simply render out this section so H we are good I guess let's see it how it looks no em yet create one from the left form we have this form here if we save it it was not full page refresh right because we are using okay now we have one problem you see I'm writing something I'm typing something and when I hit this save button it still says name field is required but we have provided the name field then what is the issue the issue is whenever we click on it the it gets post to the server to the same page it comes here and and it gets reset to this we need to tell it that you need to get the value for this from form so Supply parameter from form so when it comes for the first time it will use the default new and when we are posting it when we are clicking on this button then it will come here and it will fill these values from the form but form means whatever input text or whatever input fields we are having in the form all right so let let's save this and let's see if it picks up these changes right now we have this thing and if I do this we still have this let's try to run this if it's working Supply parameter from form this is fine and edit form form model model enhance form name Amun yeah everything is fine let's see we are here manage amenities and I'm adding something and yes icon field is required name we provided so it is not giving that thing now if we do this yes so this thing is working all right now we need to work on saving the amenity okay so whenever we are calling clicking on the save button it should save the amenity let's do this so here we'll go here on this addit form we'll say on valid submit we'll say handle or we can say save Amin I thinkc like this and let it generate this method for us it is not generating so let's go here and let's create this so private isync task save amenity isync like this now we have this model here we can use this model to save it now how can we save it we will say uh hm first we will check if we have no let's do this AIT amenity service do save amenity I think right and here we can pass our model and it will get saved amenity in here right it gets The Amity right now if we do this we do not have any uh visual indication that something is happening what I mean is let's let's do this let I am refreshing this if we provide those values and if we hit save it should create a new Amity for us it's here oh I'm sorry login manage amenities and let's say WiFi and what is the icon for Wi-Fi it was this one icon for Wi-Fi is f a f a WiFi let's do this and if I hit save it got saved how would we know that something happened we should have some visual indication and when it got saved at least we should see this here right now if I refresh this I can see this that means the saving was done but we could not see anything here so let's do this thing and for this icon we can display this icon here right so what we can do after displaying this icons name we can say this uh let's do this let's have a span with this and an i class at theate a do icon like this so save it and we should see this icon here let's use the same class they are using on this they are using text primary right so let's see and we can see this icon here right fa F WiFi and this is the icon now let's first fix uh displaying that new updated value here so how we can do this we have two approaches first one is we know we have added this so we can prepend this new value to the amenties second one is we can simply tell this to refresh its state when I say refh ref fresh it State how we can do this we can simply inject uh navigation manager navigation manager then we can call one method from this navigation manager which will be navigation manager dot refresh okay let's try it out I'm going to first stop it and run it okay it came let's check some other imunity as well so we have this bad and the icon is going to be F fa bad okay we are logged in manage Amity we are on manage amenities page now it came here after this what we'll do let's create second one say bed f a f a b e d bed I fund right and now if I save it did something happen I refresh it yeah something happened but it did not refresh this thing and why so okay that mean navigation manager is not working in this case and if we add that se that thing to this one that is also not going to work I don't know let's try it out if we add this newly saved Amun to underscore amenities amenities dot uh can we prepend yes we can save amenity if we do this it is not going to refresh or will it let me stop it and run it again okay let's check the next one which is this bad or maybe let's have some dummy incorrect value only we'll delete those so I'm saying ABCD AB CD and if I save it it we do not have anything but if we refresh it we will have that ABCD here next thing let's try this let's try to use this navigation manager. refresh so navigation manager refresh it refreshes the current if we are on some interactive component and if we use navigation ref refesh then it refreshes all the static component that's how it works but let's see this if it works if it does not work then we'll need to uh then we will see what else we can do right now I don't have anything in my mind let's see what works for us all right manage amenities XYZ x y z save it and and it also didn't work all right okay so that means that means let me think what we can do when we force it to refresh it should have that value in here or is it because let's try this let's try to add a break point and we'll see what we are getting here let's run it manage is on initialized sync we have four amities continue all right let's add one pqr pqr save it and it again came to on initialized I think we have four amenities now came here we have breakpoint right save Amity the S saved Amity we will get PQ are amities do prepend and we have only four Amun still four it should have been five prepend is not working preand is not working when we say prepend oh it returns it returns a new sequence that begins with the elment it does not modify the existing collection okay okay so we can do this and if we are doing this we have another approach so let's do this instead of calling link Q's upend method we will say saved Amity as the first Saved Amity as the first element and then we'll use this notation it will copy all other items in here now let's save it and let's remove this breakpoints and let's run it maybe it will work we were using the wrong method that was the problem maybe let's see okay it came manage Amun is qwe qwe save and it worked it worked great cool let's check one more thing do we need navigation manager. refresh here let's check this manage amities ASDF ASDF save and we don't need that refresh right so we can have this data now all right now we need to fix two three things first this is coming in this order we should have it in ascending or descending we should follow single uh uper Ro and then let's move these icons to a separate column so if we are using the default uh ordering we can move this saved Amity to the very end so what it will do it will simply have these amenities and then we'll have Sav dity like this and inside this after icon we can say icon class icon CSS class and then icon maybe I'll move I moved it to the first after ID the second one so on this we can have call span five and in here we can after ID we can have this thing here which will display the icon and then after name and then the last one will display the class name we are using for this Save It We Fix the ordering and we fixed the UI a bit save and I want to show you one more thing before that let's first run it and let's see if functionality is working then we'll uh we'll fix one thing we'll make better ux if I go to manage amenities we can see these things let's add some giberish save and we can see this it came to the very end so we are good with this now let's what if it took time so here I would say a wait task. delay and let's say it was taking 2 seconds of time save now if I create something I'll save it and nothing is happening and then it came right so this time we should have some visual indication that something is happening right so when we say something is happening and this page is statically server side render so we do not have any interactivity on this page so for statically server side render page we have one thing which is streaming rendering so we could add one attribute where we'll say stream rendering now what it will do it can push multiple upd dates to the client from the server okay now what we'll do here we will simply say uh we'll have one private variable here private bull will say underscore is saving okay so when we'll go to save amenity async we'll say save is saving to true and after everything we'll say it saving to false now if this it saving was true we will make this button disabled so here the save button we'll say disable equals not oh no we'll say underscore it's saving so if this is savings true disabled should be true that means this button should be dis disabled now inside this we could have some uh visual that loader icon also so let's get that from bootstrap so get bootstrap [Music] bootstrap Doc and from here we'll go to docs and let's search SE for Spinners spiners Spinners search for spinner Spinners and we can use any of these so inside button we can use like this spinner border spinner then we have this button disabled this is the spinner and this is the state loading okay let's copy this we'll add this inside button so in here what we'll do we'll say if it saving is true inside this button you should display this if it saving is false just display the save text okay now let's try it out let's make this uh delay to 3 seconds now so I'll save everything and stop and run this now we should see this loading indicator on that button and that button should get disabled all right manage amenities and let's use him jklm and anything and save you see loading and this is disabled right now and after that we got it and it will be getting saved again okay we should add this validation as well the same name should not appear more than once and but this thing is working and after saving these value should get cleared from this right so that means loading is working let's use some other thing anything save you see this thing is working so now we have streaming rendering enabled so this is working it is a good ux all let's fix these small things first after saving we should reset our model model equals new we are resetting it then second thing we'll go to our service and in service we could come here when we are creating our updating amenity we will simply check if that name already exists then what we'll do we can through exception or we can let's through exception then we'll uh handle that exception on the UI or we have another approach we can have the response or result class which we can use here so let's let's follow the second approach I usually follow that approach models in our oh I don't have any models folder let's create a models folder models and here I'll add one class which I'll say let's say method result let's make it a record of type T data okay it will have bu it success and T data data and we can have string error as well if there is any error error message something like this now we can add couple of helper Factory methods inside this so we'll say public static and Method result of T data we'll say success and and we can expect T data data to this and from here we could return the same object with is Success true error message null and data is data like this then we could have one failure method here in that case we are not going to have any data we will just have error message error message message okay here we'll say false and error message will be this error message and instead of data we'll say default whatever it is cool so let's add this name space to our uh components andore imports. Razer file at theate using this so that we can use this type on all our components and then we can use this method result in our services well Amity service from this save Amity asnc it would return method result of type Amity like this okay let's change this inside the interface as well all right now we can return from here now we need to modify this final return statement so for this we have to approach either we can have it like this only or we can simply simplify it we can create an implicit operator here here we'll say public static implicit operator the return type would be this method result of T data and and the input type is going to be data here it will simply return or we could say it will simply call success of data using this what we did we can directly return data if the return type is this what I mean is you see now that error is gone we are directly return returning this Amity from here but the return type is Method result of Amity so it will automatically consider it at saved uh success case it will assign this data to data and then it's success to True automatically all right and okay so first thing now we will check if that name exists already okay so here we'll say if a wait context context Dot do amenities do any a sync a do name equals equals amenity do name if this name already exists okay so from here we will return error message we could say return method result of amenity Amity dot failure and then here we would say Amity exists already or something like this all right we're still typing so much right we can use the same implicit operator for this as well although this is for especially for error case this does not make sense but we can use this if we want it will be uh confusing it will not the internet is not going to be clear if someone is looking at your code this is not a good practice but still for making our lives easier I'm doing this so failure I'm going to use this error message error message error message like this and now I can directly instead of returning this long string I can directly return error message so here I'll say Amity already exists something like this and it will be a valid return case all right it is working fine great if that's not the case we'll create it and same condition similar condition not same condition we'll use in this update existing case here what we will check we will check if this Amity exists with this name but that should not be this this current Amun so a. ID is not equals to Amity do ID that means this name exist with some other amenity right semity with the same name yeah this makes more sense Amity with the same name already this cool so we are returning this and if everything was fine we are returning this Amity now we can use this in our component we can go to our manage amenities component now it will be freaking out but we are good with this so here we could say this is going to be result and then we'll check if result dot is success then do all of this which we are doing we are resetting model we were add modifying the Amin and here we will say result dot data result dot data all right if that's not the case we will have some error let's display that error message so for that we will have one more variable here here we'll say error message or let's say error only so we'll set this error inside this so after if we will say else if it success is false we will set underscore error to result result. error message or if this is null we'll say error in Saving Amity like this let's display this underscore error in this form we'll have Dave class mb3 and then we'll simply display this error but we display this section only if that error exist so here we'll say if not the string dot is null or whes space uh underscore error then only do this display this at the rate error okay now I think we are good let's try it out saving it should clear we should see still see the same thing but it should get cleared and after said let's introduce okay we can use the same name and we need to do one more thing let me stop this Quest whenever it came comes to this method first thing we'll reset the error we'll say error equals null now run it so that it clears the previous error we'll come here I'm running it let's see what we have all right we have this manage amenities fields are required ABCD ABCD if I save it loading we need to change this loading text and we see Amity with the same name already exist and it did not create that let's change this to red color and then change that loading to saving so this button loading let's call it saving and this thing this error let's do this text danger so that it uh gets displayed in red color and let's wrap it inside this small uh tag so that it uh looks a bit smaller all all right okay let's see saving ABCD ABCD save saving and amenity with the same name already exist right now if we create some new amenity new Amity and if I save it saving and then it will save it at the very bottom right we are not seeing that icon because that does not exist let's use some icon we saw that icon right what was that icon this first one second one bathroom so it was F fa bath let's call it will say bath room and it will be f a f a b save it is saving and we can see this you see that means everything is working fine here this logic saving populating this thing is working all right next thing is we will uh let's add those action buttons addit and delete the Tings now if we are saying delete uh that should not happen right because we this will be mapped to the room types so if we'll remove move it here from here it will be H so what we should have we should have is active field in this or let's say each deleted field inside this so we are allowing soft delete only not hard delete okay so let's do this first let me okay we we'll do this later first let's work on added functionality then we'll work on this delete functionality okay because deleting requires additional property to be added additional column to be added running the migration all those stuff so hold on on that we will first work on addit functionality here I'm saying I'm adding one more TD and inside this TD I'll say except button type button class BTN BTN SM BTN primary and here I'll say edit now the problem is this section this page is SSR that means if we click on this nothing is going to happen because there is no interactivity in SSR right we need to somehow figure out that we are trying to add it and when we say this we have trying to add it then we have uh two approaches I think so first approach would be uh we can wrap this edit inside uh H we can wrap this edit inside a form let's try it out I have two approaches in my mind let's see which which one works so I'm going to have a form here okay and in this form method will be post we don't need any class we will make use enhance form so data enhance then we will use form name so this form name this should be unique for this form on only so for this we can make it Dynamic we'll say we'll say addit underscore or hyphen the name is up to you what you can name it whatever you want and here we can say a do ID okay and inside this I will have that button and I'll change this button to submit button submit like this all right now what should happen when this form gets submitted so here we'll say on submit we will call a method we will say addit uh let's add that here we'll say private void added Amity and we will get in ID and from here what we'll do oh not ID we should pass the complete Amity object so we'll get Amity Amity and we'll set it to model model equals m because we are now going to edit this okay so let's call this method from here so we'll say added amenity with this a which is the current Amity all right let's see if it works if it works we are good if it does not work then we'll use different approach save everything let's run it where is it okay it's coming log out login login and manage amenities we have added let's try this ABCD it should come here and we have a valid anti Forin token was not provided all right so when we use this anti forg token this is by default enabled uh let me Zoom it for you this is the error so whenever we use form for edit form entry fory support is in build there but for these forms these HTML forms we need to provide explicitly so here we could say anti forgery token and when we add this let's try it first we need uh antiforgery require antiforgery attribute as well let's see if we need that or it works without that for edit form we had that edit form right this edit form for this that is inbuilt there okay it came manage amities and if I add it yes invalid operation edit form requires either a model parameter or an edit context edit form we are not using that edit form right that edit edit form is different form name amenity and for this form Name Is this different form name for name [Music] this let's see if adding that attribute helps so there are a lot of things which I am trying for the first time with this uh blazered for this SSR so we'll be learning a lot together we'll be doing and learning together okay so here we could use requir anti fory anti forer token right this is the correct name yes this everything is fine private void edit Amun and all these have a different form names let's run it and let's see what we have data enhance is this correct okay manage amities first let's see if that form name is getting applied to this on this form name underscore Handler value added one that means that is getting applied H this is how it has the form name all right after that what I'll do let's go to console and network preserve log so that we can see what is happening and let's addit this and we have this let's see what request it made it made this request which was was it was fetch request okay that is fine payload was Handler added three and request verification token okay and then we had this data but it saying edit form requires either model or this on parameter set I don't know what why this error is coming because we have multiple forms but that should work okay okay if it is not working then we'll go to the second approach which I have in my mind I'm going to use anchor Tex here I'll use a HF and this will be this same page this current page with an additional value with let's say ID or we could name it whatever we want it's up to us here we'll say a do ID okay and I'm going to add the same classes so that it uh looks same as button text will be same edit and let's remove this form and let's remove this require an4 to as well okay and in here we have this ID so we need to access this ID somehow so that somehow is going to be I'm going to create a property here private on this Amity this integer or short this is in I should have created a short no integer is fine there could be I don't know let's have private in ID or we could say MN ID get set okay and here we will say Supply this value from query because we are adding this ID in query string now the names are different this is Amity ID and this is ID so we will tell this Supply parameter from query that name in the queries string that is ID so you need to get that ID and map that ID to Amity ID like this okay all right so when it will come here what we will do we will check here if this Amity ID Amin ID is greater than zero that means we got some value from there if that's the case we will say we will Define this model we will say model equals we will get that ID from this amenities dot uh we could say first or default a do ID equals equals amenity ID now invalid amenity ID so we should not directly assign it we should check it word amenity amenity equals this then we'll check if amenity is not null is not null then set model equals this Amity okay we are doing this we'll set we will set this and then it will have this Amity and it will modify this we can make the changes let's see it we don't need this now let's see if this works ideally it should work if you're not uh maybe there is some I don't know but let's hope for the best it should work I'm running it okay we have it here manage amenities we have and all these have these links so I'm going to open this XYZ and we can see the values here all right pqr and everything is working F all right so we are seeing it and if we add some invalid ID then it will simply display blank Valu because that does not exist so we are good right cool now there is one problem if I am in edit mode okay if I in edit mode here what it would do it will if I'll save it it will say this already exists no it saved it what qwe 6 okay it is going to update it okay okay okay all right but no not update it sorry six and six it added it here but it actually updated it so this UI is not correct at as per our implementation now what have what just happened we used this we edited this it saved it or we could say updated it then we have added this here because our code says after saving it save aming after saving it whatever result we got we are simply appending that to this amenties list but for edit case that's not the case this was applicable only for add a new amenity case right in that case we were modifying it if that's not the case we should not modify it like this what we should do first we'll check if uh before this thing let's move it below here we'll say if model do ID is greater than zero or we could say model. ID is equals equals z that means we are creating a new ability then only we modify We'll add that Amun to this amities collection stop and run where is it okay it came manage amenities and if I go to let's say XYZ and if I save it saving save we have this XYZ here and we have nothing here so that means this is fine let's create a new one new one new one save now it should be added to the bottom it did not get added why oh because we had that ID equals to 4 so it thought that the ID will be this so we have some unexpected Behavior now okay let's see how to fix this what we'll do let's add a breako here first I want to see what is happening right now and I'm just remove removing this task. delay so that I can check it quickly I'm going to run it I'm going to add break point in on initializer sync as well all right manage amenities on initialized the sync [Music] continue now let's open this XYZ only it came here it came here it got Amity it set the model we have id4 xyg XY continue and now if I save it let's say I'm modifying XYZ icon to 1 save it it again came to un initializes Sy and it got that four and it modified the model that should not happen right that should not happen we need to somehow check if we are coming here for the first time or if we are using the uh if we have clicked on some submit button then we came here right we need to check in this so for that what we can do if it is greater than zero then first thing we will check we need to have access to http context we need to check if this is a get request that means we clicked on edit link or this is a post request that means we have modified the items and we clicked on save button for this what we'll do here we'll add one property here of type HTTP context http context and it will be provided as a cascading parameter HTTP context okay and then we will check here if HTTP context dot we should have [Music] some B on log in HTTP context as casting parameter and HTTP method. is get we can check like this right so here we could say HTTP methods meod dot is get then we can say HTTP context request. method I already copied everything okay so if this is get then only do this that means then only modify this models else models value will be provided from the form when we will be adding it now we have one missing piece I think that is for this model the ID in our form when we are saying Supply parameters from form it will supply all the parameters which exists in this form then this addit form so we have name we have icon but we do not have ID we need to have ID as well so we can have that ID as a uh hidden field we are not going to display this we will just have it to track if this is in edit mode input text and we can add type as hidden like this and we'll say bind value equals model do ID like this what is Theo in to string input text we could say input number save and we are good all right let's try it out if it's if it works the way we are expecting it to work uh there is one thing which we should do H if this is the case we are here and after after modifying it when we modified it we should modify that value in the collection itself okay let's first check if we are able to save it and then we'll uh modify it in the table so I am here I'll go to manage amenities ID this is here we it should not be here okay we can fix this but let's see if we get we can get the actual value that is fine so I used XYZ xyz1 save it and xyz1 this does not get upd updated if I refresh this then I'm going to have this updated value okay so let's first fix this thing and then we'll fix this thing both of these things let's fix both of these so instead of this input number number let's use the html's input element so input type hidden this is not going to be changed on run time so we are good input type hidden and the value is going to be model. ID let's remove this now it will not be displayed after that in edit case save Amun missing when we are here if the model. ID was Zero then append this if that's not the case then we need to fetch that Amity from this list so we can do this thing what we have but right now we can directly use first because we know for sure that this is going to be in this list okay instead of amenity ID we'll say model. ID now this Amity we need to modify this Amity so we'll say Amity do name equals response uh response sorry not response result do data dot name and after name we will have icon result. data icon like this save everything and let's try it out top and run with this I think everything should be done with this page uh the delete functionality we'll work on it later manage amenities we are good let's create new I'm saying fif 15th aminities so f a f a ABC I'm saving it saving what happened is there some error yes there is some error network error Blazer web if you go to network all patch refresh 15th 16th fa F BC save we have some error but it works fine the response is here response is not completed but why so you here model. ID equals z then do this if it's not zero then do this it's saving false we are setting it's saving to false uh what happened let's add a break point and let's see what is happening refresh we'll say 17th S V here this is not working this amities collection this does not have all the data but that shouldn't be the case should always have the data okay let's try it one more time all right we have 17th now we'll have 18th F f8 save we have break point if we check amenities we have 17 items oh okay I come here model. ID it's not zero because for model we have 18th the reason is we have already saved the this model so it actually modified this value because the way Entity framework updates the creates the values it it's it mutates that object this is of reference type so it is mutating this and that's what is happening here so what we should do we should make a close of this so we will say clone equals we can say uh model dot we have two approaches let's follow this approach we can simply expose a method here so I'll say public Amity clone and here I'll say member wise clone has Amity and what is the issue here possible null reference we know this is not null so let's like this all right so now we can use this clone so here we'll say model do clone or instead of creating this directly I'll say this model do clone now it is a different object now it's a different object which is going to be mutated that is a clone of this model this model will be intact so we are good we are not mutating this model all right let's try it out it should work now let's run okay I hope you are learning a lot of things please do let me know in the comment if you are still following and please like this video and share it with your friends and don't forget to subscribe my channel I'll be posting other complete full stack apps as well using Blazer using Blazer hybrid Maui all right 18 now let's say 19th fa a19 the save it came here yes continue and it got saved and we can see the 19th here now let's try to modif mod ifies anyone let's say 15th we'll modify 15th 15th I'll say updated and now if I save it it will come here and if I check the model I should have oh ID I have zero this is not good this is not good this is not good and why this is not good because we used input type it and we directly use value we did not bind this value when we say bind so uh the way it works it all these input text and all these for forms when we post form this needs the name HTML attribute so it get handled by input text by default but we are using this input type it is not being handled here what we can do we can try bind values working if it does not work then we'll need to figure out something else okay there is some case log out it has the information but it is not able to figure out the name I log out and log in then it figures out there is some case we need to check that and it I okay it was in previous project as well I missed that okay maybe will fix this if I remember this till the end of this course all right so let's check if name is getting set through this so you see on this input type hden value zero no it is not going to work you see this name uncore request verification on this we have name uh model do name then for these also we are going to have model do icon so let's do this manually so on this input we'll say value equals to this and we'll explicitly set name equals model dot ID it should work now value zero now we need to refresh name input type header name value okay let's refresh this should be string model. ID this text not the actual value so I'm I have not added at the rate to this all right or you could have used name of model. ID no that that should have added name okay we need to have this only manage amenities and now if we check we have Name model. ID model. name so it should work now let's modify this ABCD I'll say ABCD updated I have just modified the name I'll save it it should come here now if you check model it should have three ABCD ABCD updated I'll go here everything was fine updated values continue it got cleared and ABCD updated that means this functionality is working learn this ABCD let's try to or maybe this XYZ let's try to modify the CSS class so let's use this fa fa bed this only or maybe some other maybe uh f a f a pencil remove this continue we don't need break point now fa this is not a valid CS uh what we say font some icon let's use some other which we know exists for sure fa fa bad save yes addit is working now if you create a new one uh new one and oh let's add a break point I need to check something if I save it now what I have in model I have zero n Zer new one okay that means we are good all right it is creating so creation so create and update of these amenities this is working this list is going a bit long now we can have uh some what we could say that scroll bar here on this table let's do this quickly on this table we can add a wrapper so I'll say Dave class or maybe let's add add some Style Style here I'll say Max height uh let's allow 75 VH vertical height then I'll say overflow y just use scroll so save it and let's see if that is working come here and let's check okay did not came if I refresh this still not I need to stop and restart sometimes hot reload does not work okay manage amenities and we have this cool all right so this screen is fine delete functionality we'll work on on this later but right now we are good with this great or maybe let's work on delete functionality also right now only okay let let's work on that so for this first let's go to entity uh Amity and we are going to add one column here property public bu is deleted is deleted okay and fine save it and let's add the migration for this so add migration add is deleted to Amity right so it's deleted amenities we are okay now uh instead of manually running the migration let's go to our seed service and in this let's uh run all the pending migrations okay so for this what we'll do we'll inject our uh database that means IB context Factory of type application user not application user application DV context context Factory Contex Factory let's use this here so here I'll say using where context equals context Factory create DB context okay now I will check if context dot database dot get pending migrations we could use a sync version or we could use a sync do any if there is any pending migration just run that context. database. migrate all right so it will automatically migrate our database Whenever there are any pending migrations so we don't need to manually run update database from this package manager console or uh command line all right so we have added is deleted to our Amity now let's go to our amenity service here we will create one more or maybe we can what we can do can handle this from the here only or okay it's better to create a separate method the public as sync task and here I'll say delete amenity in a sync and I will get int ID okay and here I'll say same I'll get the context sorry so context then I'll simply say context do amenities dot first. default async and this should be a do ID equals equals this ID where amenity we will check if this semity is not null we will say context dot amenities dot okay no we are not removing it we are soft deleting it so we'll say Amity dot is deleted uh okay we need to AIT it a wait so Amity do is deleted equals true so we need to add as tracking because because we are tracking the changes for this the changes is deleted and then we'll say a wait context. save changes asnc and the return return type for this let's have method result of Po okay so if it was saved successfully we'll simply say return true or we'll say return false all right let's add this method to our interface and now we can use this so in order to use this okay let's add this flag is deleted flag in this get amenities async because we might need this is list from somewhere else or we will no we just need this list just in for admin only okay we'll see if we need it we'll add that this is deleted flag right now let's have it like this only or or or should we add that condition here let's add that condition here we'll see if we want to RT it we'll check it so a DOT is deleted if this is not deleted then only we will return this get am a sync all right let's go to the component Pages staff admin manage amenities here after this add it let's add a delete uh H delete option as well so how can we approach deletion can we approach deletion maybe this approach this this can work the same way because the form that was throwing exception maybe because we have edit form here I will check it maybe sometime I'll try if we can have one edit form and multiple separate form elements maybe there is some maybe that does not work someone has not tried it but for this one for deletion we or maybe let's do this uh we can add this deletion thing in this form only or let me think or maybe we can follow that approach which uh here is this in this end points for log out right we can follow this approach right yeah let's let's do this all right so what I will do let's create a new folder I'll call it end points and I'm going to add a new class file in this we'll [Music] say end points only what should I call it end points and here I can say public static uh High endpoint route Builder we will say map Uh custom end points something like this I don't know maybe we will change this name later but right now let's leave it like this only return return Builder and here what we we can do we can say staff add domain group and here we could say builder. map group and here we will say staff admin we'll just have this thing and on this we will say this requires authorization authorization policy authorization data policy name configured policy require okay require authorization and after this what we can do because this staff ad we want only with staff and admin right nothing else so here what were all those so we had policy I authorized data policy names and then we have this action delegate authorization policy Builder so we say all policy Builder let's see what we can have here Au policy Builder dot require role H and we can Define roles here so the roles we need Ro type Ro type dot R type. admin. twring and Ro type do staff dot TW string all right so because this is a single line we can make it expression body like this all right now here let's define staff admin group dot map post or map get ideally it should be post but because we do not have form so maybe we can have form okay let's do this map post and here we'll say staff admin after that we'll say uh what was that manage and amenities this then we'll say delete and then we will have the ID here we could say Amity ID like this and this will be of type iner all right now we can Define our Handler here so I'll say sync and I will inject uh we need to inject our service right I amenity service Amity service okay Amity service integer here we will say of fit Amun service dot delete Amun asnc and Amity ID okay we need to use this in Amity ID and it will be deleted from here then what we can do we can simply redirect to this current URL only right so how we are getting current URL in that or we know that we are deleting this manage Amun right so we can directly navigate to this here we will say typed results. locally redirect and here we'll say this slash St admin slash manage amenties let's try it out and let's see if it works return type result. locally redirect let's try it out if it if it works or but before that we need to map this map custom endpoints so we'll go to program.cs and before app. run we'll say app do map custom endpoints okay okay let's go to manage amenities and here after this anchor tag we will create a form okay method post okay and action it will be uh what is it this URL slash delete and then slash at theate a. ID and then here we are going to have button type submit class BTN BTN SM BTN danger and text we'll use delete let's see if it works uh maybe we might have some different approach but right now I cannot think of any other approach so maybe I'll try to think of something later or if if you know any other approach we can do this please do let me know in the comment so that other can also think in that way or maybe we can have an healthy discussion related to this all right we have it here let's check in header how we are handling that form there so shared header and we have return URL button type submit log out action method post that's all same thing we are doing here right all right let's try it out if we are able to delete the amenties I'm running it it will first run that migration and then it will load up okay application is here and again we have this okay add it delete addit delete and I want to delete ABCD updated ABCD and that got deleted cool we have that message for a short time because we have streaming rendering true right that's why we see that message we can fix this if we want or we can leave it like this only so things are working cool and this is a complete page refresh and it will be like this only the reason [Music] is okay maybe we can leave it like this reason is that form is posting form is not posting to this bler component that is posting some other uh page which is that end point but we are good I think cool so we have at least this functionality let's fix these buttons we need these buttons Side by side so we have two approaches maybe we can have these both of these buttons in two separate columns we have a lot of space on this so we can have these into different columns so here I'll add one more column in the header then here I let this pulse Spen six and then I will move this to a separate TD all right so add it delete create and list all that is working fine save and we are good cool so I think we are good with this let's see one more time we whenever we just modify just the HTML template the hard reload does not work okay it came here and we still have the same thing let's check what is happening here how come these things are here that that means it has the authorization authorized view is fine but somehow it is not able to get the name of the user so if we go to header in here let's do this context. user I just want to check so I'll add a block here where I'll say context. user dot claims dot select C do type c. type equals C do value I just want to see what all values we have here the string dot join envirment do new line comma this thing label and this this all right save it I want to see what are claims and values we have right now so that at least we can see what is happening so we have all these columns we have name identifier we have name email address role it means we don't have additional claims which we added right all other claims are there name email address security stamp and roll okay now at least we have something I'll try to read about it research about it and if you guys know something about it do let me know in the comment so that I can maybe learn something new because I have no idea what is happening here the additional claims we have added those somehow we could say got expired or got removed from the sttp context if we run the app or maybe after some time but these claims the basic claims these are still there that that's why we see that log out button but we cannot see the name of the user right we can have some work around for this maybe if this is not there we have user ID so we can simply get these details and then maybe we can refresh kind of thing we can refresh these claims we can add those additional claims again something like this I don't know maybe we can you can try that but we'll do that at the very end not right now right now we'll just focus on the functionality which we are working so we have this after that this also let let's add a uh HR tag after this table so after table or maybe after this entire day we'll have an HR and I want to add a style here and I'll say height is 5X save it let's see and because that this is HTML change it is not going to pick it up okay we can remove this thing now we know what the issue is but how to solve it we have a work around but how to actually solve it I have no idea so I will check it later let's go to header and command this label out let's run it one more time so we have finalized our manage amenity section let's log out login admin manage amenities and we have this line we have saved this we can edit fa WiFi we should be able to have some no we okay so after Wi-Fi let's again do this bad I will say uh f a f a bad save it Amity with the same name already exist yeah that is also a problem if we have that Amin as deleted so when we are checking it we should skip the is deleted check right so because we are uh dealing with IDs we will be mapping room type with amenity ID not the name so we'll go to our service amenity service and here save Amity and now if this is this and not a do is deleted we need to add this condition same thing here all right save it rerun and let's try to create it again okay it's here manage amenities bad fa fa bad and we can see this bad with this icon and everything is fine we can edit it or we can delete it cool again add bed f f a bed saved great so manage amenities we are good cool now we can start working on other items let me think what next we can work on let's just clean this I'm going to close all these app all these tabs okay so let's start working on manage rooms which is manage room types we could say we'll work on that for that we have this room type entity we will create a dto a slim model from this room type we don't need all of these properties to create a new room type okay so in models let's create a new class and let's say room create create D something like this or room create model okay and for this let's copy the room type properties we'll see what we can do in this uh these navigation property we don't need these navigation properties because these this room create model this is not a part of any itty framework core EF core this is not an entity this is just a model which we are going to use on our Blazer page to create the entity uh sorry create the room type okay and added by we don't need this added on we don't need this these we will handle from our backend side last updated on last updated why these are going to be used when we we will create when we'll work on addit the room type okay then what we have now ID image price description maximum adults allowed maximum children allowed and is active so I guess we are good with these data anotation we already have required max length unic Code false there is no point of having uni code here this is from Entity framework code only so we can skip this then price we are okay with this or maybe we can use the new data annotation we got in net 8 we could say denied values and here we can say zero so zero is denied or maybe let's go with range only because we don't want to allow uh negative values all like this is fine price range one to max value then we have description maximum adults Max children okay I think we are good for these also we can Define the range we could say start from one and maybe Max I don't know be 10 Max children it can range from zero because maybe we are not allowing any children any child in this room type category and maybe 0 to 10 only let's have 10 all right so I think we are good with this model let's clean this up okay mhm [Music] all right now this image for this image what we should do uh we will allow we will we want image upload functionality H I have not tried if we could use the iPhone file here I don't know I have not tried it with blazer SSR so let's try it in the previous video in which we created that complete fullstack blog application in that we uh used interactive server component for this maybe for this also we might want image preview functionality if we want preview functionality then we cannot use SSR we would need interaction so we need to make this component as interactive component so Interactive server in this case Okay so maybe let's use interactive server only then we can leave it like this and then we can upload the image and then use that image URL here okay let's go with this approach only now let's go to our Pages or maybe before Pages let's go to services and let's create a room type service room type service okay we already have one room service let's remove this okay so room type service in this first we will inject uh idb context Factory of type application DB context context Factory all right let's create a method public asnc task method result of uh maybe Boolean uh maybe let's return the ID we'll see what what we need to return from here okay so method result of guid and let's say create room type as sync and it will get create room or what was that that room create model room create model model all right and we will need user ID as well who is performing this operation okay all right now here first we will get our DB context so using word context text factory. create DV context now here uh we can uh check maybe room name what I mean room type category if we are adding duplicate category then it should not allow us to create that right there is no point of having two room type of room categories of the same name so here we will say if a wa context dot room types Dot any a sync rt. name uh we don't have name in this we should have name right room type room type ID image price description added on oh we missed and what we have in room we have ID room type ID room number is available yes so in room type we should have name as well so public string name and we will have same thing required max length 100 this is fine and uni Code false tool so room type and same thing we'll add to our room create model and we'll just remove this unic code string name okay so let's add the uh migration because we added this new anded new property to this room type so this should be added as a column to this table so we'll say add migration add name to room type room type build failed because we are still working on that room type service let's comment this out for now so that this migration gets added build started build succeeded and it will add this add column name into room types whereare 100 and we are fine okay now it will automatically run when this seed service runs when we start our app it will automatically update the database so we are good on that part all right so let's uncommanded do name if we have any room type with the same name we should not allow it to create right so from here we will return return uh string we will say uh room type with the same name we can provide the name if we want the model do name already exist okay method result string it would be error message fine so it will return failed this thing cool if that's not the case we will continue and then we will generate our entity from this model okay we can have these mappings using some maybe third party Auto mapper or something like that or we can create our own mapper or we can directly use here inline so I'm going to use inline here I'll say where room type equals I'll say new room type this and then we'll start adding the properties name is model. name added by user ID add it on it would be datetime do now then come 7 we'll see description then image model. image after that isactive model. isactive then Max adults Max children then price added by user this is navigation property amenities and navigation property ID it will be autogenerated last up updated by we don't need this because we are creating we are not modifying it last updated on same we are creating not updating rooms this is again a navigation property so I think we are good with this we just need this these amenities okay so what we'll do room type this is fine we'll simply add this and now for this we need to have a list of amenities as well in this room create model so here I'll say public I en numerable amenity ID name icon is deleted we don't need all these we can just get ID right when we are creating we can just get ID so I'm going to get a list of uh integer okay so on the UI we will show maybe list of checkboxes and staff and admin can check all those check boxes which allows no not just check boxes because we need unit as well right so if you go to room type amenity here we have unit so we would need unit and Amity ID these two things all right so for this what we can do we can create one more model public class and we will say room type or let's say create room type Amity model and here we will have int ID and int unit which is nullable because this is nullable in our run type amenity okay okay so in our create room type model room create model oh my God these namings room create model but it should be room type create model so here it should be room type create amenity model or room type amenity create model I know I I'm not good with these names sometimes I'm pretty good with these names but right now my mind is not working so I'm just uh throwing whatever comes to my mind at this particular moment okay so our room type create model this is going to have a list of or we could use array of these we'll say amenities amenities like this and we'll have a empty array as default value for this all right let's rename this file as well so this should be like this and let's this room type Amity create model in here only we could send it to this or maybe we can create it as an Ned class because it it belongs to this only all right now what we'll do uh room type service it should be this okay now we have room type so first we'll create a room type here we will say word uh no no no no we'll say a wait context. room type. add asnc room type okay then we we will say a fit context or save changes INC now this room type got added and now in this room type. ID we would have the actual ID there is one more other approach as well to get this ID before saving changes so in that case we need to create a proxy object of this room type when we are creating this room type we need to create a proxy we need to add one uh I think new package in EF C this is maybe this is directly included I don't remember I used it with the EF core I guess 3.1 in the past so we can create that proxy it kind of creates a temporary object and then we can directly use that ID before saving changes and then it will save all these changes but right now I'm just uh preferring simplicity so let's go with this approach now we have save change after this we will check if this for this room type so model dot amenties if we have provided any Amity if this length is greater than zero now we need to add these amenities as well for this what we can do we can say model do amenities dot select we can create a list of amenities which we can save where we'll say room type amenities object here we'll say model. amenities do select new we need room type amenity this entity type okay so for this entity we need amenity ID which we don't have this will be autogenerated sorry no no no no not autogenerated this has a. ID it will come from this amenity which we are creating here after that we have room type ID this we can get from this room type object which we just added to the database so we will have room type. ID pay attention this room type. ID we cannot access it before this line 39 because when we added this when we called the save changes as sync that at this time it created this room type into the database and it generated the ID and returned it it and set it to this room type object so we can access this ID after this line all right then we will have our unit a do unit now we have all these uh items okay now we could say a wait context dot room Type amenities. A range async we are adding multiple items right we are good and I have not added two list or two array to this because I know that this is this room type Amity I'm not going to use it more than once if there is any case if you want to use some I numerable or I variable more than once it's always a good idea idea to materialize it so that this thing does not uh execute multiple times right what I mean is if if I could have maybe maybe I have said this room type do count something like this now what would happen if I say total amenity something like this now what would happen when I call this count it is actually going to create and let's say if this Amil has five amities added so what it will do it will create these five objects after that when I'm adding it here I'm using it again at that time it will again create five different objects because it is going to evaluate this select execute this statement these statements twice because we have not materialized it we have not added maybe two list or two array or like something like this right so so right now I am sure that I'm not going to use it multiple times so we are good with this okay we added this using add range async then we could say context. save change async and we are good we have added our amenities as well okay and after that we can simply return room type. id id is room type. ID short okay so it should return short not gu ID room type create model we have short ID right okay so in here we don't need this ID because we are creating at creation time we don't have IDE all right so I think we are good with our save uh create method basically okay okay okay let's extract interface from this service add to current file we'll keep on adding other methods as well when we'll reach to those places we'll need one for add it we'll need one for to list down the room types and all these stuff we'll do this we have this create room typ sync user ID all right let's register this to our dependency container so we'll go to program.cs and we have our services here so we'll say add transient I Room type service we'll add room type Service as implementation and we are good now we can create room type now okay all right let's go to uh components Pages staff admin here I'm going to create a new razor component and I'm going to call it let's say save room time okay I named it save room time because we are going to use the same component for editing an existing uh room type category later right so we'll use the same component only first thing let's add the route so page we'll say let's say manage room types Slash new okay all right now we will make this page as interactive should we make it interactive that's the question let's first start without making it interactive let's try so here first we will need our model so I'm going to say private room type create model model equals new and here I'm going to create an edit form but before that I'm going to create a DA class container container and then I'll have H1 I'll say create a new room type or create room type create room type and then HR and then we we'll use our edit form on this edit form first we'll have our model which is this model after that uh we will use enhance form for this so let's add enhance then we'll use form name let's say create room type the name is up to you you can name it whatever you want this is just to tell blazer for static server side render pages that this data is belongs we are currently uh posting this model so you should call the method which we defined on this form name so what I mean is this on valid submit we will say save room type is thing it should need to know that it need to know that which method it should call so here we will say private sync task save room type A sync all right inside this first we'll add our data annotation validator because we want validations here all right after this now this room type model because we are using SS on this we need to change this to property so we use this model like this and then we will add Supply parameter from form so that it can be used with form so that we can post the form and it can get the values from for this form from the form which got posted to the server all right now let's add all the properties room type model where is that room type create model we have these properties so let's add these here we will start adding one by one so name image it will be maybe on right or okay because we are not using SS uh because we are not using interactivity right now so we will not be able to see the preview so we can use it like this let's create this form as two column layout so here we'll say div class row and then D class call sm6 and then we'll use the class mb3 margin bottom three then we'll have our label with class uh form label and then name after that we'll use our input text with bind value as model do name and class form control and placeholder placeholder as room type name and then we'll use our validation message validation message for model. M with class text denture all right so we have our name ready then we can copy this and let's add we will modify this later but let's right now let's have these like this only image we will have input file model do image and we have one problem okay let's see in model. image the problem is this image right now it is string but this should not be string this should be of type iPhone 5 or should we use okay let's try to see how this works so for this string image let's create one more property of type iPhone file and here I'll say image file okay and I'll remove required from the first image we will generate this before sending or maybe in service okay so this this should be image file image file let's see if this works I never tried this iPhone file with blazer SSR so I just want to see if it works all right after that name image we have price description and this so price and description it will be a long text so we can use text area for this but price is simple Max adults and Max children these are also integer values so I I'm just thinking how I should have the so maybe price Max adult and Max children we could have these in the left side and then description on the right side okay okay so let's do this call sm6 then mb3 in this I will use first I'll use price it is going to be input number model do price model do price and then I'm going to copy this call mb3 two more times first for Max adults and then Max children okay then in the second uh column div class call sm6 I'll use Dave class mb3 and in here I am going to use uh first we'll have our label label with description then the validation message for description but in instead of input number input text we will use use input text area bind value model do description description and we can Define rows default rows uh let's say five all right now we have added all this now we have is active and then we have our amenties okay so first let's use isactive flag then we'll see how what we can do for amenities so for isactive or to think about how to L 12 how to handle the list of amenities here because these values these are not simple single values right we need to have one check box and then one unit [Music] right and we are not handling this right for wifi okay so first let's have a list of amenities here so private amenity amenities and then we'll override on initialized async and we will inject our uh Amity service let's see in amuni service what we are having Amun service get amuni ASN for this one we just need active only right oh get Amity I think we have this all right we'll insert inject this I Amun service amenity service and we'll get all the amenities in here so here we'll say underscore amenities of weight amenity service dot get amenities I think H now we have this list of amenities we need to look through this underscore amenity and then we need to have some data type here which would allow us to have two different set of data one check box to enable or disable that particular amenity and then second the unit value for this I need to think about it let me think so uh let's create uh model here so I'll say private class and let's say amenity selection model something like this and in here we are going to have couple of properties ID which is Amity id id then name name because we want to display theity name then one Boolean which would tell us that if this is checked or not this particular amenity is selected or not and then that unit all right so this collection of amenity let's change this to this color amenities and now we will patch these amenities and then we'll generate this Amity selection model so underscore amenities equals this amities do select okay then new let's create a uh Constructor to make our life easier so here here I'll say in ID string name Bol is checked and nullable in unit okay and let's set these values here so here I will say Amity ID and name and is checked and unit this should be ID name is check and unit all right so now we can say here new Amun selection model and then we can Define a. ID a DOT a is Amun Amity service a do ID then comes name so a do name and intelligence is not working I don't know why it is not working then is checked right now there is nothing uh selected so we will make it false right now we'll get the actual value when we will uh work on the addit room type functionality right now we are just creating a room type so initially there is no amenity selected for this particular room type so we will have it as false then comes unit which will be null by default value is null all right now we have underscore amenities with all these so this for each now here what we can have we can simply have uh let's say on this D we will have display flex and justify content evenly all right now let's have a div wrapper for one Amity and then we will have a label and we will have input check boox okay and for this we will bind value with a do is check like this then we will display the name a do name and then we will have a input number at theate bind value it would be at theate a DOT uh not at a do unit right yes then let's have a class form control SM and let's have a placeholder uh unit value I don't like this unit name makes sense it should be something like value or I don't know do let me know the comment what should be the correct name for this or this unit is fine all right so now we have this save let's try to run it and we will see okay now we have a problem we have a problem here uh this am selection model this is a different model we missing this here do two array H now the problem is when we will click C on save button submit button which we have not added yet let's remove this thing and let's add the submit button this will class Row in here we will say Dave class save call SM 36 and here I'll say da class display grade and then button type submit class BTN BTN primary and then we will say save save everything and let's see how it looks it's here login login manage uh we have not added any link right to open this page okay we'll add this but right now let's use this URL directly so here we will say this and we have this WiFi and back uh let's add couple of other amenities as well I don't know if have a lifted something now and what else we can have maybe water supply no you say Geer this now okay now we have four amenities so we'll go back we have these four so first thing let's this save it looks ugly okay let's try to work on this styling first a bit so let me Zoom it all right then we are here instead of space I don't know maybe start and or we have what other classes we have oh we can use between yeah this looks fine but the problem is if we will have two amenities then these will be on very left and very right but we are okay we'll see that then we come here this input and okay form control SM we are missing the actual form control class then we will have this isue which says H so that means on this instead of display Flex let's use display grid okay and then we'll work then we can uh have these things maybe four or four in a row then we can have this or would be able to H or we call ASM let's use three and then we can directly have this uh unit value without any issue or maybe this also looks fine if we move it to the botom yeah let's do these two things justify content between and on the input type numbers let's add form control s oh sorry form control okay so we will come here say between and then on these input numbers we'll say form control and then P control s all right then comes okay this is so it should be called and space all right now what I was saying then when we click on this submit button it will going to submit this form so it will submit only this model not this section right so what we can try maybe we can add this Amun selection model as a property on our main model then when we'll submit the form it will actually submit these values as well okay so let's try to do this we'll go to our room create model here we have this room type Amity create model which is the final value when we are saving it then let's cut this Amity selection model from here and we'll add it here make it public okay and then use this as a property here so here we'll say Amity selections something like this we might not need this first one now in that case right because we can get ID and unit from here only Amity ID and unit okay we'll see see we might we may remove this amenities but right now let's use this so amenity selections uh stop [Music] it we'll go back and here now we don't need this and then we don't have this underscore Amun what we will do we will uh model do amenities equals this and this Amity selection model now this is a subass on this room type create model so room type create model dot Amity selection model not amuni Amity selections all right and then on this this thing this for each we will use model do amenity selection now we need to check okay we need to have both of these two things the reason being this thing we am selection models array we need to display it on the U it should have all the amenities available right we might check and check from it and this amen this first one it will have only the selected ones only the checked ones okay we need both of these this one is just to display and get the user input and the second one this one this Amin room type Amity create model this is uh by which we are going to save the data Android database all right save and we'll come back and let's try it out that when we will come to the same room type asnc do we have this Amity selections or not okay so let's run it it's here manage room types we have these now let's have some dummy Valu I'm selecting Wi-Fi not providing value selecting bad providing value two not selecting lift providing value uh let's say three gazer no change okay so let's see what we got and let's add description as well when I hit save it came here it is saying object reference not set to an instance of an object and why so model. imunity selections it has default value as blank array and now why it is saying this let's add a break point here as well continue [Music] continue it came here and we are good with this we have Amity selections continue it will display and Wifi bed LIF and then save we came here on initial okay this time this is working on uh server and this time it is not picking up the values so let's see what happened uh Network this time we need to continue and we'll check why it is not getting these values all right network if I do this continue and same thing save when I hit save we have this fetch request payload and if you check payload the reason is it is using a do is check a do unit the name is a dot but it should be model dot uh that m Community selection then indexing on that so this is being a bit uh what we say complex so what we can do instead of doing all these These are admin pages so these are going to be behind the authentication so we are good if we are we use uh interactivity on this page instead of using SSR we could use interactive server render mode on this that will make our life easier in this particular case so let's use interactive server then what it will do it will not post this so we can remove this thing save room type it will only run once and now we will have uh that actual selection in save room type async right let's try it out now there is no need to submit this using it will not submit uh now this enhance it will not have any effect form name it will not have any effect so we can remove these two things because these two are only for static server at rendering that is SSR Blazer SSR that's the reason that in of posting the complete form it will do a fatch request but when we are in interactivity mode then it is not going to submit the complete form in any way so we can remove these two things all right now let's try it out run it and here is it manage room types continue oh you saw it came twice the reason is uh because this is interactive component we have not defined any pre-rendering true or false by default is presenting true so first it uh that on initialization it ran on server then second time it ran on client so that's why and we can fix it we have two way either we can disable pre- rendering and for this particular case we can easily disable pre- rendering because there is no point of having pre- rendering because we don't want any SEO support or anything on this then second approach would be we can use the purchas component state so for this I already created a dedicated video in which which I showed the uh all the details how can we Implement component uh purchas component State application state to persist the data on server side when pre-rendering is enabled and when the control comes to the client it will easily use that uh that cast value on the server so if you want to check out I'll drop the link in description all right now whatever we will do we will easily access that WiFi bed this three and on this nothing now if I H save it came here and if we inspect model now model is fine this amenity selections we have these four the first each check is true Wi-Fi unit is null this is fine for second one this uh name is bad value is two this is true so we can access this then third one lift we have value but each checked is false so we are not going to use this value when we'll save it we will not use this value then comes the fourth one Geer for this also is checked false so we will simply skip this value so whatever uh Amity selection model has this now we don't need to have this as a property on Amity selection now right so that means we can stop this because now we are not posting this selections with the model so we can simply cut this sity selection model from here and we'll move back to our component here we are going to have it make it private and we can remove this then we will use this same thing underscore Amity selection model underscore amenities and then we are going to use this underscore amenities here like this and here also we will use underscore all right okay cool now we have save room typeing we came here now we will set the model do aminities and this should be prore aminities we will get all the selections where is checked is true from here we will select new room type create model do room type Amity create model and here okay let's have a Constructor here as well so here I'll use in ID the label int unit and I'll add these values ID and unit to ID and unit okay then from here we can set a do id id Amity ID and a do un like this dot to and now we should be good yes now we have filled model do amenities with only the checked values all right now we can save the amenity uh yes save this room type now we can save this so let's inject inject I Room type service room type service and then using this room type service okay before this let's uh set the pre-rendering to F to new interactive server render mode pre render PS all right then in here we can directly use it we'll say a room type service dot what was create room type is sync and we can pass a model and we have some error and error is we need to provide user ID okay user ID so we need to get user ID and this is interactive server rendered page so we can inject authentication State provider here authentication State provider let's say Au State provider and from this state provider we can get a user ID so we would say word of State equals of all state provider do get authentication status Inc and from this we can say auate do user dot we can get the user ID from this for user ID we know the claim type it uses claim types do name identifier this is the unique ID user ID in our to to Value were uh user ID okay now this could be nullable do we have any other properties on o State o state DOT we have user dot can we access identity yes so is user nullable do user this is notable dot identity this is the LA dot is authenticated so we can check this if user do identity do is authenticated is false or null so what we will say false or we can say if identity is null or o state do user oate do user do identity and intelligence again stopped working identity thought is authenticated false continue we will uh what we'll do we will return user to login page and how can we do this uh how are we doing this from login H sorry log out page we have a form we are posting the form and the form we are posting to Identity component end points we are posting that form to this log out where we have these two sections so signin manager. sign out asnc and then we have locally redirect to this slash return URL okay and our login page what is the URL for a login page sl/ login or we can use this approach so from register page we will have a link to login page this one let's use this suppo this return URL return url url what is this return URL it should be the current URL okay so here what we'll do we will inject navigation manager inject navigation manager we'll call it navigation manager only and then in here it means user is not logged in what we'll do we'll say navigation manager let's paste this navigation manager. getet URI with query parameters return URL this should be this current URL only so that means navigation manager dot urri which is the current okay so this is the UR which we want to navigate to ur this okay now we will use our navigation manager navigation manager do navigate to this navigate to URL or we could say login page something like this we'll do this and we'll simply return from here all right if that's not the case that means user is logged in we are good to go and we can save it now here we know that this is not going to be new so we can add this exclamation sign that mean n forgiving operator that you don't need to worry about this it will never be n so we can directly access value so now we have user ID as well we can pass this user ID create room Miss sync method results short it will return return newly created room ID okay where we would say word new room type ID equals this if this new room typee ID not new room type ID it would be method result if result do it success then simply return to manage rooms so here we would say navigation manager dot navigate 2 and we will navigate user to manage [Music] manage what is the URL let's check our layout so layout main layout inner page [Music] layout we have that in head so shared header and and for manage rooms or manage amenities we should have manage rooms and here only we can have this manage room types actually instead of booking this should be staff admin manage Amun same we will use staff admin manage rooms do we have room type and room pag is different let's have room types only from room types we will because rooms just have numbers and ID of this room type ID the rooms are associated with the room type so we can use the manage room types only and from there we can manage rooms so the name let's have it manage rooms only but the actual logic and actual things those are going to be for room types okay so manage rooms or maybe we'll see if we uh need dedicated separate pages then we'll see later so let's have it manage rooms or maybe manage room types let's use this URL here we will redirect to this page we'll simply return from here all right if that's not the case that means the saving was not successful we got some error right so for that let's have one piece of State here private string let's say error sorry okay so error message and with default value null of course underscore error message message all right and if we came here then we could set this error message to result dot error message if that is n we will simply have some generic message and which shouldn't be the case but still uh error in Saving Room type something like this all right and we will reset this error method when we are directly entering to save room type is thing so we set it back here all right now let's use this underscore error message in our HTML so on this button we have this Colm 6 let's create one more Colm six and here we can check if uh string do is null or Whit spacecore error message if it is not n or white space then we can simply add one p with text danger and we'll display error message here let's do this let's make this the first column and then button in the second coln all right okay let's try it out to save everything run let's see if it works or no okay it's here log out login [Music] login manage rooms and we have not defined this page this is fine manage room types new we need to fix this also okay if we hit save we have all these save we have some error and what this error is let's see console for more details turn on detailed exceptions by setting this to True detailed errors and if we check in here we have something and that something is DB update exception column does not allow null which column image okay image is also required all right so one thing what we can do we can wrap uh this section create room type in TR catch block try catch exception ex and we can come here and set eh. message all right now it will show that exception but we need to fix that image we'll work on upload image but before that we just want to see if we can save it without any error so what we'll do here we will set model. image [Music] to okay staff admin manage room types let's fix these two things as well so the URL for this page we want this to be like this staff admin manage room types and then new and and let's create this page so in staff admin we'll add a new razor component we'll call it manage room types manage room types and attribute authorized rules staff admin first let's add a page narrative here so we'll say staff admin manage room types and then we'll add this attribute now if you see we are adding this same attribute attribute authorized with this rule staff admin same on manage Amity same we need to add on save room type because all these Pages inside this staff admin folder all these requires have one of these two rules staff or admin so instead of adding this on all these Pages what we can do we can create a new file inside this sta admin folder and that is going to be underscore imports. Riser file okay so it will be only for this folder how import raser works it uh gets applied to its uh containing folder to all the files all the siblings basically we could say siblings and uh children so in for this underscore input this new file which we created this whatever we will add inside this underscore imports. reg it will going to be applied on all of these three pages manage amenities manage room type save room type and whatever other folders We add to this it will be applied to all so let's cut this authorized attribute and let's add it to T authorize and we can remove this from these Pages manage room types we can remove this from here save room type we are not having it here so we are good so manage room types manage room types we have URL we have this thing all right let's try to run it now and let's add the save room type Link in our header as well so manage rooms let's add this URL here and here we'll say add room time save let's run now let's see if it works all right it's here we have these two things manage room types add room types let's add some dummy data to this m one one one one let's say we have lift Wii add this save and it came back to manage room types that means we got it saved let's check in the database stopping it server Explorer or we are not going to use as we with table room types show table data and we have this value this thing and if we check room type amenity here also we should have we have three rules room type room type ID 222 Amity ID 12223 unit 111 so we have successfully saved room type and uh room type amenities all right we are going good actually now next thing we will pull Types on this page or before this let's work on that image image uploading room type then we'll work on this manage room type space and after that we'll work on edit a room type functionality all right I'm going to take a quick break then I'll be back you can also take a quick break pause this video this video after taking a small break all right all right so we are on save room type. Riser page here we should have that upload file this input file okay model. image file now we don't need this iPhone file image file we can remove this okay and what we'll do for this one we will directly say on change and we are going to use this on change which is from Blazer this lowercase on change this is HTML uh on change but we need this on change so on change this and we can name it whatever we want so let's say uh on image uh select or something like this on image select Miss sync okay so what we want to do we want to and we don't need this validation message we want to display the selected image so we want to preview the image before uploading we want to show a preview so for that we will work on this method image select a sync would it create no it will not create so let's create this method I'm going to create it here so private sync task this and this should be input file change event arguments this one okay now we want to preview the image so we can convert this image to base 64 and then we can display this so for this what we'll do we will have one more State variable here private string and we'll say image URL something like this and the default value would be null then we'll set the base 64 image for this underscore image URL and we are allowing only single image so we will work with single image only so how can we use this uh so we'll say using word we'll get the stream from this image so we'll say e do file dot get or open read stream now we have this image stream now we'll create a new memory stream using memory stream Ms equals new memory stream or we can say using YMS equals to new memory stream then we will simply copy this image stream to this memory stream and then we can use this memory stream okay how can we use this we will generate the image URL but before that let's convert it to word base 64 image data image data okay so here what we can use we can say convert dot 2 base 64 string and it takes an by array and we can convert this memory stream to by array using two array method now we have base 64 image data reading okay now we can generate our image URL so we would say image URL equals and for base 64 the format is data column image then type of the image M type then colum uh sorry semicolon then base 64 comma and then the base 64 string which is in here base 64 image data all right now this PNG this could be PNG or jpg or JP eg it could be any image form right so we or maybe webp so we need to get this dynamically okay so the simplest solution could be we could get the extension of the image we'll say path dot get extension and E do file dot name then it return the dot so it will give dot PNG but what we need we need just PNG not DOT so we want to skip the first character so we could say subring from one we can use this or we can use the uh rain syntax that would be from one take all so one is index so it will give us PNG or jpg or whatever it is then we can add this extension here and now we are good we have this underscore image URL which has this base 64 image URL okay now what we will do uh where we have this image upload here inside this Dave class mb3 in here or maybe before this mb3 we will check if this uh string dot is null or whitespace underscore image URL if this is not null or wh space that means we have this image we will set IMG SRC equals this underscore image URL then we need to provide a fixed height and width so that it uh looks good on the UI does not break the UI so here we would say let's say uh we can have I don't know I think IMG fluid this class comes from bootstrap I guess IMG fluid let's check it how it looks okay let's run it okay app is here login login and add room type let's choose a file let me uh generate some images for hotel or maybe we can use any image right now so maybe this one and we can see this okay we can see the preview and if we check the source it would be this you see the image SRC is data IMG image/ jpg base 64 then the base 64 uh representation of this image so this preview functionality is working but this is breaking so we need to work on this as well H let me think what we can do where can we show this image maybe we can have this image section on the right only in the main container uh before all these so that this does not break like this okay let's do this instead of having this where is it in here what we will do on the very top this is H we can have two container uh two columns in the First Column we will have all these form fields and in the second column we can have the image okay do this Dave class row then Dave class call sm6 duplicate this and add this image here after image we will add this image control layer like this and then all of this thing we'll cut it and we'll add it inside this call6 come on paste and this sm6 now what we can do we don't have to use this SM 66 because now all of our okay this should be the second column so what we'll do we'll move this image to the the right column cut this and it again does this and in the First Column we will have all our Fields so no need to add these call sm6 and all these things so let's extract out these inside this call sm6 the top one cut paste then cut this paste and then we can extract these things these button amenities and error message these things we can have outside of these two columns so div class row calls SM 6 calls 6 and then in here we can have calls sm2 for these and then error message and save button all right so let's see it now I'm saving it so looks like this now so image is here let's add some spacing uh for this save button and this uh amenity selection so for this what we can do this amenity selection on this div let's add class mb3 the standard margin we are using for all the fields all right so we have the save we can change the image okay so it is looking fine not that great but okay maybe we can move these uh these uh Amity selection to here right let's move this here in the left column only okay how would it look if we don't have this image Let me refresh it will look like this which is not great but let's be it like this maybe we will try to uh modify this UI later I don't know or maybe we can live with this only all let's do the saving of this image right now we are previewing it so when we are saving the room type then we should save this image as well right so for this we need to have access to this image inside the save room type sync method for this what we can do we can have one more variable and this would be of type browser file because this is the type of this e do file I browser file okay so here we could say image and this is going to be nullable okay so now underscore image and here after displaying it we could say underscore image equals e do file all right so now we have this I browser file we can access this file in here so right before saving the creating uh the room we should save this image here so what I'm going to do I'm going to create a new folder H sorry not new folder new method private async task we'll say save image async like this and we can pass this browser file or maybe we can directly access this here so here first we will check if image or maybe we can check it on the consumer side that means here only what should we do here hm we should we want to save it so first we need to have some path where we are going to save the images so for this we'll go to Triple W root folder and here we are going to create a new folder for images or maybe we can uh create this folder dynamically if we want let's create dynamically only so we want to access this triple W root folder and for this we need to get the web root path and that we can get from [Music] inject uh I web host environment web host environment from this web host environment we can access the web root path so this web root path this is the triple W root folder okay all right so first thing we need to generate a dynamic name for this file so let's use gu ID for this so here we could say uh name and we could say uh room type IMG hph and then we can say guid do new guid but then we need extension so for extension we can do the same thing we could get the extension from path dot get extension image Dot name it will give us dot that period so we can directly use it like this okay so now we have this new file name which we are going to save this save with this name now what we need to do first we will get we will generate the folder path where we are going to save this image so for fold path we can use path do combine we need to get to this uh trip W root folder web host environment. web root path okay then we need to go to images and then let's say room types and then we will save the room Type image inside this folder so we are good with this till this URL we are good now first thing what we'll do we'll say directory do create directory and then we'll provide folder path so what it will do if this folder does not exist it will create first it will create images folder then inside that images folder it will create this types folder okay so we are good now we have our folder path now after this we need to have the complete file path so here we'll say full file path for this we could say path. combine folder path and then this name of the file or let's call it image name so it makes more sense image name image name now we have this full file path now we can save this file path how can we do this we can simply say a wait using we can create a file stream FS equals new file stream and we can use the Constructor path and file mode so path this is going to be full file path and then the file mode we will use create we want to create this new file okay now we have this file stream what we need to do we need to copy the this image which we got inside this underscore image we need to copy this image to this file string okay so for this what we can do we can do the similar approach we were doing here so we have this image string so we'll say using our image stream but this time it would be image. file. open read stream or image is already fil image. open read stream and after that we can simply say image stream image stream dot copy to async and this will be this file stream a wait and we are good we have saved this file to this uh path now saving file it could lead to some unexpected errors so for this what we can do let's WRA this inside a TR catch block to try and if we got exception what we will do we will say we have error message right so here we will say error in Saving image and then we can display the ex. message the actual app here all right so we are good with this save image async H now when we are creating this save room type A sync so here what we will do first we will check ideally we should not check or maybe we should check uh before doing anything we can simply check here if the image is null that means image is missing and we are not allowing it to create room type if the image is missing so from here we could simply set error message to we will say image is required and we will return from here directly now if we came this far then we are sure that image will be there for sure so here we could call that method save image async and now we need to return something from here which we can save with this model. image okay so this model. image what we will do here for this one we will where are we here so what we should do we should return the file name sorry URL because we will display that URL on the UI so we need URL not file path so there is a difference in file path and url url would be what we can add in the browser with the uh forward slashes but for file path we use backward slashes right so slashes are different now here we should we can return two piece of data first H success or let's say status and then second one message okay or maybe we can say URL image URL all right or maybe we can directly return image URL only yes so let's make it stream and a label string so from this one when everything was successful then we will simply return the image URL so we need to get image URL from this image name and these things we need to construct the image URL so how can we construct it we can simply say slash Images slash room types which is this one and slash image name like this and in exception we will return null so we can check there if we got the image name image URL then the operation was successful we can continue if that's not the case we got some error so here let's use word image URL here we will check if image URL is null we will not do anything we will simply return from here because the error message we are already displaying from this save image sync right this error message so we are good and if that's not the case we can set model. image to this image your and then everything will be same as it was before we just added the dynamically generated image URL let's try it out okay I'm running it let's see if it works where is it okay it came uh add room type let's say first room pric is 12200 two adults one child some random description we don't have WiFi we have add one bad and one gazer and if we save it it is saying image is required so let's choose the image we have this image save came back now if we check the image it should be in this images folder images room types and we have this image and we can see this image we have this image and let's navigate to this image in the browser so that we can see this image stop copy the image path then run the app and let's go to this URL and we cannot see it it is saying 404 but we know we have this uh image the reason is our application does not allow direct file serving automatically we need to enable that what that mean is no we have used static files right yes we have used static files so it should should have worked so it was images SL room type SL this right oh I just copied the the name image name I did not use the full path so it should be images then what was that room types slash then this image name yes and we can see this image great so image saving is working this looks great this looks fine that means using this now our uh where is it save room type page for creating a new room type this is completed now the addit functionality we'll work on it later but right now we are good with this all right so next thing we will work on the manage room types page we will pull up the room types here and we'll display the these room types uh all the available room types listing on this page let's first create the method to fetch these room types so for this we will go to our services room type service and in here we need public syn task now on uh that page that manage room types page what do we need we need a small subset of room type entity okay so what we'll do we'll go to our models and let's create a new model so let's say room type list model room type list model so here what I will get uh let's make it uh record public record and here first thing we will will have our ID that is of type short then we will have name then we will have image and then we could have price and I think that's all what we need to display on the the main uh that manage room type page right all right so save this here we would return return an array of this type okay so get room types uh list yeah just use this method this is not making sense get room types for manage page something like this I think okay we don't need paging on this because room types are going to be a finite number fix maybe 5 10 not more than this all right so from here first thing we need to have our uh context so we can simply get it using word context now we have our context so from this context what we can do we can directly return a weight context do room types do select and it would be room type RT so new room type list model ID which would be rt. ID rt. name rt. image rt. price and then to array I syn and we are good with this let's break it to multiple lines is happening okay so now we have this method ready let's add this to our interface all right now let's inject this and use this on our manage room types page the first thing we'll inject our room type service room type service then we will have uh private uh room type list model and here we will say room types with the default value as blank array then we will override on initialized sync method and we will fill these room types from our service underscore room types equals here we can say a wait a wait room type service do get room types for manage P all right now we have the list of rooms we can come here [Music] and wrapping everything in container yes so on this page now what we will do we will simply add a DA class container Dave class container then we'll have our H1 which will be manage room types okay on this page we can have a link to the create new room type page so instead of this directly what I will do here I will have a d class and let's have it as display flex and justify content between first I will have this H1 and then I'm going to have a nav link with HF with which will be this Slash new then let's add couple of classes BTN BTN SM BTN primary here we will say add new room type all right after this we will have one HR tag cool now we can have this listing so what I am going to do instead of displaying a table what I will do here I'll have a uh this row and then I'll have simple columns what I mean is first I will have a d class row then first thing let's check if we have any room type room types. length if this is equals z then we can simply say there is no Rome type created yet and then in the else case we will have uh one for each Loop so here I'll say RT which is room type room types and then I will simply use div class call sm3 mhm and in this we can display are room types so let's create a card here card this card class comes from bootstrap and then we can have Dave class [Music] card body and inside this card body first thing we can have our image IMG SRC equals this would be rt. image class IMG fluid all right after this I am going to have card putter okay so on this card footer uh let's have a display flex and justify content between then I'll display the name so let's have it something like H4 and here we'll say rt. name and then on the right side let's have one more H4 and here we'll display the price RT do price do string with our currency format all right so this is actually we could say per night all right okay let's try it out let's see how it looks so run it it's here login [Music] login manage rooms and we have these rooms and it looks uh bad it does not look good all right so what we can do sorry H4 is very big and one thing this this subscribe newsletter we don't need this on this admin pages right it is not making any sense let's remove this from admin Pages we'll do this but before that let's try to fix this design and this is okay this is the first one which we checked when we did not have that image upload functionality all right so first thing we'll do we will make this H4 to small maybe let's see how the last H6 looks H6 is fine so maybe we can move this header to the this room name to the top as card header and then we can have this price in card footer only and yeah we need added link as well so we'll have that added Link in head okay let let's try it out the first thing let's make it H6 instead of H4 we'll do H6 then we'll add card header as well P Plus Card header and we'll do the same thing disli flex and justify content Center for this as well justify content Center and in here we are going to have name and edit link so name is fine and then we will have added link so we cannot use nav link because we need to generate Dynamic link this addit link something like we would say add link equals this would be the staff admin manage room types and slash then we'll have rt do ID and then add it something like this so here we will have oh we can use nav link with h with this addit link class BTN BTN SM BTN default and then inside this we'll use one uh font or some item fa a fa a what was that pencil or edit edit right fa edit I'm not in touch with this font or some from a long time I have used font orome for very long time actually all right do let me know in the comment if you also used font orome for icons I have used this I think from 2015 or 2016 till around 20120 okay have this edit link we have name then we have price per night now we can remove this display flags and this thing all right okay let's see it how it looks now is it any better so it should be on the very left it should be on the very right but it is not that means we missed some class or something card header deflex just defy content oh Center it should be between between all right now it is on the top it is in the center so let's move both of these to Center and remove the additional margin I think this H4 or H6 all these have some margin margin bottom this oh this is on H5 margin bottom if I remove this it will get it from somewhere else okay we'll use margin zero and this add new room type this is also looking weird right and this H1 manage room type this is also kind of uh we should have some spacing in here as well okay let's fix all these things so first thing on this H6 we will say m zero remove all the margins whatever margin we have and then we will have align items Center this is for vertical alignment and same this align item Center we'll do this on the top when where we have this header and this thing align item Center and on this H1 we will say m0 and that heading H1 it would be same for all the pages right so if we go to our layout and on this page what layout we are using p layout interpace layout interpace layout okay we have not defined any layout that means it is using main layout in main layout we have this body so for this and then we have inner P layout where we have this section then looking small then we have this body on Main layout we have this newslet section so what we can do what we can do we can create one more layout because what we need two things we need to add margin between the main Navar main header and this heading and then we want to remove newsletter okay right now this newsletter we have it on Main layout so what we'll do we'll go to layout we'll create one more razor component and we'll say admin layout okay and it should inherit from layout component base and for this page we will have a layout main layout and then we can remove all these things now what we will do we will remove this news letter section from Main layout I'll cut it from here and this body for the inner page layout we need newsletter so whatever inner phas layout is it will be rendered inside this body at theate body so if you go to Inner page layout we can add this newsletter after this body so now it will be at the same place as it was in main layout right now what we have achieved we have moved this from here to interpace layout and now admin layout we are directly inheriting this main layout so here that uh that newsletter component that is not going to be rendered cool now after this we need to have some spacing inside that body so what we can do we can say div class container fluid inside this we will use our body but before that what we will do we will say m y which is margin top and margin bottom we could have it something like M Y3 all right and then we might have let's have a are after the very end so or we don't need this let's see how it looks now this admin layout we will use this admin layout for all the admin Pages all right so one approach is we could add this on this manage amenities manage room type save room type all these Pages or we can directly add this toore input reg because this page is going to be applied in in its parents folder so it parent is Staff admin so it will be applied to all these three pages so here what we will do we will say layout and here we will say admin layout right here we are not adding any layout on manage amities manage room types and save room type so it will automatically get this admin layout so save everything and let's run it and let's see if it fixed all the UI issues okay it came so this is the main and here okay we don't have newsletter oh because this is homepage all right we need to fix this as well because we moved that to from the main layout so that is not here we need to work on this but if you go to any other page we have this subscribed newsletter and we have this spacing okay we'll need to add this on homepage as well we'll do this all right so all these pages are okay now let's go to our uh manage amenity page first we have this and there should be some spacing that means here is is something let's see okay we can at least see the top section and that subscribe newsletter is not here but there is some issue maybe with the template okay and you see manage room types and add room type both of these are selected the reason is if we check the URL for the manage room types URL is still here manage room types and then new we including this new it is for that new add a new room type so by default this nav link matches both of these so that's why both of these are getting selected we'll fix this to fix is simple on this nav link we can set the match property all right then we'll go [Music] to manage rooms and we are okay so let's see why this is overlapping with this so what is this this one is contain FL busy dark wow fading so footer is saying margin top minus 110 PX okay so that's the issue but why they have this like this if we go to here because they wanted to display that subscribe newsletter like this all right you see because they wanted the Subscribe newsletter to be halfway through this uh this footer that that's why so for admin Pages we are not having this subscribe newsletter so for admin Pages we can simply override this footer and we can remove this margin top all right so let's do this I have copied this hoter style I'll go here first thing for the homepage we have two approaches because we have removed that subscribe newslet either we can create one more layout but because that is single page only so we can add that directly because in any way body is the index page homepage so if we will add the Subscribe newsletter at the very end of the body it will be actually here only so at the same place so let's go to homepage first and after teams let's use that newsletter and then for admin we can go to admin layout here we can add a style with this footer like this and this margin top it should be zero and we will override it so save everything let's try it out if it's getting applied okay it came on homepage we have subscribed newsletter fine inner Pages we have newsletter and design is intact then we'll go to manage amenities and this is fine we can see this Gap right and manage rooms we can see this Gap okay so on manage amenties we have this okay this this HR this is part of this manage ability page but we are good we can see this spacing between these this nav menu and this header all right manage rooms it is okay and then manage room type this is also fine and I think we should work on this as well right so for this one let's try some approach if it works but before that let's fix this selection manage rooms and add room type so what we'll do we'll go to our header so it should be in component shared header and here we have this nav link for this new and manage room types all right so here we would say match excuse me all right so for match we will use n link match do prefix and then we have all so default is prefix so what it is checking if this URL if it comes in the main address by main URL it will automatically add active class to this but this is not what we want we want this to all so when the complete URL is this then only apply active class okay so save this and let's see if it work now we can see this it is working right now this add room type is selected only manage rooms is not selected now if you go to manage rooms then manage rooms is selected all right this thing is also working so everything looks fine now all right now let's try to fix this if it fixes so what we can do here we can make it a flex box and we can have an m div with flex one so that the uh that takes the entire available height let's see if we can get that call sm6 this is the first one and this is the second one right it is taking this entire space and that is great for us so on this what if we make it display flex and it changes this so let's do this inside this calls sm6 let's introduce a div so we'll go to our create or save room type page we'll go to this calls sm6 and here we would have add a div on this we would say display flex dlex and inside this we will have image wrapper and on this image wrapper we will have Flex grw one and then this imgsrc we are going to use this inside this image rapper and then this div class mb3 it should be after this we can remove the CSS class we'll see it first let's see how it looks if it is fixing the thing or okay we have something we have display Flex we need to make it Flex column Flex column and the problem is it is not getting the complete height what if we set height 100% and now it is good okay so on this deflex we can set height 100% now what it does it will look like this without selecting any image and if you select image then it should be added here only so it will look better than before all right okay so let's add this height 100% on this display flex and flex column Flex column and style height 100% cool save everything and we should be good now all right so now we are good we can see the uh on manage rooms we can see this so this first case this is actually an exceptional case right now we are not allowing creating room types without adding image so it will not be the case for now let it be like this only we will uh when we'll work on this edit then we'll edit this and add that image or maybe let's work on this right away right because this page is done we don't have to do anything on this page now we will list whatever room types we will add it will be automatically being displayed on this page we have the room type name price image and then we have this edit link so this edit link should open the same save page with uh the details prepopulated all right all right so first thing we need to fetch the details of this room type when we'll be in edit mode okay so for that let's go to room type service and we'll create a method here public async task and the edit model is room type create model so what we should do let's rename this room type create model because now this is not just for creating we are going to use this for saving as uh updating as well so let's rename this to room type save model so room Zoom type save model and then we can add the ID property as well so public short ID all right then let's modify uh rename these as well room type amenity create model so instead of this we'll say room type amenity save model all right okay now let's go to our service room type save model let's continue on this so it will be get room type to edit a SN like this okay and we will get short ID this room type ID here first thing let's sorry let's create our context so using word context equals context factory. Crea context and then we can get a room type so we need to have we need to get room type with these room type amenities now all these details we can easily get from room type directly but for these amenities we have a separate uh entity if we go to a data folder data entities room type amenities which is room type ID amenity ID and unit so we have two approaches so we can actually get context. room type amenities we can directly query this right because from this room type amenities room type Amity we can easily get room type ID Amity ID unit and from this we have navigation property room type we can get room type details as well but if we will use this we'll have one problem and that problem is going to be what if I created a room type and I have not added any Amity to this in that case we will have entry in room type but we will not have any entry in room type amenities and if we will try to edit it it will simply return null so we won't be able to edit it so that means one option is gone now we have only one option and that is we will directly query room types so in this room type we will be having our aminities which is room type ameni so we can easily get amenities from this navigation property all right so context. room types and let's add eager loading so I'm going to include rt. amenities all right then I'm going to apply we condition which will be rt. ID equals idid because I need this room type ID only and then we could use our select so RT equals new room type save model then we can fill all our properties here name rt. name image price description is active then ID and Max adults Max children and then amenities so these amenities how we can access these here we will say because this Amity is of type room type amenity save model but these amenities of are of type room type Amity so here we could add do select RT or let's say Amity that means aals new room type save model dot room type amenity save model model and here we can use ID which will be a. ID a. Amity ID and then Unit A do unit like this and now we on two array and now we are good our room type model is ready then we'll say a first or default aing like this all right and then we'll simply return this room type now it could be null so let's make the return type as nullable and let's add this method to [Music] our uh interface all right saas our service is ready to fetch the room type details to edit but now let's modify our create room type method as well right so instead of create room type we should change this to save room typee async first we'll change it to save room type async after that we will check if we are in edit mode or create mode so here we will check if model. ID if this is equals equals zero that means we are in create mode so we can have this condition okay and what are we returning we're rning room type. ID right all right so let's do this this thing then this thing add a sync till this section I'm going to cut it and I'm going to add it inside this first if condition so we are first checking for the name existence then we are creating room type entity then we adding it to the context after this let's have else condition which is addit uh room type now first thing we need to check if some other room type has the same name so here so here room type any async rt. name but with this we will say rt. ID is not equals to are model. id model. id that means we don't want to check with the same entity with the same room type because this we know that this has the same name all right room type with the same name already exists fine now if that's not the case we will get the room type from database so we'll say DB room type equal a wait context. room type do first. default async and here we would say rt. ID equals equals model. ID now if this DV room type is null that is rare case it should not be like this but if it is then we can simply return the same thing uh the error message would be we could say invalid attempt or invalid request something like this now if this is also not the case that means we got DB room type from database now we need to modify this DB room type from the details of this model okay so let's do this let's copy all these things add these here and uh I will add the B room typee dot all this then I'll set these commands to saving is active Max adults Max children price now this added on and added by because we are in edit mode then these fields does not make sense because this room type has already created these fields will already set so we are not going to modify these two Fields now what we'll do we will use we have last updated by so this will be this user ID and last updated on this will be this date time. now so we will modify these two values all right now we have created this this room type right now we have on application context we are using no tracking query Behavior it will not be tracked so what we can do we can say context do room types do update DB room type or if we do not want to do this we can simply remove this line and when we are querying this context. room type we could say as tracking now it will track the changes for this DB room type and it will automatically add these to DB context change tracker and then this save changes asnc it will automatically get these changes and it will save these changes to the database all right so here we are saving it we are good we need room type. ID so for this let's do this model uh H let's do this let's have this room type here so we'll say room type and then what we'll do we'll generate this inside here and then when we are aditing it so instead of using this DB room type let's use this same room room type and we'll remove this bar it will be actual room type only and this is going to be of course Noel all right so here we can access this room type. ID automattic it will be automatically added all right so now after saving the room type then we'll generate our room type entities and and we are going to add these but before these what we should do what if we already have the uh couple of room type amenities added to our database so one approach could be we can check uh what we already have what we now have so we can check the difference then we can say that these needs to be updated these needs to be inserted these needs to be deleted or we have a s simpler approach what we can do we can simply remove all the amenities for this room type and then we can add those directly okay because this ID the unique ID for room type amenities that is a collection of Amity ID and room type ID so we are good so what I mean is when we are in this addit mode what we will do we will fetch all the amenities room type amenities equals a context do room type amenities do where room type am RTA do room type ID equals equals model. ID okay do to list iing now we have this room type amenities and now we can easily say uh context dot room type amenities dot remove range and then we can remove this room type amenities okay now uh you could say that we could use the bulk delete option from EF code but the problem with that would be uh that does not track the changes and that does not work inside this EF course transaction so what I mean is if I have used that context dot room type amenities dot uh execute delete or execute delete async these things the problem here is so here what I could have done could have done this where and then execute delete this this thing could have done the same thing with these two lines but the only difference is this execute delete this operation executes immediately against the database rather than being deferred until DB contact save changes so it also does not interact with ef course change tracker so what this mean if there is some issue with this save changes Inc then we will be in an inconsistent state so room type amenities would be deleted but room type would not deleted so we will have an unpredictable state that is not what we want in this particular case so that's why we are using this traditional approach so first we are getting all room type amenities then we are removing it and that this remove range this is not directly removing this this is actually adding to the EF course change tracker and when we will call the save changes ring it will run all these operations in a single transaction so we will be good within consistent State all right so here we are good and let's say existing room type amenities let's call this this existing room type amenties and we're removing these and after this is when we came here if we modified anything or we have any amenity we are going to Simply add this so we are good with this approach it will work for create and uh add it for both the cases all right so that me save room type Asing method is done and get room type to addit Asing method is also working let's uh we don't know if this is working or not we just have this logic ready now we'll go to our Pages let's go to our component uh Pages staff admin same room type async we have manage room type async and here we have this ID uh this URL right so let's go to save room type asnc and let's add one more page directive for this thing slash manage room type and this should be we'll have it as ID or maybe room type ID room type ID all right then we can use this room type ID as a parameter here which we will get from the Ur So we will create a public it should be a label in and room type ID and we will Mark is at parameter now this room type ID we need as short and short is not uh allowed as a route constraint so here we will have integer only nullable in let's rename this so room type ID uh let's say raw so room type ID something like this or maybe room type ID uh let's use ra only then we'll have one more computed property which will be of type short let's use the label short and here I will have room type ID this I will check if room type ID had some value or maybe room type ID is greater than zero if this is greater than zero then uh we will try to not room type ID room type ID row we will try to convert this int to this short for this we can try short. tripar room type ID raw. two string outward room type ID okay H so if that's the case let's move it to Second Line so that we can make it readable okay short triers if this is the case if it was able to successfully parse it then we'll simp simply return room type ID this variable which we generated room type ID this one if that's not the case we'll return null and let's wrap this thing inside this parenthesis so that this are uh these falls in the same group then if that's not the case if room type ID was not greater than zero then we'll simply have null for this room type ID now we can use this room type ID to fetch the room type details to edit those all right so save everything now when we are in on initialized async after patching the amenties let's check if this room type ID this has value this is not null then what we can do we can check room type from the database using a wait room type service room type service. getet room type to addit a sync and here we can provide room type id. value now here is a thing we might hit null so if this room type is null n l we want to return from here so for this let's inject our uh navigation man okay we already have navigation manager let's use this navigation manager we'll say navigation manager do navigate to so we'll navigate to staff admin SL manage room types to the previous page and on this we could say or let's not use replace we might get that URL later or yeah let's use this so we'll say replace true because this URL is invalid we don't want this URL to be in our browser history so if you press back it should not come to this page because this page is invalid it has invalid uh room type ID all right then we'll simply return from here we don't want to continue execution all right if that's not the case we have room type that we can add to model we can directly say model equals room type now we have values in this room all right now for this underscore amenties collection for this also so let's get the actual values and this actual values what we can do we have uh values in this thing so amenities do select okay let's follow a longer approach or maybe inside the select only we can do what we can do let's make this a part so we will add some logic in here right now this is doing this thing now what we need to do we need to get this false and null these two things actual values ID name is fine but this false this is if we have this particular Amin in this models amuni collection we will make it true that means it was selected so for this what we can do here we will check if model do amenities do or maybe we can simply get word existing Amun something like this here we will say model do aminities DOT first or default M A do ID equals equals this a do ID okay now if we have this existing amenity that means this was true so this false we will say existing Amity is not null it will be true else it will be false all right then this is the unit value so we will say existing amenity and question mark dot unit now we should have the actual values here let's try it out we'll modify this uh save room type using this method right now it is or should we need do yes we should handle through this image change logic only okay yeah with this if we are in edit mode after setting model to room type we can set image URL equals model. image save let's run it and let's see it in edit mode then we'll work on the save on this page let's see first if it works okay login and this page is broken and why so okay we'll check it what is the issue maybe we have modified that layout and all those that's why it is broken oh okay the these are these Pages login and register pages are also using the same main layout so we need to add newsletter on this also all right so manage rooms if I press edit I have all the details I have first room this price maximum children image and bad is selected with one gizer is selected with one so that means this functionality is working okay okay we need to modify this create room type also it should be addit room type or modify room type or update room type and if you go to add room type it is also working now let's go to manage rooms again and let's check the first one here we have all these first three selected with one one one value and then this gazer without selections that means fetching data on this page this is working and saving should also work directly so let's add this image I am saving the first one let's say updated room type all right and let's make back to two so we'll see that things are getting changed so name image and the am these three things I have changed let's type on Save updated room type this got updated image got updated let's go to edit mode again and we can see bad to that means saving is also done um what if we change this image if we save it image got changed so image is working out of the box but there is only one problem when we Chang this image so right now this particular image this is saved on our physical device physical disk in our folder and if I change this image we are uploading this new image we are saving it and then it will be saved it will be updated in the database but that existing image that previous image that will be in our folder but that image is not not in use anymore so we need to delete that existing image when we are changing the image uh when we are in edit mode so that is one additional step we need to take so delete the existing image and uh modify this heading to update room type these two things let's do this quickly so stop it first thing we will do instead of create room type we will check if room type ID do has value then we'll say addit or update and if that's not the case we'll say create so create room type update room type and after that we need to modify the we need to delete the image from physical path so for this whenever we are selecting any image on image select Asing in here we will have one more state or maybe we can do this instead of having this when we are in save room type A syn we can check where is the image saving here when we are saying save image Asing before this we will check if model. image this is not null or we would say not is null or wh space we can hold this we'll say existing image URL if this is not n white space or maybe we can directly use this we'll say this model. image this is the existing image then after doing everything if we came to this thing result do is Success if we came here we will check if string do is null or whitespace existing image URL if this is not null or wies space that means we have some exis image if we have this we will simply delete this so for this let's move it to a separate method so private void delete image string URL image URL basically all right so first we need to uh generate path the full path for this image URL that we can somehow do this thing so this folder path and this let's come here we'll be here so folder path no folder path it will be having this image URL it will be having images room types and then image name so for this what we can do full file path we could say web host environment web root path then this image URL we need to get the image path word image path so to generate the image URL we use this forward slashes to generate path we will replace forward slash to backward slash so here we would say image URL do replace T this with this we need to use double because we need to escape it all right now we have this image path so we have web root path then image path we are combining these and now we can simply check if file do exists this full file path if this exists then we'll say file. delete and this full file path now there could be some uh there it could throw some exception so let's wrap it inside try catch block and we can simply eat out this exception because it is not uh breaking anything we are just uh this file will not be deleted from the physical storage that's the only issue so we can simply if you want we can log this exception and we are okay to uh skip this exception we don't need to throw it all right let's use this delete image uh here so if we have existing image URL we'll simply say delete image and we'll pass this existing image URL and it shouldn't be prefixed with underscore all right so now we are deleting this image file save everything and now everything is fine our complete flow for ADD and add it should work let's try it for one more time and we'll be good with this okay this is here manage rooms will come here here we will change this image and if we save it it should save it without any issue and that image should have been deleted from the physical storage all right we can check if you want but we are good all right so that means this thing is also working everything is fine so manage room types page and add a new room type page and edit room type these things are working yeah and this heading also got changed now this says update room type and here it says create room type all right so we are good let's see what next we can implement
Info
Channel: Abhay Prince
Views: 6,024
Rating: undefined out of 5
Keywords:
Id: 53O3QUic2OA
Channel Id: undefined
Length: 570min 2sec (34202 seconds)
Published: Sat Jan 06 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.